Как соединяются пути заполнения, чтобы сформировать эффективный путь, учитывающий геометрию объекта?

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

Я не знаю, мой нынешний подход является возможным, но если у меня есть набор векторов, которые представляют путь вокруг объекта и набор векторов, которые представляют сколь угодно большие заполнения шаблона есть ли способ, чтобы союз двух путей вместе с внешней пути (объект раковины) и внутренний контур, является заполнение шаблона вырезать в форме объекта?

ИЗМЕНИТЬ:

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

, 👍4

Обсуждение

Основываясь на ответах, которые у вас уже есть, возможно, имеет смысл отредактировать ваш вопрос, чтобы уточнить, как ответы на самом деле не решают проблему для вас (предполагая, что мы пропустили что-то критическое)., @Sean Houlihane

Вы уверены, что не было бы быстрее и проще взять ваши объекты и запустить их через одно из приложений, которое создает сетку? Каков точный формат и содержимое ваших объектов-то есть как они были созданы, находятся ли они в каком-либо стандартном формате и т. Д.?, @Carl Witthoft

@CarlWitthoft К сожалению, объекты не являются промышленным стандартом, и преобразование их обратно в сетку приведет к поражению цели работы с неявными объектами., @Chris Uchytil

В моей реализации (в c#) Я перебрал список строк, чтобы проверить, совпадает ли начальная или конечная точка с начальной или конечной точкой текущей строки. Если он найден, то я удалил его из списка, и эта новая строка стала текущей. Все найденные строки будут добавлены в очередь точек, в которую я затем превращусь, и в массив точек, чтобы создать путь., @user77232


2 ответа


Лучший ответ:

8

Ответ на этот вопрос в значительной степени сводится к базовой алгебре: программное обеспечение решает проблему с помощью набора функций, которые генерируют шаблон заполнения для ВСЕГО объема сборки, а затем отбрасывают все, что находится за пределами оболочек. Что определяется алгеброй:

Основы

Функция контура

Предположим, что контур тела является функцией $O(l)$, которая имеет параметр $l$ для своей длины. Эта функция может быть вычислена в координатах XY, что дает нам $y\mapsto O^{xy}(x)$, которая параметризуется после $x$и должна давать нам значения $y$ для замкнутой функции $O(l)$.

Функции Заполнения

Теперь давайте сгенерируем функцию для шаблона заполнения. Давайте упростим это для нас и используем шаблон диагоналей: $I_n(x)=x+n\times d$ где $d$ - фиксированный параметр для "расстояния до последней строки", а $n\in\mathbb Z$ - номер строки, в которой 0 проходит начало координат.

Сравнение: Контур=Заполнение

Теперь начальная алгебра! Пусть компьютер решит для каждого $n$ термин $O(x)=I_n(x)$. Результатом должны быть (в лучшем случае) парные точки, все на линейной функции $I_n(x)$. Сначала отсортируйте эти точки по их коррелирующему $n$, а затем по $x$.

Работа с результатами

Давайте предположим, что у нас есть некоторая форма банана, и наши решения для n=0 выглядят следующим образом: $P_{i=1 \to 4}=\{\{1,1\},\{2,2\},\{3,3\},\{4,4\}\}$

Стартер для моделирования

В самых простых случаях мы надеемся получить только парные результаты - контур замкнут, и поэтому каждая линия, проходящая через него, должна разрезать его на две части. Поскольку мы не допускаем, чтобы геометрия была ниже $\{0,0\}$, линия в этом примере будет проходить в тело при первом решении этих точек и выходить из него при втором и так далее. Как правило: он входит в нечетное и выходит в четное i. Таким образом, наши линии заполнения в примере должны соединить $\{1,1\} \to \{2,2\}$ и $\{3,3\} \to \{4,4\}$.

Совершенствование моделирования

проверка касательных

Теперь у нас может быть нечетное число точек, которые решают O(x)=In(x) для данного n. Давайте предположим$P_{i=1 \to 5}=\{1,1\},\{2,2\},\{3,3\},\{4,4\},\{5,5\}$.

Теперь нам нужно быть осторожными, так как одна из этих точек гарантированно будет точкой, в которой $I_n(x)$ является касательной на уровне $O(x)$. Итак, нам нужно знать первый дифференциал $O(x)$ в точках, который является касательной к $O(x)$. Но нам не нужно решать все точки: мы знаем, что первый должен войти, а последний выйти из тела, поэтому нам нужно (в большинстве случаев) решить это только для точек $P_i$ с $i=2 \to i_{max-1}$. Когда $O'(x)=I_n(x)$, мы получаем касательную и удаляем эту точку из списка точек для соединения с линиями заполнения.

Поскольку у нас может быть несколько касательных в наборе точек, эта проверка должна быть выполнена для всех наборов точек, чтобы исключить эти точки.

Кроме того, я использовал "обычно" там намеренно: бывают случаи, когда первая или последняя точка является касательной, и, поскольку это проще сделать, мы должны запустить процесс исключения по всем $P_1 \to P_{max}$!

Новый, уменьшенный набор точек будет представлять собой парный список: $Q_{i=1 \to 4}=\{1,1\},\{2,2\},\{4,4\},\{5,5\}$. Заполнение соединяет $Q_1 \to Q_2$ и $Q_3\to Q_4$.

Превращение точек в векторы

Теперь у нас есть наши точки $Q_1$ и $Q_2$ (или любая другая пара $n \land n+1$, где n-элемент нечетных чисел), как на $I_{n=0}(x)$. Как подключиться? Полегче! $I{n=0}$ - это функция, скорее всего, линейная. Вдоль этой линии должна быть наша соединительная линия от $Q_1\to Q_2$, поэтому движение, которое мы должны построить, является функцией нашего шаблона между точками. Для простого линейного шаблона это будет:

$L_1=\frac{I(x)}{|I(x)|} \times |\vec{Q_2}-\vec{Q_1}|+\vec{Q1}$

Оптимизация

Правильная сортировка

Теперь у нас есть набор строк $L_n$, где, как установлено в последнем абзаце, n-нечетное число, объявляющее, что оно имеет нижний конец $Q_n$и верхний конец $Q_{n+1}$. Как нам грамотно отсортировать эти линии, чтобы у нас было наименьшее движение? Давайте взглянем на наши списки:

  • Список Pi, содержащий все касательные точки и конечные точки. Не очень полезно.
  • Сокращенный список $Q_{n}$, содержащий все начальные и конечные точки; он отсортирован таким образом, что нечетные числа являются началом и четными концами.
  • Список $L_n$ с i всегда нечетным числом, который содержит пути движения (=линии) от каждого $Q_{n}$ до соответствующего $Q_{n+1}$

Кратчайшее перемещение между отпечатками?

Теперь давайте еще раз немного посчитаем: каков ближайший $Q_{a}$ к $Q_{n+1}$, на котором мы закончили после выполнения движения $L_n$? Ну, во-первых, нам нужно убедиться, что мы не вернемся к уже перемещенным путям, поэтому давайте составим новый список $R_{i}$, который содержит все $Q_{i}$, в которые мы еще не переместились.

Итак, каков ближайший $R_{i}$ к конечной точке пути $L_e$, который мы только что переместили? Ну, полегче! Решите $min|R_i-L_e|$, где i-все нечетные числа в списке $R_{i}$ и $L_e$ точка, в которую была отправлена печатающая головка в конце последнего движения

наименьшее количество изменений направления?

Постоянное перемещение только на кратчайшее расстояние может привести к большому количеству изменений направления. Поэтому, возможно, было бы хорошей идеей сохранить списки точек, отсортированных по параметру n функции $l_n(x)$, которая в первую очередь создала точки, и запустить этот список от минимального числа n, которое сгенерировало точки (которые могут быть ниже 0), до максимального числа n, которое сгенерировало точки.

оптимизация изменений направления и траекторий движения

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

До сих пор все наши линейные функции $l_n(x)$ имели один и тот же вектор и просто отличались друг от друга начальной точкой. Таким образом, все начала были на одной стороне тела, все концы-на противоположной. С помощью очень простого трюка с функцией заполнения мы можем создать группу функций, которые чередуют стороны конечных точек между каждой строкой, просто добавив обратный элемент:

$L_n(x)=-1^n\times l_n(x)$

Теперь, после того, как все движения с одинаковыми $n$ будут выполнены, проверьте ближайшую начальную точку (которая должна быть на той же стороне, но необязательно на соседней линии) и полностью спуститесь по этой линии, исключив эти точки из списка оставшихся точек $R_{i}$. Вернувшись на ту сторону, с которой мы начали сначала, мы снова ищем ближайшую неиспользуемую точку, пробегаем по этой линии, промываем и повторяем.


,

Просто небольшое уточнение. Ориентирован ли этот банан так, чтобы линия при n=0 врезалась в него дважды с зазором посередине? Касательная имеет смысл. Я работал с неявными пересечениями тора и луча, и это работает точно так же. Нечетное означает пасущийся (касательный луч), а четное-проникающий луч. Теперь мой вопрос в том, как вы соединяете конец этой первой строки со следующей строкой? Вот тут-то я и застрял. Формирование траектории между всеми линиями разреза заполнителя для формирования траектории., @Chris Uchytil

да, банан в примере 1 согнут таким образом, что он изгибается вокруг середины "промежутка"., @Trish

@ChrisUchytil Я разработал несколько оптимизаций, которые вы могли бы попробовать: для минимального количества изменений движения, а затем для ближайшей строки для печати. Имейте в виду, что это оптимизация не расчетной длины, а траектории движения., @Trish


3

простой ответ-математика, но вы это точно знаете

более описательный ответ (но все еще простой и без математики) более или менее выглядит следующим образом

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

и вуаля ;)

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

как правило, есть отличная библиотека, которую вы могли бы попробовать

https://sourceforge.net/projects/jsclipper/

Дополнение

простая сортировка (против)по часовой стрелке может быть такой

  • установите центральную точку объекта (периметр)
  • начните с 1200 часов и рассчитайте модуль и угол каждой точки среза
  • отсортируйте их по углу

это все еще очень просто и работает только для выпуклого множества

,

Шаг 5: "сортировка точек разреза в некотором порядке ("некоторые" - определенно самая трудная задача)" - вот где я застрял., @Chris Uchytil

ну, самый простой способ, кажется, сортировать (против)по часовой стрелке ;), @darth pixel