整理文件夹及架构,加入打印机页面,octo反代有问题

This commit is contained in:
2026-04-14 00:11:00 +08:00
parent 1de35f21d7
commit 570af7c225
54 changed files with 939 additions and 292 deletions

107
app/utils/stl_merger.py Normal file
View File

@@ -0,0 +1,107 @@
import struct
import math
import os
def merge_stls(input_files, output_path):
try:
from stl import mesh
import numpy as np
meshes = []
for path, matrix in input_files:
try:
# 重新换回轻量级的 numpy-stl 以防内存溢出 (OOM)
m = mesh.Mesh.from_file(path)
mat = np.array(matrix, dtype=np.float64).reshape((4, 4)).T
vectors = m.vectors.reshape(-1, 3)
hom_vectors = np.hstack((vectors, np.ones((len(vectors), 1), dtype=np.float32)))
transformed = (mat @ hom_vectors.T).T
m.vectors = transformed[:, :3].reshape(-1, 3, 3)
# 检测缩放矩阵是否引发镜像翻转 (行列式为负数)
det = np.linalg.det(mat[:3, :3])
if det < 0:
# 发生镜像反转不仅法线会反向三角形三个顶点的顺逆时针Winding Order也会错乱
# 强行交换每个三角形的顶点2和顶点3以纠正渲染正反面
m.vectors[:, [1, 2]] = m.vectors[:, [2, 1]]
m.update_normals()
meshes.append(m)
except Exception as e:
print(f"Error processing path {path} with stl mesh: {e}")
if not meshes:
return
if len(meshes) == 1:
meshes[0].save(output_path)
return
merged_data = np.concatenate([m.data for m in meshes])
merged_mesh = mesh.Mesh(merged_data)
merged_mesh.save(output_path)
return
except Exception as e:
print(f"Mesh fast-merge failed: {e}. Falling back to struct parsing.")
# Extreme fallback just in case no stl libraries work
total_faces = 0
meshes_data = []
for path, matrix in input_files:
with open(path, 'rb') as f:
f.read(80)
faces = struct.unpack('<I', f.read(4))[0]
data = f.read(faces * 50)
def apply_m(_x, _y, _z):
w = _x * matrix[3] + _y * matrix[7] + _z * matrix[11] + matrix[15]
nx = (_x * matrix[0] + _y * matrix[4] + _z * matrix[8] + matrix[12]) / w
ny = (_x * matrix[1] + _y * matrix[5] + _z * matrix[9] + matrix[13]) / w
nz = (_x * matrix[2] + _y * matrix[6] + _z * matrix[10] + matrix[14]) / w
return nx, ny, nz
new_data = bytearray(faces * 50)
src_offset = 0
dst_offset = 0
for _ in range(faces):
n_x, n_y, n_z, v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z, attr = struct.unpack_from('<12fH', data, src_offset)
nv1x, nv1y, nv1z = apply_m(v1x, v1y, v1z)
nv2x, nv2y, nv2z = apply_m(v2x, v2y, v2z)
nv3x, nv3y, nv3z = apply_m(v3x, v3y, v3z)
# Recalculate normal properly using cross product to fix flipped/sheared surfaces
Ux = nv2x - nv1x
Uy = nv2y - nv1y
Uz = nv2z - nv1z
Vx = nv3x - nv1x
Vy = nv3y - nv1y
Vz = nv3z - nv1z
nnx = Uy * Vz - Uz * Vy
nny = Uz * Vx - Ux * Vz
nnz = Ux * Vy - Uy * Vx
l = math.sqrt(nnx**2 + nny**2 + nnz**2)
if l > 1e-8:
nnx, nny, nnz = nnx/l, nny/l, nnz/l
else:
nnx, nny, nnz = 0.0, 0.0, 0.0
struct.pack_into('<12fH', new_data, dst_offset, nnx, nny, nnz, nv1x, nv1y, nv1z, nv2x, nv2y, nv2z, nv3x, nv3y, nv3z, attr)
src_offset += 50
dst_offset += 50
meshes_data.append(new_data)
total_faces += faces
with open(output_path, 'wb') as f:
f.write(b'\0' * 80)
f.write(struct.pack('<I', total_faces))
for d in meshes_data:
f.write(d)