Реализация Python для создания треугольной сетки из массива плоских контуров замкнутого цикла

Я немного застрял.

У меня есть трехмерное облако точек (массив из (n,3) вершин), из которого я пытаюсь создать трехмерную треугольную сетку. Пока мне не повезло.

Формат моих данных:

  • (x, y) значения в регулярных (z) интервалах. Думайте о данных как о плоских контурах с замкнутым контуром, сохраняемых срез за срезом в направлении z.
  • Вершины в моих данных должны быть абсолютными позициями для треугольников сетки (т.е. я не хочу, чтобы они сглаживались так, чтобы объем начал менять форму, но линейная интерполяция между слоями прекрасна).

Иллюстрация:

Z=2. : ..x-------x...   <- Contour 2
Z=1.5: ...\......|...   <- Join the two contours into a mesh.
Z=1. : .....x----x...   <- Contour 1
Repeat for n slices, end up with an enclosed 3D triangular mesh.

Вещи, которые я пробовал:

  • Используя Open3D:
    • Метод катящегося шара (шарнира) позволяет заполнить только 75% сетки и оставляет незавершенными большие области (несмотря на диапазон размеров шара). У него есть особые проблемы на верхнем и нижнем срезах, где обычно есть большие зазоры посередине (т.е. плоская поверхность).
    • Метод реконструкции Пуассона слишком сильно сглаживает объем, и у меня больше нет точного представления объема. Это происходит на всех глубинах от 3 до 12.
  • CGAL:
    • Я не могу заставить это работать, хоть убей. SWIG не очень хорош, реализация CGAL с использованием SWIG тоже не очень хороша.
    • Существует две реализации CGAL в PyBind, однако они не включают библиотеки трехмерной триангуляции из CGAL.
  • Изучал другие модули, такие как PyMesh, TriMesh, TetGen, Scikit-Geometry, Shapely и т. Д. И т. Д. Я мог пропустить ответ где-то по ходу дела.

Учитывая, что мои данные представляют собой список плоских контуров замкнутого цикла, кажется, что должно быть какое-то простое решение, позволяющее просто "объединить" контуры смежных срезов в одну большую трехмерную сетку. Вроде как в блендере. Существуют решения, отличные от Python (например, MeshLab), которые могут решить эти проблемы, но мне требуется решение на Python. У кого-нибудь есть идеи? Я немного заглянул в VTK и ITK, но пока не нашел именно то, что ищу.

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

Заранее благодарим вас за любую помощь, это очень ценно. Если есть хороший способ сделать это, который еще не закодирован, я обещаю закодировать его и сделать доступным для людей в моей ситуации:)

3 ответа

На самом деле есть два способа реализовать функциональность meshlab в python:

  1. Первый - это MeshLabXML (https://github.com/3DLIRIOUS/MeshLabXML), третья сторона, это интерфейс сценариев Python для интерфейса сценариев meshlab.
  2. второй - PyMeshLab (https://github.com/cnr-isti-vclab/PyMeshLab), постоянное усилие, предпринимаемое авторами MeshLab (в настоящее время в альфа-стадии), чтобы иметь прямые привязки Python ко всем фильтрам meshlab.

В Journal of Medical Physics есть очень интересная статья под названием "Техническое примечание: алгоритм и программное обеспечение для преобразования данных контурной последовательности лучевой терапии в готовые к печати 3D-структуры", в которой эта проблема описывается достаточно хорошо. Пакеты python не требуются, однако это проще реализовать с помощью numpy. Никаких 3D-пакетов не требуется.

Предлагается полезный отрывок: ...

  1. Определяется количество срезов (2D-контуров), составляющих указанную структуру.
  2. Определяется количество точек в каждом срезе.
  3. Декартовы координаты каждой точки в каждом срезе извлекаются и сохраняются в специальных структурах данных...
  4. Номера точек в каждом срезе (кривой) переставляются таким образом, что начальные точки (точки с индексами 0) являются ближайшими точками между последующими срезами. Перенумерация начинается с точки 0, среза 0 (срез с наименьшей координатой z).
  5. Определяется ориентация (т.е. направление, определяемое увеличением индексов точек по отношению к внутренней / внешней стороне кривой) каждой кривой. Если обнаруживаются различия между срезами, нумерация точек на несовпадающих кривых (и, следовательно, ориентация) меняется на обратную.
  6. Боковая поверхность рассматриваемой конструкции дискретизирована. Точки на соседних слоях сгруппированы по тройкам, составляя треугольные грани для файла STL. Для каждого треугольника соединяются ближайшие точки с последующими индексами из каждого слоя.
  7. Дискретизируются нижняя и верхняя базовые поверхности рассматриваемой конструкции. Программа перебирает все последующие три точки на кривой и проверяет, принадлежат ли они выпуклой части ребра. Если да, они соединяются в фасет, а средняя точка удаляется из дальнейших итераций.

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

В документе также содержится код для этого (для файла DICOM), однако я сам его переписал, и он работает прекрасно.

Надеюсь, это поможет другим! Убедитесь, что вы указали автора в любой работе, в которой это используется.

Недавняя функция pymadcad может делать такие вещи, но не уверен, соответствует ли она вашим точным ожиданиям с точки зрения «поворотного шара» или подобных вещей, ознакомьтесь с документом для смешивания

Начиная со списка контуров, он может генерировать смешанные поверхности для их соединения:

Для вашей цели, я думаю, лучше всего один из:

  • blendpair(line1, line2)
  • junction(*lines)
Другие вопросы по тегам