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

Например, вершины на изображении ниже отсортированы случайным образом. Можете ли вы отсортировать их последовательно?

Я пытался отсортировать их по оси x или оси z, но это не сработало.

Учтите, что ваше решение должно работать со сложными формами:

Ответы
Сортировка индексов вершин.
Ответ здесь https://blender.stackexchange.com/a/36619/15543 показывает, как сортировать индексы вершин с помощью bmesh.
Ответьте здесь. Как упорядочить список вершин по позиции? каким-то образом показывает, как обходить края заказа.
Чтобы быть уверенным, нужно пройти по ребрам, как показано выше, пока первая вершина не встретится повторно (так как это цикл), и использовать это для порядка. Оставлю на ваше усмотрение собрать сценарий из того, что здесь
Как показано в ответе @ Leander
Кратчайший путь
Использование сценария из раздела Что такое bmesh, эквивалентное bpy.ops.mesh.shortest_path_select ()? может выбрать ребро как связь между первой и последней индексной вершиной, временно удалить его, найти кратчайший оставшийся путь (единственный путь) от ребер двух вершин. Восстановите край.
Порядок намотки торца
Вместо этого для замкнутого цикла, подобного приведенному выше, команда может заполнить ngon, использовать вершины граней ngon в качестве порядка (порядок намотки), пересортировать вершины и удалить созданную грань ngon.
import bpy
import bmesh
ob = bpy.context.object
assert ob.type == "MESH"
me = ob.data
bm = bmesh.from_edit_mesh(me)
f = bmesh.ops.contextual_create(
bm,
geom=bm.verts[:] + bm.edges[:],
)["faces"][0]
for i, v in enumerate(f.verts):
v.index = i
bm.verts.sort()
bm.faces.remove(f)
bmesh.update_edit_mesh(me)
Выберите первую вершину и по часовой стрелке или против
Чтобы выбрать нулевую вершину и обеспечить индексацию против часовой стрелки (при виде сверху)
Запустите в режиме редактирования, выберите вершину, у которой вы хотите иметь индекс 0. Предполагается, что форма лежит в плоскости XY. Если нормаль созданной грани направлена вниз, намотка переворачивается.

import bpy
import bmesh
from mathutils import Vector
ob = bpy.context.object
assert ob.type == "MESH"
me = ob.data
bm = bmesh.from_edit_mesh(me)
v0 = bm.select_history.active
f = bmesh.ops.contextual_create(
bm,
geom=bm.verts[:] + bm.edges[:],
)["faces"][0]
fverts = f.verts[:]
if f.normal.dot((0, 0, 1)) < 0:
fverts.reverse()
for i, v in enumerate(fverts):
v.index = i
if v is v0:
iv0 = i
for v in fverts:
v.index = (v.index - iv0) % len(fverts)
bm.verts.sort()
bm.faces.remove(f)
bmesh.update_edit_mesh(me)
- Добавьте шейп-ключ.
- В этом shapekey разместите вершины, которые должны быть первыми и последними, на большом расстоянии друг от друга по оси x.
- Выделите все остальные (между вершинами).
- Выберите W> Smooth Vertices и установите большое количество итераций. Вершины будут сглажены.
- Отсортируйте их по оси абсцисс. Сетка> Сортировать элементы> Ось X
- Удалите шейп-ключ.

Используя Python, вы можете обойти края и присвоить им новый индекс.
import bpy
import bmesh
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
# index of the start vertex
initial = bm.verts[0]
vert = initial
prev = None
for i in range(len(bm.verts)):
print(vert.index, i)
vert.index = i
next = None
adjacent = []
for v in [e.other_vert(vert) for e in vert.link_edges]:
if (v != prev and v != initial):
next = v
if next == None: break
prev, vert = vert, next
bm.verts.sort()
bmesh.update_edit_mesh(me)
Без скрипта:
- V разделите меш в вершине, которую вы хотите сделать первой, если это еще не сделано.
- Заголовок> Меню объекта> Преобразовать сетку в кривую
- Режим редактирования, контекстное меню, при необходимости переключить направление сплайна
- Режим объекта, контекстное меню, Преобразовать обратно в сетку.

Я не знаю, почему Convert не находится в меню правой кнопки мыши в режиме Object для меша, это немного раздражает.
Если исключить уточнения, предоставленные @Seyed, сценарий будет следующим:
import bpy
bpy.ops.object.convert(target='CURVE', keep_original= False)
bpy.ops.object.convert(target='MESH', keep_original= False)