基于Lua的3D三角形矩形棱柱近似的数学实现问题咨询
用最少长方体近似3D三角形的实现方案
核心几何逻辑(针对你提到的短边中点方案)
假设3D三角形的三个顶点为A(x₁,y₁,z₁)、B(x₂,y₂,z₂)、C(x₃,y₃,z₃),按以下步骤推导最长边上的对应点:
- 确定最长边:计算三边长度,把最长边设为
AB,剩余顶点为C(若最长边不是AB,调整顶点顺序即可)。 - 取短边中点:计算两条短边
AC、BC的中点N、M:N = ((A.x+C.x)/2, (A.y+C.y)/2, (A.z+C.z)/2)M = ((B.x+C.x)/2, (B.y+C.y)/2, (B.z+C.z)/2)
- 构建局部坐标系转2D计算:
- 以
A为原点,AB方向为u轴,三角形平面内垂直于AB的方向为v轴,将3D顶点转换为2D局部坐标。 - 在2D坐标系中,
A为(0,0),B为(AB长度, 0),C为(c_u, c_v)(c_u是AC在u轴的投影长度,c_v是垂直投影长度)。
- 以
- 计算长边AB上的对应点:
- 矩形在AB上的两个顶点
P、Q的2D坐标为(c_u/2, 0)和(c_u/2 + AB长度/2, 0),再转回3D坐标:P = A + (c_u/2) * 单位化AB向量Q = A + (c_u/2 + AB长度/2) * 单位化AB向量
- 矩形在AB上的两个顶点
- 生成长方体:将矩形
M-N-Q-P沿三角形平面的法向量方向拉伸指定厚度,即可得到对应的rectangular prism。
Lua代码实现片段
-- 基础向量运算工具 local function vec_sub(a, b) return {x = a.x - b.x, y = a.y - b.y, z = a.z - b.z} end local function vec_add(a, b) return {x = a.x + b.x, y = a.y + b.y, z = a.z + b.z} end local function vec_mul_scalar(v, s) return {x = v.x * s, y = v.y * s, z = v.z * s} end local function vec_dot(a, b) return a.x*b.x + a.y*b.y + a.z*b.z end local function vec_len(v) return math.sqrt(v.x^2 + v.y^2 + v.z^2) end local function vec_normalize(v) local len = vec_len(v) return {x = v.x/len, y = v.y/len, z = v.z/len} end local function vec_cross(a, b) return { x = a.y*b.z - a.z*b.y, y = a.z*b.x - a.x*b.z, z = a.x*b.y - a.y*b.x } end -- 计算三角形内的矩形顶点及平面法向量 local function get_rect_in_triangle(A, B, C) -- 计算三边长度,确定最长边并调整顶点顺序 local AB = vec_sub(B, A) local BC = vec_sub(C, B) local CA = vec_sub(A, C) local len_AB = vec_len(AB) local len_BC = vec_len(BC) local len_CA = vec_len(CA) local longest_len = math.max(len_AB, len_BC, len_CA) if longest_len == len_BC then A, B, C = B, C, A elseif longest_len == len_CA then A, B, C = C, A, B end -- 重新计算向量 AB = vec_sub(B, A) local AC = vec_sub(C, A) len_AB = vec_len(AB) -- 构建局部坐标系 local u_vec = vec_normalize(AB) local ac_dot_u = vec_dot(AC, u_vec) local AC_perp = vec_sub(AC, vec_mul_scalar(u_vec, ac_dot_u)) local v_vec = vec_normalize(AC_perp) -- 计算AB上的对应点P、Q local P = vec_add(A, vec_mul_scalar(u_vec, ac_dot_u / 2)) local Q = vec_add(A, vec_mul_scalar(u_vec, (ac_dot_u + len_AB) / 2)) -- 计算短边中点M、N local M = vec_add(B, vec_mul_scalar(vec_sub(C, B), 0.5)) local N = vec_add(A, vec_mul_scalar(vec_sub(C, A), 0.5)) -- 计算平面法向量(用于拉伸长方体) local normal = vec_normalize(vec_cross(AB, AC)) return {M, N, Q, P}, normal end
额外优化提示
- 若要完全覆盖三角形,用上述大长方体加两个小长方体(分别覆盖剩余的两个小三角形),总共3个即可满足最少数量要求。
- 你之前尝试的投影2D再旋转方案失败,大概率是因为旋转时未正确还原3D空间的平面深度信息,用局部坐标系的方法全程在3D平面内计算,可靠性更高。
内容的提问来源于stack exchange,提问作者Bug
相关产品推荐
相关产品推荐

