128x128规格Points结构2D点数组插值扩容Z坐标处理方案咨询
Z坐标完全可以采用和X、Y坐标相同的线性插值方式处理,不需要更换方案。
原因说明
你当前用的是逐轴一维线性插值的拉伸方案,Points结构体中的X、Y、Z都是和网格点位置绑定的独立双精度标量属性,插值的核心逻辑都是「根据原数组相邻点的属性值,按位置占比权重计算新点的对应属性」,三个属性的处理逻辑没有本质区别。
代码修改说明
你现有代码存在一处笔误:方法输入参数是array,但内部引用的变量名是domes,先统一替换为参数名array即可。只需要在现有X、Y的插值逻辑基础上,补充Z的插值步骤即可:
- 第一轮行方向插值时,同时完成X和Z的行插值
- 第二轮列方向插值时,同时完成Y和Z的列插值
修改后的完整插值方法代码如下:
public Points[,] Interpolate(Points[,] array, int newWidth, int newHeight) { Points[,] result = new Points[newWidth, newHeight]; int oldWidth = array.GetLength(0); int oldHeight = array.GetLength(1); double[] bufferBefore = new double[oldWidth]; double[] bufferAfter = new double[newWidth]; // 第一轮:行方向插值,处理X和Z for (int i = 0; i < oldHeight; i++) { // 插值X for (int j = 0; j < oldWidth; j++) { bufferBefore[j] = array[j, i].X; } bufferAfter = InterpolateArray(bufferBefore, newWidth); for (int j = 0; j < newWidth; j++) { result[j, i].X = bufferAfter[j]; } // 插值Z(行方向) for (int j = 0; j < oldWidth; j++) { bufferBefore[j] = array[j, i].Z; } bufferAfter = InterpolateArray(bufferBefore, newWidth); for (int j = 0; j < newWidth; j++) { result[j, i].Z = bufferAfter[j]; } } bufferBefore = new double[oldHeight]; bufferAfter = new double[newHeight]; // 第二轮:列方向插值,处理Y和Z for (int i = 0; i < newWidth; i++) { // 插值Y for (int j = 0; j < oldHeight; j++) { bufferBefore[j] = array[i, j].Y; } bufferAfter = InterpolateArray(bufferBefore, newHeight); for (int j = 0; j < newHeight; j++) { result[i, j].Y = bufferAfter[j]; } // 插值Z(列方向) for (int j = 0; j < oldHeight; j++) { bufferBefore[j] = result[i, j].Z; } bufferAfter = InterpolateArray(bufferBefore, newHeight); for (int j = 0; j < newHeight; j++) { result[i, j].Z = bufferAfter[j]; } } return result; }
可选优化
如果你后续需要更高的插值精度,可以将逐轴一维插值替换为双线性插值,直接取新点位置周边4个原网格点的Z值加权计算,精度会更高,但你当前的方案已经可以满足绝大多数常规场景的需求。
内容的提问来源于stack exchange,提问作者Infiniter
相关产品推荐
相关产品推荐

