Построение объекта выпуклой оболочки с известными гранями tri angular - PullRequest
0 голосов
/ 30 апреля 2020

TLDR: мне нужно создать объект python для быстрого внутреннего тестирования, похожий на SciPy ConvexHull или DelaunayTriangulation. Уловка в том, что я заранее знаю порядок, в котором должна быть построена триангуляция точек : (6 точек, 8 три angular граней, с определенным c порядком каждой грани) , По сути, я уже знаю, какой должна быть выпуклая оболочка, но мне она нужна в форме, которую я могу использовать с существующими (и оптимизированными!) Библиотеками (например, Scipy пространственные). Как я могу это сделать?

Контекст: Мне нужно построить три angular призму (представьте себе бар Toblerone - 2 торца, 6 боковых граней, все три angular) для того, чтобы сделать некоторые внутренние тесты. Поскольку у меня будет много таких призм, лежащих рядом друг с другом (рядом с их боковыми гранями, представьте себе, что много столбцов Тоблерона стояли на своих концах и рядом друг с другом), я должен быть осторожным, чтобы ни одна область в пространстве не содержалась двумя смежные призмы. Поперечное сечение призмы, как правило, не будет равномерным, поэтому существует возможность перекрытия между смежными призмами, как показано на этой диаграмме приблизительно плоской грани между двумя смежными призмами:

 ____
|\  /|
| \/ |
| /\ | 
|/__\|

Обратите внимание на две разные диагонали построенный вдоль лица - это проблема. Одна призма может разделить грань на два треугольника, используя \ диагональ, а соседняя призма может вместо этого использовать /. Чтобы не перекрывать смежные призмы, мне нужно явно контролировать порядок формирования треугольников, чтобы они всегда использовали одну и ту же диагональ. Это я могу сделать: для каждой призмы, которую мне нужно построить, я заранее знаю, в каком порядке должны быть построены грани три angular. Вот иллюстрация двух смежных призм с правильной общей диагональю между ними: соседние призмы, общая диагональ

Моя проблема заключается в выполнении быстрого тестирования внутренней точки с этими призмами. Ранее я использовал подход, связанный с этим ответом : Delaunay(prism_points).find_simplex(test_points) >= 0. Это быстро, потому что он использует высокооптимизированный библиотечный код, но я не контролирую построение триангуляции, поэтому возможны совпадения.

Если я создаю оболочки как явные np.array объекты (вершины, грани), тогда я могу использовать свой собственный код для выполнения тестов (существует множество возможных подходов, я проецирую лучи и тестирую их на пересечение с каждый три angular лицо). Проблема в том, что это примерно в 100 раз медленнее, чем упомянутый ранее подход find_simplex(). Хотя я уверен, что смог бы получить код немного быстрее, стоит отметить, что этот код уже довольно оптимизирован по сравнению с другим вариантом использования с Cython - я не уверен, что смогу найти здесь дополнительную скорость, которая мне нужна. Что касается неизбежного «вам действительно нужен вопрос скорости», пожалуйста, поверьте мне на слово. Это превращает 5-минутную работу во многие часы.

Мне нужно создать объект, который я могу использовать с внешними оптимизированными библиотеками, сохраняя при этом контроль над гранями tri angular. Добавление дополнительного Cython в мой код - это, конечно, вариант, но такой высокооптимизированный код уже существует, использование которого было бы чрезвычайно предпочтительным.

Спасибо всем, кто может помочь.

1 Ответ

0 голосов
/ 02 мая 2020

Половина решения ... Не точное решение исходного вопроса, но другой способ достижения того же результата. Любую призму tri angular можно разбить ровно на три тетраэдра (см. http://www.alecjacobson.com/weblog/?p=1888). Это конкретный случай c того факта, что любой многогранник можно разбить на тетраэдры, соединив все грани с одной вершиной, если грани еще не включают ее.

Точно зная, как бы я хотел расположить лицевые треугольники моей призмы, я могу определить, какие три тетраэдра будут воспроизводить одинаковую конфигурацию треугольников (с дополнительными гранями, конечно, добавленными внутри самой исходной призмы) , Затем я поочередно формирую триангуляции Делоне вокруг каждого из этих трех тетраэдров (ie, наборы из 4 точек) и выполняю первоначальные тесты внутренних точек: если они совпадают по любому, то я получаю положительный результат для всей призмы. Ключевым моментом является то, что, предоставляя только четыре точки конструктору Делоне за раз, я точно знаю, какую триангуляцию он вернет, поскольку существует только один способ формирования таких тетраэдров (при условии отсутствия геометрии c вырождения).

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

...