Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Алгоритм ближайшего соседа Quadtree

Автор вопроса: Magic Bullet DaveОтветов: 1

Я реализовал структуру дерева квадрантов для n точек, а также метод возврата массива точек внутри заданного прямоугольника. Кажется, я не могу найти алгоритм для эффективного поиска точки, ближайшей к другой заданной точке. Я упускаю что-то очевидное? Я предполагаю, что рекурсивное решение - правильный подход?

Я работаю в Objective C, но псевдокод будет в порядке. Кроме того, я фактически храню широчайшие, длинные данные, а расстояние между точками находится по большому кругу.

EDIT: Это код вставки и разделения моего дерева.

- (BOOL)insert:(id<PASQuadTreeDataPoint>)dataPoint {

    BOOL pointAdded = false;

    // If the point lies within the region
    if(CGRectContainsPoint(self.region, dataPoint.point)) {

        // If there are less than 4 points then add this point
        if(self.dataPoints.count < kMaxPointsPerNode) {
            [self.dataPoints addObject:dataPoint];
            pointAdded = true;
        }
        else {

            // Subdivide into 4 quadrants if not already subdivided
            if(northEast == nil) [self subdivide];

            // Attempt to add the point to one of the 4 subdivided quadrants
            if([northEast insert:dataPoint]) return true;
            if([southEast insert:dataPoint]) return true;
            if([southWest insert:dataPoint]) return true;
            if([northWest insert:dataPoint]) return true;
        }
    }

    return pointAdded;
}

- (void)subdivide {

    // Compute the half width and the origin
    CGFloat width = self.region.size.width * 0.5f;
    CGFloat height = self.region.size.height * 0.5f;
    CGFloat x = self.region.origin.x;
    CGFloat y = self.region.origin.y;

    // Create a new child quadtree with the region divided into quarters
    self.northEast = [PASQuadTree quadTreeWithRegion:CGRectMake(x + width, y, width, height)];
    self.southEast = [PASQuadTree quadTreeWithRegion:CGRectMake(x + width, y + height, width, height)];
    self.southWest = [PASQuadTree quadTreeWithRegion:CGRectMake(x, y + height, width, height)];
    self.northWest = [PASQuadTree quadTreeWithRegion:CGRectMake(x, y, width, height)];
}

EDIT: Написал этот код, чтобы найти наименьший узел (лист), который будет содержать точку:

-(PASQuadTree *)nodeThatWouldContainPoint:(CGPoint)point {

    PASQuadTree *node = nil;

    // If the point is within the region
    if (CGRectContainsPoint(self.region, point)) {

        // Set the node to this node
        node = self;

        // If the node has children
        if (self.northEast != nil) {

            // Recursively check each child to see if it would contain the point
            PASQuadTree *childNode = [self.northEast nodeThatWouldContainPoint:point];
            if (!childNode) childNode = [self.southEast nodeThatWouldContainPoint:point];
            if (!childNode) childNode = [self.southWest nodeThatWouldContainPoint:point];
            if (!childNode) childNode = [self.northWest nodeThatWouldContainPoint:point];
            if (childNode) node = childNode;
        }
    }

    return node;
}

Ближе, но без сигары!

geolocationalgorithmnearest-neighborquadtree

Ответы

Ответ 1 · рейтинг 4 · ElKamina

Найдите наименьший квадрат с точкой поиска в центре и ровно с одной другой точкой внутри этого прямоугольника (вам нужно выполнить логарифмическое количество поисков).

Пусть x будет расстоянием до другой точки.

Затем найдите все точки внутри квадрата со стороной, равной 2x, с центром вокруг вашей первой точки. Для каждой точки внутри этого квадрата рассчитайте расстояние от точки поиска и найдите ближайшую.

ОБНОВЛЕНИЕ: Как найти один квадрат с центром вокруг точки поиска, который содержит ровно одну другую точку?

Найдите случайную точку. Пусть расстояние до этой случайной точки равно x. Найдите все точки в квадрате размера x с центром вокруг точки поиска. Если в этом квадрате ненулевое количество точек, то случайным образом выберите точку и повторите. Если точек нет, увеличьте размер квадрата поиска до (2-0,5)*x (на следующем шаге (2-0,25)*x и так далее.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы