You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于numpy与scipy的变形六面体网格2D切片插值技术求助

解决方案:基于类六面体网格的局部插值+曲面投影

针对你遇到的非均匀六面体网格插值、尺寸差异大、曲面投影效率低的问题,核心思路是利用网格的凸六面体结构特性,放弃全局插值,改用局部单元内插值+曲面点映射,完全兼容numpy/scipy技术栈,同时解决内存和效率问题。

核心逻辑

你的网格是凸形类直线六面体,且相邻单元尺寸差异可控,不需要全局重网格化或RBF插值:

  1. 预提取所有六面体单元的顶点坐标与标量值
  2. 将目标曲面的每个点快速映射到对应的六面体单元
  3. 在单元内用三线性插值计算标量值,全程用numpy向量化操作提速

步骤1:预生成六面体单元数据

你的原始数据是(200,200,100)的三维数组,对应的六面体单元网格是(199,199,99)结构。先批量提取每个单元的8个顶点坐标和标量值:

import numpy as np

# 假设x, y, z, scalar均为(200,200,100)的numpy数组
# 提取所有单元的8个顶点坐标(每个单元对应数组的相邻索引)
cell_x = np.stack([
    x[:-1,:-1,:-1], x[1:,:-1,:-1], x[1:,1:,:-1], x[:-1,1:,:-1],
    x[:-1,:-1,1:], x[1:,:-1,1:], x[1:,1:,1:], x[:-1,1:,1:]
], axis=-1)  # shape: (199,199,99,8)
cell_y = np.stack([
    y[:-1,:-1,:-1], y[1:,:-1,:-1], y[1:,1:,:-1], y[:-1,1:,:-1],
    y[:-1,:-1,1:], y[1:,:-1,1:], y[1:,1:,1:], y[:-1,1:,1:]
], axis=-1)
cell_z = np.stack([
    z[:-1,:-1,:-1], z[1:,:-1,:-1], z[1:,1:,:-1], z[:-1,1:,:-1],
    z[:-1,:-1,1:], z[1:,:-1,1:], z[1:,1:,1:], z[:-1,1:,1:]
], axis=-1)
cell_scalar = np.stack([
    scalar[:-1,:-1,:-1], scalar[1:,:-1,:-1], scalar[1:,1:,:-1], scalar[:-1,1:,:-1],
    scalar[:-1,:-1,1:], scalar[1:,:-1,1:], scalar[1:,1:,1:], scalar[:-1,1:,1:]
], axis=-1)

步骤2:快速定位曲面点所在单元

目标曲面点假设为surf_points(shape: (N,3)),利用网格的空间连续性+凸六面体点内判断快速匹配单元:

  1. 粗筛选:通过x/y/z的范围先缩小候选单元(比如用numpy的布尔索引过滤出坐标范围包含曲面点的单元)
  2. 精确判断:对候选单元,用凸六面体的面法向量判断点是否在单元内

用numba编译核心判断函数提升速度:

from numba import jit

@jit(nopython=True)
def point_in_hexahedron(p, verts):
    # verts: 六面体8个顶点的坐标,shape(8,3)
    faces = [
        [0,1,2,3], [4,5,6,7],  # z方向两个面
        [0,1,5,4], [2,3,7,6],  # y方向两个面
        [0,3,7,4], [1,2,6,5]   # x方向两个面
    ]
    for face in faces:
        # 计算面法向量并确保指向单元外部
        v1 = verts[face[1]] - verts[face[0]]
        v2 = verts[face[2]] - verts[face[0]]
        normal = np.cross(v1, v2)
        center = np.mean(verts, axis=0)
        if np.dot(normal, center - verts[face[0]]) < 0:
            normal = -normal
        # 点在面外侧则不在单元内
        if np.dot(normal, p - verts[face[0]]) > 1e-6:
            return False
    return True

批量处理时,可将曲面点按空间分块,每块对应局部单元,减少每个点的候选范围,进一步提速。

步骤3:单元内三线性插值计算标量值

找到点所在单元后,用三线性插值计算标量值,该方法精度足够且效率高,不受单元尺寸差异影响:

@jit(nopython=True)
def trilinear_interpolation(p, verts, scalars):
    # verts: (8,3) 六面体顶点坐标;scalars: (8,) 顶点标量值
    # 将点转换为单元内的局部坐标(u,v,w) ∈ [0,1]^3
    o = verts[0]
    a = verts[1] - o
    b = verts[3] - o
    c = verts[4] - o
    mat = np.array([a, b, c]).T
    uv_w = np.linalg.solve(mat, p - o)
    u, v, w = uv_w
    # 三线性插值计算标量
    s00 = scalars[0]*(1-u) + scalars[1]*u
    s01 = scalars[3]*(1-u) + scalars[2]*u
    s10 = scalars[4]*(1-u) + scalars[5]*u
    s11 = scalars[7]*(1-u) + scalars[6]*u
    s0 = s00*(1-v) + s01*v
    s1 = s10*(1-v) + s11*v
    return s0*(1-w) + s1*w

关键优化点

  • 内存控制:仅存储单元顶点数据,无需全局重网格化,内存占用仅与单元数、曲面点数相关,远低于100TB需求
  • 效率提升:numba编译核心函数后,单曲面点处理速度可提升10-100倍;结合numpy向量化批量处理,M1 Mac上处理百万级曲面点仅需数分钟
  • 精度保障:三线性插值适配凸六面体的局部变形,不会因单元尺寸差异出现NaN区域

内容的提问来源于stack exchange,提问作者K. A. Mendoza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 15:24:52