public override IResult SearchKNN(object q, int K, IResult res)
{
// take the distance from q to the centers.
var dcq_cache = new double[this.clusters.Count];
var m = this.clusters.Count;
double min_dist = double.MaxValue;
for (int centerID = 0; centerID < m; ++centerID) {
var node = this.clusters [centerID];
var center = this.DB [node.objID];
var dcq = this.DB.Dist (center, q);
dcq_cache [centerID] = dcq;
res.Push (node.objID, dcq);
if (dcq < min_dist) {
min_dist = dcq;
}
}
this.internal_numdists += m;
// range queries can be empty at this point
// var min_dist = res.First.Dist;
// check for the cells of all the centers
for (int centerID = 0; centerID < m; ++centerID) {
var node = this.clusters [centerID];
var center = this.DB [node.objID];
var dcq = dcq_cache [centerID];
var rad = res.CoveringRadius;
if (dcq > node.cov + rad) { // the elements of the center are not in the query ball
continue;
}
if (dcq > min_dist + rad + rad) { // the query is in a cell too far from the center.
continue;
}
// check for the elements in the cell of actual center
int l = node.dists.Count;
for (int i = 0; i < l; ++i) {
var lower = dcq - node.dists[i];
if (lower < 0) {
lower = -lower;
}
if (lower <= rad) {
var docID = node.objects [i];
var d = this.DB.Dist (this.DB [docID], q);
res.Push (docID, d);
}
}
}
return res;
}