分布式处理和脚底板文件
This commit is contained in:
1 parent
f4254f0051
commit
2c036235a6
19 files changed
+1932
-56
No files matched your search
@@ -0,0 +1,148 @@
|
||||
import bpy, sys, os, math, bmesh
|
||||
# from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
def gen_qrcode(pid):
|
||||
fontHeightMax = 40
|
||||
fontsize = 1
|
||||
qr = qrcode.QRCode()
|
||||
qr.border = 2
|
||||
qr.add_data(pid)
|
||||
img = qr.make_image(fit=True)
|
||||
img = img.transform((250, 294), Image.Transform.EXTENT, (0, 0, 250, 294), fillcolor='white')
|
||||
|
||||
cwd = os.path.dirname(os.path.abspath(__file__))
|
||||
fontfile = os.path.join(cwd, 'fonts', 'Helvetica.ttf')
|
||||
font = ImageFont.truetype(fontfile, fontsize)
|
||||
while font.getsize(pid)[1] <= fontHeightMax and font.getsize(pid)[0] <= 240:
|
||||
fontsize += 1
|
||||
font = ImageFont.truetype(fontfile, fontsize)
|
||||
fontsize -= 1
|
||||
|
||||
captionx = (250 - font.getsize(pid)[0]) / 2
|
||||
draw = ImageDraw.Draw(img)
|
||||
draw.text((captionx, 242), pid, font=font)
|
||||
img.show()
|
||||
img.save(f'{workdir}{pid}.png')
|
||||
|
||||
def auto_rotate(pid):
|
||||
# 坐标复位
|
||||
obj = bpy.context.selected_objects[0]
|
||||
obj.rotation_euler[0] = 0
|
||||
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
|
||||
bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_VOLUME', center='MEDIAN')
|
||||
bpy.ops.object.align(align_mode='OPT_1', relative_to='OPT_1', align_axis={'Y', 'Z'})
|
||||
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
|
||||
# bpy.ops.export_scene.obj(filepath=f'{workdir}{pid}_align_yz.obj')
|
||||
|
||||
# 躺平到打印机排版需要的坐标与角度
|
||||
obj.rotation_euler = (math.radians(90), math.radians(90), 0)
|
||||
bpy.ops.object.transform_apply(rotation=True)
|
||||
# bpy.ops.export_scene.obj(filepath=f'{workdir}{pid}_rotate_y90.obj')
|
||||
|
||||
heights = {}
|
||||
min_height = 999999
|
||||
min_i = 0
|
||||
max_height = -999999
|
||||
max_i = 0
|
||||
|
||||
bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_VOLUME', center='MEDIAN')
|
||||
bpy.ops.object.align(align_mode='OPT_1', relative_to='OPT_3', align_axis={'X', 'Y', 'Z'})
|
||||
|
||||
# 步进精度2旋转X轴到180度,找到Y轴最低点和最高点,其中最低点为打印
|
||||
step = 2
|
||||
i = 0
|
||||
while i <= 180:
|
||||
obj.rotation_euler = (math.radians(step), 0, 0)
|
||||
bpy.ops.object.transform_apply(rotation=True)
|
||||
if obj.dimensions[1] < min_height:
|
||||
min_height = obj.dimensions[1]
|
||||
min_i = i
|
||||
if obj.dimensions[1] > max_height:
|
||||
max_height = obj.dimensions[1]
|
||||
max_i = i
|
||||
heights[i] = (obj.dimensions[0], obj.dimensions[1], obj.dimensions[2])
|
||||
print(i, heights[i])
|
||||
i += step
|
||||
|
||||
obj.rotation_euler = (0, 0, 0)
|
||||
bpy.ops.object.transform_apply(rotation=True)
|
||||
obj.rotation_euler = (math.radians(min_i), 0, 0)
|
||||
bpy.ops.object.transform_apply(rotation=True)
|
||||
bpy.ops.export_scene.obj(filepath=f'{workdir}{pid}.obj')
|
||||
|
||||
# obj.rotation_euler = (0, 0, 0)
|
||||
# bpy.ops.object.transform_apply(rotation=True)
|
||||
# obj.rotation_euler = (math.radians(max_i), 0, 0)
|
||||
# bpy.ops.object.transform_apply(rotation=True)
|
||||
# bpy.ops.export_scene.obj(filepath=f'{workdir}{pid}_maxz.obj')
|
||||
print(f'最小高度: {min_height} @ {heights[min_i]}min_i:{min_i}' , f'最大高度: {max_height} @ {heights[max_i]}max_i:{max_i}')
|
||||
|
||||
def cut_obj(pid):
|
||||
# 根据定位用一个面切割模型
|
||||
offset = 45.5
|
||||
radian = math.radians(90)
|
||||
bpy.ops.mesh.primitive_plane_add(size=200, enter_editmode=False, align='WORLD', location=(offset, 0, 0), rotation=(0, radian, 0), scale=(1, 1, 1))
|
||||
|
||||
# 布尔切割,保留交集切面
|
||||
bpy.ops.object.modifier_add(type='BOOLEAN')
|
||||
bpy.context.object.modifiers["Boolean"].object = bpy.data.objects[pid]
|
||||
bpy.context.object.modifiers["Boolean"].operation = 'INTERSECT'
|
||||
bpy.context.object.modifiers["Boolean"].solver = 'FAST'
|
||||
bpy.ops.object.modifier_apply(modifier="Boolean")
|
||||
|
||||
# 拆分切割面为多个多边形,然后遍历多边形,找到最大的面积
|
||||
bpy.ops.mesh.separate(type='LOOSE')
|
||||
|
||||
max_area = 0
|
||||
max_obj = None
|
||||
for obj in bpy.data.objects:
|
||||
if obj.type == 'MESH' and obj.name.startswith('Plane'):
|
||||
area = obj.data.polygons[0].area
|
||||
if area > max_area:
|
||||
max_area = area
|
||||
max_obj = obj
|
||||
|
||||
# 选中最大面积的多边形,然后计算中心点
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
max_obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = max_obj
|
||||
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
|
||||
|
||||
return max_obj
|
||||
|
||||
def main():
|
||||
filename = f'{workdir}{pid}.obj'
|
||||
print('正在处理:', filename)
|
||||
bpy.ops.import_scene.obj(filepath=filename)
|
||||
|
||||
auto_rotate(pid)
|
||||
# gen_qrcode(pid)
|
||||
|
||||
# 脚底切片,查找最大面积,计算中心点,计算坐标位置,怼入二维码贴片
|
||||
max_obj = cut_obj(pid)
|
||||
bpy.ops.import_scene.obj(filepath=f'{workdir}qr.obj')
|
||||
qr_obj = bpy.data.objects['Cube']
|
||||
shore_obj = bpy.data.objects['Cube.001']
|
||||
# bpy.data.objects['Cube'].origin_set(type='ORIGIN_GEOMETRY')
|
||||
# bpy.data.objects['Cube.001'].origin_set(type='ORIGIN_GEOMETRY')
|
||||
# bpy.data.objects['Cube.002'].origin_set(type='ORIGIN_GEOMETRY')
|
||||
# bpy.data.objects['Cube.003'].origin_set(type='ORIGIN_GEOMETRY')
|
||||
bpy.data.objects['Cube'] = (math.radians(90), math.radians(90), 0)
|
||||
bpy.data.objects['Cube.001'].rotation_euler = (math.radians(90), math.radians(90), 0)
|
||||
bpy.data.objects['Cube.002'].rotation_euler = (math.radians(90), math.radians(90), 0)
|
||||
bpy.data.objects['Cube.003'].rotation_euler = (math.radians(90), math.radians(90), 0)
|
||||
qr_obj.location = (max_obj.location[0] - qr_obj.dimensions[1] / 2 - shore_obj.dimensions[1]/2, max_obj.location[1], max_obj.location[2])
|
||||
shore_obj.location = (qr_obj.location[0] - shore_obj.dimensions[1]/2, max_obj.location[1], max_obj.location[2])
|
||||
bpy.data.objects['Cube.002'].location = (shore_obj.location[0], shore_obj.location[1]+0.2, shore_obj.location[2])
|
||||
bpy.data.objects['Cube.003'].location = (shore_obj.location[0], shore_obj.location[1]-0.2, shore_obj.location[2])
|
||||
|
||||
bpy.ops.object.transform_apply(rotation=True, location=True, scale=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
workdir = '/home/water/Downloads/'
|
||||
if len(sys.argv) - (sys.argv.index("--") +1) < 1:
|
||||
print("Usage: blender -b -P auto_qrcode.py -- <pid>")
|
||||
sys.exit(1)
|
||||
pid = sys.argv[sys.argv.index("--") + 1]
|
||||
main()
|
||||
Reference in new issue
Block a user