00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <QVVectorMap>
00022
00023 #define SIGNATURE(Vector) (Vector.sum()/sqrt((long double) (Vector.size())))
00024
00025 void QVVectorMap::add(const QVVector &vector)
00026 {
00027 insertMulti(SIGNATURE(vector), vector);
00028 }
00029
00030 QVVectorMap::QVVectorMap(const QList<QVVector> & vectors): QMap<double, QVVector>()
00031 {
00032 foreach(QVVector vector, vectors)
00033 add(vector);
00034 };
00035
00036 QList<QVVector> QVVectorMap::getClosestVectors(const QVVector actualVector, const QList<QVVector> &vectors, const int n)
00037 {
00038 QMap<double, QVVector> hash;
00039 foreach(QVVector v, vectors)
00040 hash.insertMulti((v - actualVector).norm2(), v);
00041 return hash.values().mid(0,n);
00042 }
00043
00044 QVVector QVVectorMap::getClosestVector(const QVVector &vector) const
00045 {
00046 if (size() == 0)
00047 return QVVector();
00048 else
00049 return getClosestVectors(vector, 1).first();
00050 }
00051
00052 QList<QVVector> QVVectorMap::getClosestVectors(const QVVector &vector, const int maxVectors) const
00053 {
00054 const double vector_signature = SIGNATURE(vector);
00055
00056
00057 if (size() == 0 || maxVectors <= 0)
00058 return QList<QVVector>();
00059
00060 if (size() <= maxVectors)
00061 return values();
00062
00063
00064 int t = 0;
00065 QMap<double, QVVector> closestVectors;
00066 for(QMap<double, QVVector>::const_iterator i = constBegin(); t < maxVectors; ++t, ++i)
00067 closestVectors.insertMulti((vector - i.value()).norm2(), i.value());
00068
00069
00070 double last_key = (--(closestVectors.end())).key();
00071
00072
00073 QMap<double, QVVector>::const_iterator pivot = lowerBound(SIGNATURE(vector));
00074 if (pivot == constEnd())
00075 --pivot;
00076
00077
00078 if (pivot != constBegin())
00079 for (QMap<double, QVVector>::const_iterator i = pivot; i != constBegin(); --i)
00080 {
00081 if (ABS(i.key() - vector_signature) >= last_key)
00082 break;
00083
00084 const double actualDistance = (vector - i.value()).norm2();
00085 if (actualDistance < last_key)
00086 {
00087 closestVectors.take(last_key);
00088 closestVectors.insertMulti(actualDistance, i.value());
00089 last_key = (--(closestVectors.end())).key();
00090 }
00091 }
00092
00093
00094 for (QMap<double, QVVector>::const_iterator i = pivot + 1; i != constEnd(); ++i)
00095 {
00096 if (ABS(i.key() - vector_signature) >= last_key)
00097 break;
00098
00099 const double actualDistance = (vector - i.value()).norm2();
00100 if (actualDistance < last_key)
00101 {
00102 closestVectors.take(last_key);
00103 closestVectors.insertMulti(actualDistance, i.value());
00104 last_key = (--(closestVectors.end())).key();
00105 }
00106 }
00107
00108 return closestVectors.values();
00109 }