PARP Research Group University of Murcia, Spain


src/qvmath/qv2dmap.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2009. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00024 
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <iostream>
00028 
00029 #include <QSet>
00030 
00032 #include <QVVector>
00033 
00034 #include <QV2DMap>
00035 #include <qvmath.h>
00036 
00037 #define SIGNATURE(Point)        (Point.x())
00038 void QV2DMap::add(const QPointF &point)
00039         {
00040         insertMulti(SIGNATURE(point), point);
00041         }
00042 
00043 QV2DMap::QV2DMap(const QList<QPointF> & points): QMap<double, QPointF>()
00044         {
00045         foreach(QPointF point, points)
00046                 add(point);     
00047         };
00048 
00049 QList<QPointF> QV2DMap::getClosestPoints(const QPointF &point, const int n) const
00050         {
00051         // Trivial cases
00052         if (size() == 0 || n <= 0)
00053                 return QList<QPointF>();
00054 
00055         if (size() <= n)
00056                 return values();
00057 
00058         QMap<double, QPointF> closestPoints;
00059         QMap<double, QPointF>::const_iterator pivot = lowerBound(SIGNATURE(point));
00060 
00061         // Special threatment of the first element
00062         closestPoints.insertMulti(norm2(point - constBegin().value()), constBegin().value());
00063 
00064         // Iterate to the left of the pivot element
00065         if (pivot != constBegin())
00066                 for (QMap<double, QPointF>::const_iterator i = pivot; i != constBegin(); --i)
00067                                 {
00068                                 const double actualDistance = norm2(point - i.value());
00069                                 if (closestPoints.size() >= n)
00070                                         {
00071                                         QMap<double, QPointF>::iterator last = (--(closestPoints.end()));
00072 
00073                                         if (ABS(i.key() - SIGNATURE(point)) >= last.key())
00074                                                 break;
00075 
00076                                         if (actualDistance < last.key())
00077                                                 {
00078                                                 closestPoints.take(last.key());
00079                                                 closestPoints.insertMulti(actualDistance, i.value());
00080                                                 }
00081                                         }
00082                                 else
00083                                         closestPoints.insertMulti(actualDistance, i.value());
00084                                 if (i == constBegin())
00085                                         break;
00086                                 }
00087 
00088         // Iterate to the right of the pivot element
00089         for (QMap<double, QPointF>::const_iterator i = pivot + 1; i != constEnd(); ++i)
00090                 {
00091                 const double actualDistance = norm2(point - i.value());
00092                 if (closestPoints.size() >= n)
00093                         {
00094                         QMap<double, QPointF>::iterator last = (--(closestPoints.end()));
00095 
00096                         if (ABS(i.key() - SIGNATURE(point)) >= last.key())
00097                                 break;
00098 
00099                         if (actualDistance < last.key())
00100                                 {
00101                                 closestPoints.take(last.key());
00102                                 closestPoints.insertMulti(actualDistance, i.value());
00103                                 }
00104                         }
00105                 else
00106                         closestPoints.insertMulti(actualDistance, i.value());
00107                 }
00108 
00109         return closestPoints.values();
00110         }
00111 
00112 QList<QPointF> QV2DMap::getClosestPoints2(const QPointF &point, const int n) const
00113         {
00114         // Trivial cases
00115         if (size() == 0 || n <= 0)
00116                 return QList<QPointF>();
00117 
00118         if (size() <= n)
00119                 return values();
00120 
00121         QMap<double, QPointF> closestPoints;
00122 
00123         // Add the first point of the list, and the closest one to the provided point
00124         foreach(QPointF actual, values())
00125                 closestPoints.insertMulti(norm2(point - actual), actual);
00126 
00127         return closestPoints.values().mid(0,n);
00128         }
00129 
00130 void QV2DMap::test()
00131         {
00132         QSet<QPointF> sourcePointsTemp, destinationPointsTemp;
00133 
00134         for (int i = 1; i <= 1000; i++)
00135                 sourcePointsTemp.insert(QPointF(rand()%100, rand()%100));
00136 
00137         for (int i = 1; i < 1000; i++)
00138                 destinationPointsTemp.insert(QPointF(rand()%100, rand()%100));
00139 
00140         QList<QPointF> sourcePoints = sourcePointsTemp.values(), destinationPoints = destinationPointsTemp.values();
00141 
00142         QV2DMap m = destinationPoints;
00143 
00144         for(int i = 0; i < sourcePoints.size(); i++)
00145                 {
00146                 const QPointF point = sourcePoints[i];
00147                 const QList<QPointF> l1 = m.getClosestPoints(point, 50), l2 = m.getClosestPoints2(point, 50);
00148                 const QSet<QPointF> temp1 = l1.toSet(), temp2 = l2.toSet();
00149 
00150                 if (l1.size() != l2.size())
00151                         std::cout << "ERROR: different sizes for obtained lists" << std::endl;
00152 
00153                 bool cond = false;
00154                 for(int j = 0; j < l1.size(); j++)
00155                         if (ABS(norm2(l1[j] - point) - norm2(l2[j] - point)) > 0.00000001)
00156                                 cond = true;
00157                         
00158                 if (cond)
00159                         {
00160                         std::cout << "Error: distances are different" << std::endl;
00161                         std::cout << "Point("<< point.x() << ", " << point.y() << ")" << std::endl;
00162                         std::cout << "l1 = " << std::endl;
00163                         foreach (QPointF p, l1)
00164                                 std::cout << "\tPoint("<< p.x() << ", " << p.y() << ")\tdistance = " << norm2(p - point) << std::endl;
00165 
00166                         std::cout << "l2 = " << std::endl;
00167                         foreach (QPointF p, l2)
00168                                 std::cout << "\tPoint("<< p.x() << ", " << p.y() << ")\tdistance = " << norm2(p - point) << std::endl;
00169 
00170                         }
00171                 }
00172         }
00173 



QVision framework. PARP research group, copyright 2007, 2008.