Нахождение точек треугольников в


16

Предположим, у меня есть двумерная сетка, состоящая из непересекающихся треугольников и набора точек . Как лучше всего определить, в каком треугольнике лежит каждая из точек?{Tk}k=1N{pi}i=1Mk=1NTK

Например, на следующем изображении мы имеем , p 2T 4 , p 3T 2 , поэтому я хотел бы функцию f, которая возвращает список f ( p 1 , p 2 , p 3 ) = [ 2 , 4 , 2 ] .p1T2p2T4p3T2ff(p1,p2,p3)=[2,4,2]

введите описание изображения здесь

Matlab имеет функцию pointlocation, которая делает то, что я хочу для сеток Делоне, но не работает для общих сеток.

Моя первая (тупая) мысль, что для всех узлов нужно пройти через все треугольники, чтобы выяснить, в каком треугольнике находится p i . Однако это крайне неэффективно - вам, возможно, придется пройти через каждый треугольник для каждой точки, поэтому это может занять O ( N M ) работы.pipiO(NM)

Моя следующая мысль: для всех точек найти ближайший узел сетки с помощью поиска ближайших соседей, а затем просмотреть треугольники, прикрепленные к этому ближайшему узлу. В этом случае работа была бы O ( a M l o g ( N ) ) , где a - максимальное количество треугольников, прикрепленных к любому узлу в сетке. Есть несколько решаемых, но раздражающих проблем с этим подходом,piO(aMlog(N))a

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

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

Благодарность!

Ответы:


16

Обычный метод случайного скачкообразного изменения должен работать. По сути, начните с любого треугольника сетки, затем определите, на каком из ребер целевая точка лежит с противоположной стороны. То есть определите, какие из ребер, если они растянуты до линии, отделяют точку от внутренней части треугольника. Когда есть две возможности, выберите одну наугад, рассмотрите треугольник, который смежен с этим общим краем, и повторите. Рандомизация должна сделать этот метод сходящимся с вероятностью 1 для триангуляций Делоне, и я не могу придумать причину, по которой он не будет работать для произвольных триангуляций.

O(logN)O(MlogN)M точек. Однако, если вы сортируете свои точки по местоположению (например, сначала по порядку кривой Гильберта), вы можете инициализировать каждый новый запрос треугольником предыдущего запроса, чтобы еще больше сократить время выполнения (я не теоретик CS, поэтому могу Я не скажу вам, что там будет с большой О).

Edit2 : найдено этот PDF-файл, описывающий такую ​​"прогулочную" схему, которая гарантированно прекращается, и рассматривает более наивные подходы.

Другой альтернативой использованию квадрид деревьев является использование иерархии триангуляции. Смотрите Оливье Девиллерс. Улучшенная инкрементная рандомизированная триангуляция Делоне. В учеб. 14 лет ACM Sympos. Вычи. Geom., Стр. 106-115, 1998. Это работает лучше всего для триангуляций Делоне, но может также работать и для не Делоне.

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


Виктор - ты знаешь какой-нибудь код с открытым исходным кодом, который подразумевает подход скачкообразной перестройки? Похоже, это будет очень хорошим решением для моего случая. (модель отслеживания частиц, управляемая текущими полями в сетке traingualr) -Спасибо
Крис Баркер

У меня есть код для этого, и я могу отправить его вам; это в C / C ++. Еще не успел почистить его и опубликовать на Github. Мне приходилось писать это, по крайней мере, дважды в моей жизни, один раз со структурой данных с половинными гранями, снова с квадратным, но это легко можно использовать, когда они недоступны и вам нужно построить топологическую структуру самостоятельно. Посмотрите на странице моего профиля для моего сайта, где вы можете найти контактную информацию. Мы можем обсудить это дальше в автономном режиме.
Виктор Лю

Я близок к тому, чтобы закончить реализацию этого в Matlab, используя упорядочение по кривой Гильберта и рандомизированный обход треугольника. Это исследовательский код: не оптимизированный, не документированный и т. Д., Но все же довольно быстрый - я могу дать вам код, если вам интересно.
Ник Алджер

2
О: "" "Прыжок по кромке должен быть O (logN)" "" Я не вижу этого. Например, в патологическом случае большой длинной полоски треугольника (например, узкого канала только на ширине треугольника), в худшем случае вам нужно будет перепрыгнуть от одного треугольника до следующего вплоть до конца. В среднем случае на полпути. Таким образом, если вы удвоите количество треугольников, это будет O (N). В более нормальном случае прямоугольного расположения треугольников я бы ожидал O (sqrt (N)). Или я что-то упустил? -Крис
Chris Barker

@Chris - Добро пожаловать в Scicomp! Как часть ведения домашнего хозяйства Scicomp, я перенес ваши ответы и последующий разговор в качестве комментариев к ответу Виктора. Мы с нетерпением ждем вашего участия на сайте.
Арон Ахмадиа

8

Я не уверен, что ваше решение на самом деле правильно. Рассмотрим ситуацию, когда у вас есть эти узлы:

  • A: (-3,1)
  • B: (0, 2)
  • C: (3, 1)
  • D: (0, -5)

Есть треугольники ABC и ACD. Теперь B является ближайшей точкой к началу координат, но начало координат находится в треугольнике ACD, который не содержит B.

O(NM) , но, как правило, будет быстрее - особенно для триангуляций Делоне и триангуляций, близких к этому в некотором смысле.

Я бы рассмотрел вариант построения квадродерева, которое содержит сами треугольники. Т.е. у вас есть четвертичное дерево, которое хранится в каждом узле (что соответствует ограничительной рамке):

  • Координаты, по которым разбивается прямоугольник, или, альтернативно, ограничивающие прямоугольники четырех поддеревьев;
  • Указатели на поддеревья;
  • Набор треугольников, которые полностью попадают в ограничивающую рамку этого прямоугольника, но не полностью в любое из четырех поддеревьев. Другими словами, треугольники, которые пересекаются с любым из двух разделительных отрезков линии дерева квадрантов.

nnlognO(NM)


Хм, ты прав. С другой стороны, если бы триангуляция была Делоне, я думаю, что ближайший сосед будет работать. Это слишком ограничительно для того, что я пытаюсь сделать, но в случае Делоне рассмотрим двойственную диаграмму Вороного - ячейки Вороного - это множество точек, ближайших к узлу, и все ребра треугольников Делоне встречаются с ребрами Вороного. ячейки под прямым углом, поэтому любая точка должна быть в треугольнике, соединенном с ближайшим узлом. Интересно, так ли работает функция pointLocation в matlab?
Ник Алджер

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.