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 Labels& featureLabels,
00114 const Labels& descriptorLabels,
00115 const Labels& timeLabels,
00116 const size_t pointCount):
00117 featureLabels(featureLabels),
00118 descriptorLabels(descriptorLabels),
00119 timeLabels(timeLabels)
00120 {
00121 features.resize(featureLabels.totalDim(), pointCount);
00122
00123 if(descriptorLabels.totalDim())
00124 descriptors.resize(descriptorLabels.totalDim(), pointCount);
00125 if(timeLabels.totalDim())
00126 times.resize(timeLabels.totalDim(), pointCount);
00127 }
00128
00130 template<typename T>
00131 PointMatcher<T>::DataPoints::DataPoints(const Matrix& features, const Labels& featureLabels):
00132 features(features),
00133 featureLabels(featureLabels)
00134 {}
00135
00137 template<typename T>
00138 PointMatcher<T>::DataPoints::DataPoints(const Matrix& features, const Labels& featureLabels, const Matrix& descriptors, const Labels& descriptorLabels):
00139 features(features),
00140 featureLabels(featureLabels),
00141 descriptors(descriptors),
00142 descriptorLabels(descriptorLabels)
00143 {}
00144
00146 template<typename T>
00147 PointMatcher<T>::DataPoints::DataPoints(const Matrix& features, const Labels& featureLabels, const Matrix& descriptors, const Labels& descriptorLabels, const Int64Matrix& times, const Labels& timeLabels):
00148 features(features),
00149 featureLabels(featureLabels),
00150 descriptors(descriptors),
00151 descriptorLabels(descriptorLabels),
00152 times(times),
00153 timeLabels(timeLabels)
00154 {}
00155
00157 template<typename T>
00158 unsigned PointMatcher<T>::DataPoints::getNbPoints() const
00159 {
00160 return features.cols();
00161 }
00162
00164 template<typename T>
00165 unsigned PointMatcher<T>::DataPoints::getEuclideanDim() const
00166 {
00167 return (features.rows() - 1);
00168 }
00169
00171 template<typename T>
00172 unsigned PointMatcher<T>::DataPoints::getHomogeneousDim() const
00173 {
00174 return features.rows();
00175 }
00176
00178 template<typename T>
00179 unsigned PointMatcher<T>::DataPoints::getNbGroupedDescriptors() const
00180 {
00181 return descriptorLabels.size();
00182 }
00183
00185 template<typename T>
00186 unsigned PointMatcher<T>::DataPoints::getDescriptorDim() const
00187 {
00188 return descriptors.rows();
00189 }
00190
00192 template<typename T>
00193 unsigned PointMatcher<T>::DataPoints::getTimeDim() const
00194 {
00195 return times.rows();
00196 }
00197
00199 template<typename T>
00200 bool PointMatcher<T>::DataPoints::operator ==(const DataPoints& that) const
00201 {
00202
00203 bool isEqual = false;
00204 if((features.rows() == that.features.rows()) &&
00205 (features.cols() == that.features.cols()) &&
00206 (descriptors.rows() == that.descriptors.rows()) &&
00207 (descriptors.cols() == that.descriptors.cols()) &&
00208 (times.rows() == that.times.rows()) &&
00209 (times.cols() == that.times.cols()))
00210 {
00211 isEqual = (features == that.features) &&
00212 (featureLabels == that.featureLabels) &&
00213 (descriptors == that.descriptors) &&
00214 (descriptorLabels == that.descriptorLabels)&&
00215 (times == that.times) &&
00216 (timeLabels == that.timeLabels);
00217 }
00218
00219 return isEqual;
00220
00221 }
00222
00224 template<typename T>
00225 void PointMatcher<T>::DataPoints::concatenate(const DataPoints& dp)
00226 {
00227 const int nbPoints1 = this->features.cols();
00228 const int nbPoints2 = dp.features.cols();
00229 const int nbPointsTotal = nbPoints1 + nbPoints2;
00230
00231 const int dimFeat = this->features.rows();
00232 if(dimFeat != dp.features.rows())
00233 {
00234 stringstream errorMsg;
00235 errorMsg << "Cannot concatenate DataPoints because the dimension of the features are not the same. Actual dimension: " << dimFeat << " New dimension: " << dp.features.rows();
00236 throw InvalidField(errorMsg.str());
00237 }
00238
00239
00240 this->features.conservativeResize(Eigen::NoChange, nbPointsTotal);
00241 this->features.rightCols(nbPoints2) = dp.features;
00242
00243
00244 concatenateLabelledMatrix(&descriptorLabels, &descriptors, dp.descriptorLabels, dp.descriptors);
00245 assertDescriptorConsistency();
00246
00247
00248 concatenateLabelledMatrix(&timeLabels, ×, dp.timeLabels, dp.times);
00249 assertTimesConsistency();
00250
00251 }
00252
00253
00255 template<typename T>
00256 template<typename MatrixType>
00257 void PointMatcher<T>::DataPoints::concatenateLabelledMatrix(Labels* labels, MatrixType* data, const Labels extraLabels, const MatrixType extraData)
00258 {
00259 const int nbPoints1 = data->cols();
00260 const int nbPoints2 = extraData.cols();
00261 const int nbPointsTotal = nbPoints1 + nbPoints2;
00262
00263
00264 if (*labels == extraLabels)
00265 {
00266 if (labels->size() > 0)
00267 {
00268
00269 data->conservativeResize(Eigen::NoChange, nbPointsTotal);
00270 data->rightCols(nbPoints2) = extraData;
00271 }
00272 }
00273 else
00274 {
00275
00276
00277
00278 Labels newLabels;
00279 for(BOOST_AUTO(it, labels->begin()); it != labels->end(); ++it)
00280 {
00281 for(BOOST_AUTO(jt, extraLabels.begin()); jt != extraLabels.end(); ++jt)
00282 {
00283 if (it->text == jt->text)
00284 {
00285 if (it->span != jt->span)
00286 throw InvalidField(
00287 (boost::format("The field %1% has dimension %2% in this, different than dimension %3% in that") % it->text % it->span % jt->span).str()
00288 );
00289 newLabels.push_back(*it);
00290 break;
00291 }
00292 }
00293 }
00294
00295
00296 if (newLabels.size() > 0)
00297 {
00298 MatrixType newData;
00299 Labels filledLabels;
00300 this->allocateFields(newLabels, filledLabels, newData);
00301 assert(newLabels == filledLabels);
00302
00303
00304 unsigned row(0);
00305 for(BOOST_AUTO(it, newLabels.begin()); it != newLabels.end(); ++it)
00306 {
00307 Eigen::Block<MatrixType> view(newData.block(row, 0, it->span, newData.cols()));
00308 view.leftCols(nbPoints1) = getViewByName(it->text, *labels, *data);
00309 view.rightCols(nbPoints2) = getViewByName(it->text, extraLabels, extraData);
00310 row += it->span;
00311 }
00312
00313
00314 data->swap(newData);
00315 *labels = newLabels;
00316 }
00317 else
00318 {
00319 *data = MatrixType();
00320 *labels = Labels();
00321 }
00322 }
00323 }
00324
00326 template<typename T>
00327 void PointMatcher<T>::DataPoints::conservativeResize(Index pointCount)
00328 {
00329 features.conservativeResize(Eigen::NoChange, pointCount);
00330 if (descriptors.cols() > 0)
00331 descriptors.conservativeResize(Eigen::NoChange, pointCount);
00332
00333 if (times.cols() > 0)
00334 times.conservativeResize(Eigen::NoChange, pointCount);
00335 }
00336
00338 template<typename T>
00339 typename PointMatcher<T>::DataPoints PointMatcher<T>::DataPoints::createSimilarEmpty() const
00340 {
00341 const int nbPoints(features.cols());
00342 DataPoints output(
00343 Matrix(features.rows(), nbPoints),
00344 featureLabels
00345 );
00346
00347 assertDescriptorConsistency();
00348 if (descriptors.cols() > 0)
00349 {
00350 output.descriptors = Matrix(descriptors.rows(), nbPoints);
00351 output.descriptorLabels = descriptorLabels;
00352 }
00353
00354 assertTimesConsistency();
00355 if (times.cols() > 0)
00356 {
00357 output.times = Int64Matrix(times.rows(), nbPoints);
00358 output.timeLabels = timeLabels;
00359 }
00360
00361 return output;
00362 }
00363
00365 template<typename T>
00366 typename PointMatcher<T>::DataPoints PointMatcher<T>::DataPoints::createSimilarEmpty(Index pointCount) const
00367 {
00368 DataPoints output(
00369 Matrix(features.rows(), pointCount),
00370 featureLabels
00371 );
00372
00373 assertDescriptorConsistency();
00374 if (descriptors.cols() > 0)
00375 {
00376 output.descriptors = Matrix(descriptors.rows(), pointCount);
00377 output.descriptorLabels = descriptorLabels;
00378 }
00379
00380 assertTimesConsistency();
00381 if (times.cols() > 0)
00382 {
00383 output.times = Int64Matrix(times.rows(), pointCount);
00384 output.timeLabels = timeLabels;
00385 }
00386
00387 return output;
00388 }
00389
00391 template<typename T>
00392 void PointMatcher<T>::DataPoints::setColFrom(Index thisCol, const DataPoints& that, Index thatCol)
00393 {
00394 features.col(thisCol) = that.features.col(thatCol);
00395
00396 if (descriptors.cols() > 0)
00397 descriptors.col(thisCol) = that.descriptors.col(thatCol);
00398
00399 if (times.cols() > 0)
00400 times.col(thisCol) = that.times.col(thatCol);
00401
00402 }
00404 template<typename T>
00405 void PointMatcher<T>::DataPoints::swapCols(Index iCol,Index jCol)
00406 {
00407 features.col(iCol).swap(features.col(jCol));
00408 if (descriptors.cols() > 0)
00409 descriptors.col(iCol).swap(descriptors.col(jCol));
00410 if (times.cols() > 0)
00411 times.col(iCol).swap(times.col(jCol));
00412 }
00413
00414
00415
00416
00417
00418
00420 template<typename T>
00421 void PointMatcher<T>::DataPoints::allocateFeature(const std::string& name, const unsigned dim)
00422 {
00423 allocateField(name, dim, featureLabels, features);
00424 }
00425
00427 template<typename T>
00428 void PointMatcher<T>::DataPoints::allocateFeatures(const Labels& newLabels)
00429 {
00430 allocateFields(newLabels, featureLabels, features);
00431 }
00432
00434 template<typename T>
00435 void PointMatcher<T>::DataPoints::addFeature(const std::string& name, const Matrix& newFeature)
00436 {
00437 removeFeature("pad");
00438 addField<Matrix>(name, newFeature, featureLabels, features);
00439 addField<Matrix>("pad", Matrix::Ones(1, features.cols()), featureLabels, features);
00440 }
00441
00443 template<typename T>
00444 void PointMatcher<T>::DataPoints::removeFeature(const std::string& name)
00445 {
00446 removeField(name, featureLabels, features);
00447 }
00448
00450 template<typename T>
00451 typename PointMatcher<T>::Matrix PointMatcher<T>::DataPoints::getFeatureCopyByName(const std::string& name) const
00452 {
00453 return Matrix(getFeatureViewByName(name));
00454 }
00455
00457 template<typename T>
00458 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getFeatureViewByName(const std::string& name) const
00459 {
00460 return getConstViewByName(name, featureLabels, features);
00461 }
00462
00464 template<typename T>
00465 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getFeatureViewByName(const std::string& name)
00466 {
00467 return getViewByName(name, featureLabels, features);
00468 }
00469
00471 template<typename T>
00472 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getFeatureRowViewByName(const std::string& name, const unsigned row) const
00473 {
00474 return getConstViewByName(name, featureLabels, features, int(row));
00475 }
00476
00478 template<typename T>
00479 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getFeatureRowViewByName(const std::string& name, const unsigned row)
00480 {
00481 return getViewByName(name, featureLabels, features, int(row));
00482 }
00483
00485 template<typename T>
00486 bool PointMatcher<T>::DataPoints::featureExists(const std::string& name) const
00487 {
00488 return fieldExists(name, 0, featureLabels);
00489 }
00490
00492 template<typename T>
00493 bool PointMatcher<T>::DataPoints::featureExists(const std::string& name, const unsigned dim) const
00494 {
00495 return fieldExists(name, dim, featureLabels);
00496 }
00497
00499 template<typename T>
00500 unsigned PointMatcher<T>::DataPoints::getFeatureDimension(const std::string& name) const
00501 {
00502 return getFieldDimension(name, featureLabels);
00503 }
00504
00506 template<typename T>
00507 unsigned PointMatcher<T>::DataPoints::getFeatureStartingRow(const std::string& name) const
00508 {
00509 return getFieldStartingRow(name, featureLabels);
00510 }
00511
00512
00513
00514
00515
00517 template<typename T>
00518 void PointMatcher<T>::DataPoints::allocateDescriptor(const std::string& name, const unsigned dim)
00519 {
00520 allocateField(name, dim, descriptorLabels, descriptors);
00521 }
00522
00524 template<typename T>
00525 void PointMatcher<T>::DataPoints::allocateDescriptors(const Labels& newLabels)
00526 {
00527 allocateFields(newLabels, descriptorLabels, descriptors);
00528 }
00529
00531 template<typename T>
00532 void PointMatcher<T>::DataPoints::addDescriptor(const std::string& name, const Matrix& newDescriptor)
00533 {
00534 addField(name, newDescriptor, descriptorLabels, descriptors);
00535 }
00536
00538 template<typename T>
00539 void PointMatcher<T>::DataPoints::removeDescriptor(const std::string& name)
00540 {
00541 removeField(name, descriptorLabels, descriptors);
00542 }
00543
00544
00546 template<typename T>
00547 typename PointMatcher<T>::Matrix PointMatcher<T>::DataPoints::getDescriptorCopyByName(const std::string& name) const
00548 {
00549 return Matrix(getDescriptorViewByName(name));
00550 }
00551
00553 template<typename T>
00554 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getDescriptorViewByName(const std::string& name) const
00555 {
00556 return getConstViewByName(name, descriptorLabels, descriptors);
00557 }
00558
00560 template<typename T>
00561 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getDescriptorViewByName(const std::string& name)
00562 {
00563 return getViewByName(name, descriptorLabels, descriptors);
00564 }
00565
00567 template<typename T>
00568 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getDescriptorRowViewByName(const std::string& name, const unsigned row) const
00569 {
00570 return getConstViewByName(name, descriptorLabels, descriptors, int(row));
00571 }
00572
00574 template<typename T>
00575 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getDescriptorRowViewByName(const std::string& name, const unsigned row)
00576 {
00577 return getViewByName(name, descriptorLabels, descriptors, int(row));
00578 }
00579
00581 template<typename T>
00582 bool PointMatcher<T>::DataPoints::descriptorExists(const std::string& name) const
00583 {
00584 return fieldExists(name, 0, descriptorLabels);
00585 }
00586
00588 template<typename T>
00589 bool PointMatcher<T>::DataPoints::descriptorExists(const std::string& name, const unsigned dim) const
00590 {
00591 return fieldExists(name, dim, descriptorLabels);
00592 }
00593
00595 template<typename T>
00596 unsigned PointMatcher<T>::DataPoints::getDescriptorDimension(const std::string& name) const
00597 {
00598 return getFieldDimension(name, descriptorLabels);
00599 }
00600
00602 template<typename T>
00603 unsigned PointMatcher<T>::DataPoints::getDescriptorStartingRow(const std::string& name) const
00604 {
00605 return getFieldStartingRow(name, descriptorLabels);
00606 }
00607
00609 template<typename T>
00610 void PointMatcher<T>::DataPoints::assertDescriptorConsistency() const
00611 {
00612 assertConsistency("descriptors", descriptors.rows(), descriptors.cols(), descriptorLabels);
00613 }
00614
00615
00616
00617
00618
00620 template<typename T>
00621 void PointMatcher<T>::DataPoints::allocateTime(const std::string& name, const unsigned dim)
00622 {
00623 allocateField(name, dim, timeLabels, times);
00624 }
00625
00627 template<typename T>
00628 void PointMatcher<T>::DataPoints::allocateTimes(const Labels& newLabels)
00629 {
00630 allocateFields(newLabels, timeLabels, times);
00631 }
00632
00633
00635 template<typename T>
00636 void PointMatcher<T>::DataPoints::addTime(const std::string& name, const Int64Matrix& newTime)
00637 {
00638 addField(name, newTime, timeLabels, times);
00639 }
00640
00642 template<typename T>
00643 void PointMatcher<T>::DataPoints::removeTime(const std::string& name)
00644 {
00645 removeField(name, timeLabels, times);
00646 }
00647
00649 template<typename T>
00650 typename PointMatcher<T>::Int64Matrix PointMatcher<T>::DataPoints::getTimeCopyByName(const std::string& name) const
00651 {
00652 return Int64Matrix(getTimeViewByName(name));
00653 }
00654
00655
00657 template<typename T>
00658 const typename PointMatcher<T>::DataPoints::TimeConstView PointMatcher<T>::DataPoints::getTimeViewByName(const std::string& name) const
00659 {
00660 return getConstViewByName(name, timeLabels, times);
00661 }
00662
00664 template<typename T>
00665 typename PointMatcher<T>::DataPoints::TimeView PointMatcher<T>::DataPoints::getTimeViewByName(const std::string& name)
00666 {
00667 return getViewByName(name, timeLabels, times);
00668 }
00669
00671 template<typename T>
00672 const typename PointMatcher<T>::DataPoints::TimeConstView PointMatcher<T>::DataPoints::getTimeRowViewByName(const std::string& name, const unsigned row) const
00673 {
00674 return getConstViewByName(name, timeLabels, times, int(row));
00675 }
00676
00678 template<typename T>
00679 typename PointMatcher<T>::DataPoints::TimeView PointMatcher<T>::DataPoints::getTimeRowViewByName(const std::string& name, const unsigned row)
00680 {
00681 return getViewByName(name, timeLabels, times, int(row));
00682 }
00683
00684
00686 template<typename T>
00687 bool PointMatcher<T>::DataPoints::timeExists(const std::string& name) const
00688 {
00689 return fieldExists(name, 0, timeLabels);
00690 }
00691
00693 template<typename T>
00694 bool PointMatcher<T>::DataPoints::timeExists(const std::string& name, const unsigned dim) const
00695 {
00696 return fieldExists(name, dim, timeLabels);
00697 }
00698
00700 template<typename T>
00701 unsigned PointMatcher<T>::DataPoints::getTimeDimension(const std::string& name) const
00702 {
00703 return getFieldDimension(name, timeLabels);
00704 }
00705
00707 template<typename T>
00708 unsigned PointMatcher<T>::DataPoints::getTimeStartingRow(const std::string& name) const
00709 {
00710 return getFieldStartingRow(name, timeLabels);
00711 }
00712
00714 template<typename T>
00715 void PointMatcher<T>::DataPoints::assertTimesConsistency() const
00716 {
00717 assertConsistency("times", times.rows(), times.cols(), timeLabels);
00718 }
00719
00721 template<typename T>
00722 void PointMatcher<T>::DataPoints::assertConsistency(const std::string& dataName, const int dataRows, const int dataCols, const Labels& labels) const
00723 {
00724 if (dataRows == 0)
00725 {
00726 if (dataCols != 0)
00727 throw InvalidField(
00728 (boost::format("Point cloud has degenerate %2% dimensions of rows=0, cols=%1%") % dataCols % dataName).str()
00729 );
00730 if (labels.size() > 0)
00731 throw InvalidField(
00732 (boost::format("Point cloud has no %2% data but %1% descriptor labels") % labels.size() % dataName).str()
00733 );
00734 }
00735 else
00736 {
00737 if (dataCols != features.cols())
00738 {
00739 throw InvalidField(
00740 (boost::format("Point cloud has %1% points in features but %2% points in %3%") % features.cols() % dataCols % dataName).str()
00741 );
00742 }
00743
00744 int descDim(0);
00745 for (BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00746 descDim += it->span;
00747
00748 if (dataRows != descDim)
00749 throw InvalidField(
00750 (boost::format("Labels from %3% return %1% total dimensions but there are %2% in the %3% matrix") % descDim % dataRows % dataName).str()
00751 );
00752
00753 }
00754
00755 }
00756
00758 template<typename T>
00759 template<typename MatrixType>
00760 void PointMatcher<T>::DataPoints::allocateField(const std::string& name, const unsigned dim, Labels& labels, MatrixType& data) const
00761 {
00762 if (fieldExists(name, 0, labels))
00763 {
00764 const unsigned descDim(getFieldDimension(name, labels));
00765 if (descDim != dim)
00766 {
00767 throw InvalidField(
00768 (boost::format("The existing field %1% has dimension %2%, different than requested dimension %3%") % name % descDim % dim).str()
00769 );
00770 }
00771 }
00772 else
00773 {
00774 const int oldDim(data.rows());
00775 const int totalDim(oldDim + dim);
00776 const int pointCount(features.cols());
00777 data.conservativeResize(totalDim, pointCount);
00778 labels.push_back(Label(name, dim));
00779 }
00780 }
00781
00783 template<typename T>
00784 template<typename MatrixType>
00785 void PointMatcher<T>::DataPoints::allocateFields(const Labels& newLabels, Labels& labels, MatrixType& data) const
00786 {
00787 typedef vector<bool> BoolVector;
00788 BoolVector present(newLabels.size(), false);
00789
00790
00791 size_t additionalDim(0);
00792 for (size_t i = 0; i < newLabels.size(); ++i)
00793 {
00794 const string& newName(newLabels[i].text);
00795 const size_t newSpan(newLabels[i].span);
00796 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00797 {
00798 if (it->text == newName)
00799 {
00800 if (it->span != newSpan)
00801 throw InvalidField(
00802 (boost::format("The existing field %1% has dimension %2%, different than requested dimension %3%") % newName % it->span % newSpan).str()
00803 );
00804 present[i] = true;
00805 break;
00806 }
00807 }
00808 if (!present[i])
00809 additionalDim += newSpan;
00810 }
00811
00812
00813 const int oldDim(data.rows());
00814 const int totalDim(oldDim + additionalDim);
00815 const int pointCount(features.cols());
00816 data.conservativeResize(totalDim, pointCount);
00817 for (size_t i = 0; i < newLabels.size(); ++i)
00818 {
00819 if (!present[i])
00820 labels.push_back(newLabels[i]);
00821 }
00822 }
00823
00825 template<typename T>
00826 template<typename MatrixType>
00827 void PointMatcher<T>::DataPoints::addField(const std::string& name, const MatrixType& newField, Labels& labels, MatrixType& data) const
00828 {
00829 const int newFieldDim = newField.rows();
00830 const int newPointCount = newField.cols();
00831 const int pointCount = features.cols();
00832
00833 if (newField.rows() == 0)
00834 return;
00835
00836
00837 if (fieldExists(name, 0, labels))
00838 {
00839 const int fieldDim = getFieldDimension(name, labels);
00840
00841 if(fieldDim == newFieldDim)
00842 {
00843
00844 if(pointCount == newPointCount)
00845 {
00846 const int row = getFieldStartingRow(name, labels);
00847 data.block(row, 0, fieldDim, pointCount) = newField;
00848 }
00849 else
00850 {
00851 stringstream errorMsg;
00852 errorMsg << "The field " << name << " cannot be added because the number of points is not the same. Old point count: " << pointCount << "new: " << newPointCount;
00853 throw InvalidField(errorMsg.str());
00854 }
00855 }
00856 else
00857 {
00858 stringstream errorMsg;
00859 errorMsg << "The field " << name << " already exists but could not be added because the dimension is not the same. Old dim: " << fieldDim << " new: " << newFieldDim;
00860 throw InvalidField(errorMsg.str());
00861 }
00862 }
00863 else
00864 {
00865 if(pointCount == newPointCount || pointCount == 0)
00866 {
00867 const int oldFieldDim(data.rows());
00868 const int totalDim = oldFieldDim + newFieldDim;
00869 data.conservativeResize(totalDim, newPointCount);
00870 data.bottomRows(newFieldDim) = newField;
00871 labels.push_back(Label(name, newFieldDim));
00872 }
00873 else
00874 {
00875 stringstream errorMsg;
00876 errorMsg << "The field " << name << " cannot be added because the number of points is not the same. Old point count: " << pointCount << " new: " << newPointCount;
00877 throw InvalidField(errorMsg.str());
00878 }
00879 }
00880 }
00882 template<typename T>
00883 template<typename MatrixType>
00884 void PointMatcher<T>::DataPoints::removeField(const std::string& name, Labels& labels, MatrixType& data) const
00885 {
00886
00887 const unsigned deleteId = getFieldStartingRow(name, labels);
00888 const unsigned span = getFieldDimension(name, labels);
00889 const unsigned keepAfterId = deleteId + span;
00890 const unsigned lastId = data.rows() - 1;
00891 const unsigned sizeKeep = data.rows() - keepAfterId;
00892 const unsigned nbPoints = data.cols();
00893
00894
00895
00896 if(keepAfterId <= lastId)
00897 {
00898 data.block(deleteId, 0, sizeKeep, nbPoints) = data.block(keepAfterId, 0, sizeKeep, nbPoints);
00899 }
00900
00901
00902 data.conservativeResize(data.rows()-span, nbPoints);
00903
00904
00905 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00906 {
00907 if (it->text == name)
00908 {
00909 labels.erase(it);
00910 break;
00911 }
00912 }
00913
00914 }
00915
00916
00919 template<typename T>
00920 template<typename MatrixType>
00921 const typename Eigen::Block<const MatrixType> PointMatcher<T>::DataPoints::getConstViewByName(const std::string& name, const Labels& labels, const MatrixType& data, const int viewRow) const
00922 {
00923 unsigned row(0);
00924 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00925 {
00926 if (it->text == name)
00927 {
00928 if (viewRow >= 0)
00929 {
00930 if (viewRow >= int(it->span))
00931 throw InvalidField(
00932 (boost::format("Requesting row %1% of field %2% that only has %3% rows") % viewRow % name % it->span).str()
00933 );
00934 return data.block(row + viewRow, 0, 1, data.cols());
00935 }
00936 else
00937 return data.block(row, 0, it->span, data.cols());
00938 }
00939 row += it->span;
00940 }
00941 throw InvalidField("Field " + name + " not found");
00942 }
00943
00946 template<typename T>
00947 template<typename MatrixType>
00948 typename Eigen::Block<MatrixType> PointMatcher<T>::DataPoints::getViewByName(const std::string& name, const Labels& labels, MatrixType& data, const int viewRow) const
00949 {
00950 unsigned row(0);
00951 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00952 {
00953 if (it->text == name)
00954 {
00955 if (viewRow >= 0)
00956 {
00957 if (viewRow >= int(it->span))
00958 throw InvalidField(
00959 (boost::format("Requesting row %1% of field %2% that only has %3% rows") % viewRow % name % it->span).str()
00960 );
00961 return data.block(row + viewRow, 0, 1, data.cols());
00962 }
00963 else
00964 return data.block(row, 0, it->span, data.cols());
00965 }
00966 row += it->span;
00967 }
00968 throw InvalidField("Field " + name + " not found");
00969 }
00970
00972 template<typename T>
00973 bool PointMatcher<T>::DataPoints::fieldExists(const std::string& name, const unsigned dim, const Labels& labels) const
00974 {
00975 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00976 {
00977 if (it->text == name)
00978 {
00979 if (dim == 0 || it->span == dim)
00980 return true;
00981 else
00982 return false;
00983 }
00984 }
00985 return false;
00986 }
00987
00988
00990 template<typename T>
00991 unsigned PointMatcher<T>::DataPoints::getFieldDimension(const std::string& name, const Labels& labels) const
00992 {
00993 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00994 {
00995 if (it->text == name)
00996 return it->span;
00997 }
00998 return 0;
00999 }
01000
01001
01003 template<typename T>
01004 unsigned PointMatcher<T>::DataPoints::getFieldStartingRow(const std::string& name, const Labels& labels) const
01005 {
01006 unsigned row(0);
01007 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
01008 {
01009 if (it->text == name)
01010 return row;
01011 row += it->span;
01012 }
01013 return 0;
01014 }
01015
01016 template struct PointMatcher<float>::DataPoints;
01017 template struct PointMatcher<double>::DataPoints;
01018
01019
01021 template<typename T>
01022 void PointMatcher<T>::swapDataPoints(DataPoints& a, DataPoints& b)
01023 {
01024 a.features.swap(b.features);
01025 swap(a.featureLabels, b.featureLabels);
01026 a.descriptors.swap(b.descriptors);
01027 swap(a.descriptorLabels, b.descriptorLabels);
01028 a.times.swap(b.times);
01029 swap(a.timeLabels, b.timeLabels);
01030 }
01031
01032 template
01033 void PointMatcher<float>::swapDataPoints(DataPoints& a, DataPoints& b);
01034 template
01035 void PointMatcher<double>::swapDataPoints(DataPoints& a, DataPoints& b);