Структура данных для точек запроса, которые лежат внутри треугольника - PullRequest
3 голосов
/ 30 ноября 2011

У меня есть несколько 2D-данных, которые содержат ребра, которые были растеризованы в пиксели.Я хочу реализовать эффективную структуру данных, которая возвращает все краевые пиксели, которые лежат в не выровненном по оси 2D треугольнике.

Spatial query for sparse data

На рисунке показановизуализация проблемы, где белый цвет обозначает растеризованные ребра, а красный визуализирует треугольник запроса.Результатом будут все белые пиксели, которые лежат на границе или внутри красного треугольника.

  • При дальнейшем рассмотрении изображения можно заметить, что у нас есть разреженный логический данные, означающие, что если мы обозначим черные пиксели с 0 и белые пиксели с 1, то число 1 в данных будет намного меньше, чем число 0.Следовательно, растеризация красного треугольника и проверка для каждой точки на его внутренней стороне, является ли он белым или черным, не самый эффективный подход.

  • Помимо разреженности данных;поскольку белые пиксели происходят от краев, по своей природе они связаны друг с другом .Однако на стыках с другими линиями у них более двух соседей.Пиксели, которые находятся на стыке, должны быть возвращены только один раз.

  • Данные должны обрабатываться в режиме реального времени , но без помощи графического процессора.Будет несколько запросов для различного содержимого треугольника, и после каждого из них точек могут быть удалены из структуры данных *1029*.Однако новые точки больше не будут вставляться после начального заполнения структуры данных.

  • Треугольники запроса уже известны , когда прибывают растеризованные ребра.

  • На больше треугольников запросов, чем ребер данных .

Существует множество структур пространственных данных имеется в наличии.Однако мне интересно, какой из них лучше для моей проблемы.Я готов внедрить высокооптимизированную структуру данных для решения этой проблемы, так как она станет ключевым элементом проекта.Поэтому приветствуются также сочетания или сокращения структур данных!

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

    Однако я не уверен, насколько хорошо R-деревья будут вести себяпоскольку данные, основанные на ребрах, не могут быть легко сгруппированы в прямоугольники, так как точки сгруппированы вместе на узких линиях, а не согнуты.

    Я не уверен, что имеет смысл предварительно построить структуруR-дерева с использованием информации о треугольниках запросов, которые будут сделаны, как только структура будет заполнена (как уже упоминалось ранее, треугольники запросов уже известны, когда поступают данные).

  • Решение проблемы, по-видимому, также является правильным решением, где я использую дерево 2-мерный интервал , чтобы получить для каждого белого пикселя список всех треугольников, которые его содержат.Затем он уже может быть сохранен во всех этих результирующих наборах и может быть немедленно возвращен при поступлении запроса.Тем не менее, я не уверен, как это выполняется, если количество треугольников больше, чем количество ребер, но все же меньше, чем количество белых пикселей (поскольку ребро в основном разбито на ~ 20-50 пикселей).

  • Структура данных, которая использовала бы то, что белые пиксели имеют чаще всего белые пиксели в качестве соседей, может показаться наиболее эффективной.Однако до сих пор я ничего не мог найти о такой вещи.

Ответы [ 2 ]

1 голос
/ 30 ноября 2011

Разложить треугольник запроса на n * 3 строки.Для каждой тестируемой точки вы можете оценить, на какой стороне каждой линии она находится.Все остальное - логическая логика.

РЕДАКТИРОВАТЬ: поскольку ваши точки растеризуются, вы можете предварительно вычислить точки на линиях сканирования, где линия сканирования входит в конкретный треугольник запроса или выходит из него (= пересекает одну из 3n строк выше && включена«внутрь» двух других линий, которые участвуют в этом конкретном треугольнике)

ОБНОВЛЕНИЕ: инициировано другой темой ( Как узнать, находится ли точка в треугольнике в 3D? )Я добавлю код, чтобы доказать, что невыпуклый случай можно выразить в терминах "на какой стороне каждой линии находится точка".Поскольку я ленивый, я буду использовать L-образную форму.ИМХО другие невыпуклые формы можно обрабатывать аналогично.Линии параллельны осям X и Y, но это опять-таки лень.

/*

Y
| +-+
| | |
| | +-+
| |   |
| +---+
|
0------ X
the line pieces:
Horizontal:
(x0,y0) - (x2,y0)
(x1,y1) - (x2,y1)
(x0,y2) - (x1,y2)
Vertical:
(x0,y0) - (x0,y2)
(x1,y1) - (x1,y2)
(x2,y0) - (x2,y1)

The lines:
(x==x0)
(x==x1)
(x==x2)
(y==y0)
(y==y1)
(x==y2)

Combine them:
**/

#define x0 2
#define x1 4
#define x2 6

#define y0 2
#define y1 4
#define y2 6

#include <stdio.h>

int inside(int x, int y)
{   

switch(  (x<x0 ?0:1)
    +(x<x1 ?0:2)
    +(x<x2 ?0:4)
    +(y<y0 ?0:8)
    +(y<y1 ?0:16)
    +(y<y2 ?0:32) ) {

case 1+8:
case 1+2+8:
case 1+8+16:
    return 1;
default: return 0;
    }
}

int main(void)
{
int xx,yy,res;
while (1) {
     res = scanf("%d %d", &xx, &yy);
     if (res < 2) continue;
     res = inside(xx, yy);
     printf("(%d,%d) := %d\n", xx, yy,res);
    }
return 0;
}
0 голосов
/ 01 декабря 2011

Есть пара вычислительно-геометрических алгоритмов, которые, я думаю, в тандеме дали бы хорошие результаты.

  1. Вычислить плоское подразделение, которое содержит все ребра треугольника.(Это немного сложнее, чем вычисление всех пересечений ребер треугольника.) Для каждой грани составьте список треугольников, содержащих эту грань.Это, по общему признанию, наихудший случай, но это только тогда, когда треугольники сильно перекрываются (и я не могу не думать, что есть способ сжать его до квадратичного).

  2. Найтикаждый пиксель в подразделении (то есть выяснить, к какой стороне он принадлежит).Первый в каждом ребре будет стоить O (log n), но если у вас будет локальность после этого, может быть способ сократить вычисления в среднем до чего-то вроде O (1).(Например, если вы используете метод трапеции и сохраняете список трапеций, которые содержали последнюю точку, вы можете перемещаться вверх по списку до тех пор, пока не найдете трапецию, которая содержит текущую точку, и продолжить работу вниз.STL устанавливает вставку, передавая итератор около точки вставки.)

...