Импорт объекта САПР в Python и сохранение в виде массива

Я использую Autodesk Fusion 360 для моделирования трехмерной детали (см. Рисунок ниже), которую затем можно экспортировать и сохранить в виде файла.step, .iges, .sat или.smt.

То, чего я пытаюсь добиться, - это преобразовать эту часть в трехмерный массив в Python. Каждый элемент массива будет 0 или 1, чтобы указать, есть ли твердый материал в этой позиции или нет материала вообще (воздух).

Например, если мой объект имеет размеры фигуры, каждый элемент массива размером 100x100x50 будет представлять объем 1 мм3 объекта. Все голубые маленькие кубики будут иметь значение 1, чтобы показать, что в этой позиции находится твердый материал, а красный куб будет иметь значение 0, чтобы указать, что это пространство не состоит из твердого материала.

Можно ли это сделать с помощью API FreeCAD? Или есть какой-то другой способ импортировать файл.step/.iges/.sat/.smt в Python и конвертировать / анализировать его для создания необходимого массива?

3 ответа

Я наконец нашел способ, который работает для меня и мог бы на самом деле лучше объяснить, чего я пытался достичь.

Очевидно, у FreeCAD есть опция, где после активации рабочей среды "Точки" вы можете преобразовать свой объект в " облако точек". Каждая точка не имеет никакой массы, и всю новую структуру облака точек можно экспортировать в разделенный пробелами файл.asc.

После этого легко импортировать это в массивы Python. Я лично использовал воксельное представление для визуализации импортированного объекта в Python, что можно сделать с помощью последней версии matplotlib или mayavi (это две, которые я пробовал по крайней мере).

Вы можете проверить, лежит ли точка внутри тела с помощью:

solid_shape.isInside(point:App.Vector, tolerance:float, on_boundary_is_inside:bool)

пример:

import numpy as np
import FreeCAD as App
import Part

num_pts = 50

shape = Part.makeSphere(1)  # radius
bb = shape.BoundBox
x = np.linspace(bb.XMin, bb.XMax, num_pts)
y = np.linspace(bb.YMin, bb.YMax, num_pts)
z = np.linspace(bb.ZMin, bb.ZMax, num_pts)

mesh_x = np.array([[x] * num_pts] * num_pts).transpose(0, 1, 2)
mesh_y = np.array([[y] * num_pts] * num_pts).transpose(2, 0, 1)
mesh_z = np.array([[z] * num_pts] * num_pts).transpose(1, 2, 0)

mesh = np.array([mesh_x.flatten(), mesh_y.flatten(), mesh_z.flatten()]).T
bool_array = np.array([shape.isInside(App.Vector(p), 0.000001, False) for p in mesh])

v_r = float(sum(bool_array)) / float(len(bool_array))
v_r   # estimation of Volumeratio

Возможно разделение части на маленькие части, следуя примеру в/Mod/Part/BOPTools/SplitFeatures.py, Но он не готов к использованию для ваших нужд и требует времени для принятия. Но определенно можно разделить деталь на множество частей любой формы, которая вам нравится: https://www.freecadweb.org/wiki/Part_Slice

Затем вы можете использовать этот код для создания массива:

import FreeCAD
import Part
import numpy as np

# Creating sample parts
solid_ = Part.makeBox(10, 10, 10)
shell_ = Part.makeShell(solid_.Shells)
part_compound = [solid_, shell_]

# Generate numpy array
result = []
for part in part_compound:
    result = [*result, [part.CenterOfMass.x,
                        part.CenterOfMass.y,
                        part.CenterOfMass.z,
                        isinstance(part, Part.Solid)]]
print(np.array(result))

Это приведет к массиву, где будет обозначен центр масс каждой части, его x,y,z и четвертый элемент будут равны 1, если эта часть является сплошной, и 0 в противном случае.

Код совместим только с Python 3.6, поэтому используйте образ докера: https://github.com/ZhukovGreen/docker-freecad-cli

Другие вопросы по тегам