00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <iostream>
00028
00029 #include <QSet>
00030
00031 #include <QV2DMap>
00032 #include <qvmath.h>
00033
00034 #define SQRT2 1.414213562
00035 #define SIGNATURE(Point) ( (Point.x() + Point.y()) / SQRT2)
00036
00037 void QV2DMap::add(const QPointF &point)
00038 {
00039 insertMulti(SIGNATURE(point), point);
00040 }
00041
00042 QV2DMap::QV2DMap(const QList<QPointF> & points): QMap<double, QPointF>()
00043 {
00044 foreach(QPointF point, points)
00045 add(point);
00046 };
00047
00048 QList<QPointF> QV2DMap::getClosestPoints(const QPointF &point, const int maxPoints) const
00049 {
00050 const double point_signature = SIGNATURE(point);
00051
00052
00053 if (size() == 0 || maxPoints <= 0)
00054 return QList<QPointF>();
00055
00056 if (size() <= maxPoints)
00057 return values();
00058
00059
00060 int t = 0;
00061 QMap<double, QPointF> closestPoints;
00062 for(QMap<double, QPointF>::const_iterator i = constBegin(); t < maxPoints; ++t, ++i)
00063 closestPoints.insertMulti(norm2(point - i.value()), i.value());
00064
00065
00066 double last_key = (--(closestPoints.end())).key();
00067
00068
00069 QMap<double, QPointF>::const_iterator pivot = lowerBound(SIGNATURE(point));
00070 if (pivot == constEnd())
00071 --pivot;
00072
00073
00074 if (pivot != constBegin())
00075 for (QMap<double, QPointF>::const_iterator i = pivot; i != constBegin(); --i)
00076 {
00077 if (ABS(i.key() - point_signature) >= last_key)
00078 break;
00079
00080 const double actualDistance = norm2(point - i.value());
00081 if (actualDistance < last_key)
00082 {
00083 closestPoints.take(last_key);
00084 closestPoints.insertMulti(actualDistance, i.value());
00085 last_key = (--(closestPoints.end())).key();
00086 }
00087 }
00088
00089
00090 for (QMap<double, QPointF>::const_iterator i = pivot + 1; i != constEnd(); ++i)
00091 {
00092 if (ABS(i.key() - point_signature) >= last_key)
00093 break;
00094
00095 const double actualDistance = norm2(point - i.value());
00096 if (actualDistance < last_key)
00097 {
00098 closestPoints.take(last_key);
00099 closestPoints.insertMulti(actualDistance, i.value());
00100 last_key = (--(closestPoints.end())).key();
00101 }
00102 }
00103
00104 return closestPoints.values();
00105 }
00106
00107 QList<QPointF> QV2DMap::getClosestPoints2(const QPointF &point, const int n) const
00108 {
00109
00110 if (size() == 0 || n <= 0)
00111 return QList<QPointF>();
00112
00113 if (size() <= n)
00114 return values();
00115
00116 QMap<double, QPointF> closestPoints;
00117
00118
00119 foreach(QPointF actual, values())
00120 closestPoints.insertMulti(norm2(point - actual), actual);
00121
00122 return closestPoints.values().mid(0,n);
00123 }
00124
00125 void QV2DMap::test()
00126 {
00127 QSet<QPointF> sourcePointsTemp, destinationPointsTemp;
00128
00129 for (int i = 1; i <= 1000; i++)
00130 sourcePointsTemp.insert(QPointF(rand()%100, rand()%100));
00131
00132 for (int i = 1; i < 1000; i++)
00133 destinationPointsTemp.insert(QPointF(rand()%100, rand()%100));
00134
00135 QList<QPointF> sourcePoints = sourcePointsTemp.values(), destinationPoints = destinationPointsTemp.values();
00136
00137 QV2DMap m = destinationPoints;
00138
00139 for(int i = 0; i < sourcePoints.size(); i++)
00140 {
00141 const QPointF point = sourcePoints[i];
00142 const QList<QPointF> l1 = m.getClosestPoints(point, 50), l2 = m.getClosestPoints2(point, 50);
00143 const QSet<QPointF> temp1 = l1.toSet(), temp2 = l2.toSet();
00144
00145 if (l1.size() != l2.size())
00146 std::cout << "ERROR: different sizes for obtained lists" << std::endl;
00147
00148 bool cond = false;
00149 for(int j = 0; j < l1.size(); j++)
00150 if (ABS(norm2(l1[j] - point) - norm2(l2[j] - point)) > 0.00000001)
00151 cond = true;
00152
00153 if (cond)
00154 {
00155 std::cout << "Error: distances are different" << std::endl;
00156 std::cout << "Point("<< point.x() << ", " << point.y() << ")" << std::endl;
00157 std::cout << "l1 = " << std::endl;
00158 foreach (QPointF p, l1)
00159 std::cout << "\tPoint("<< p.x() << ", " << p.y() << ")\tdistance = " << norm2(p - point) << std::endl;
00160
00161 std::cout << "l2 = " << std::endl;
00162 foreach (QPointF p, l2)
00163 std::cout << "\tPoint("<< p.x() << ", " << p.y() << ")\tdistance = " << norm2(p - point) << std::endl;
00164
00165 }
00166 }
00167 }
00168