基于Excel的查表插值计算工具及算法详解
基于Excel的查表插值计算工具首先二维查表算法是控制器软件开发中最为基础的算法之一,同时在标定开发过程中,二维查表计算也是新的改变我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:全新的界面设计 ,将会带来全新的写作体验;在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的...
一、基于Excel的查表插值计算工具
二维查表算法是控制器软件开发中最为基础的算法之一,同时进行二维查表计算也是标定开发过程中常见操作。
通常一维线性插值算法可以采用手工计算的方式;二维查表插值算法则多采用Matlab、Origin等软件实现,但上述软件体积较大,操作复杂,并不适合日常办公使用。
为此制作了基于Excel的查表插值计算工具,其操作界面如下:
其使用方法如下:
1、将INCA中的二维MAP表格的X轴坐标值、Y坐标值、MAP值分别填入Excel中对应的位置。
注意
- 本工具X轴最大长度为25,Y轴最大长度20
- X轴与Y轴坐标值务必是单调递增趋势
2、填写Y轴取值点以及X轴取值点(X轴可选取多个点),按下计算按键后,蓝色框区会自动显示查表插值算法的结果。
二、查表插值算法详解
1、举例计算X=18,Y=850时,Z点的取值 ?
二维查表函数如下:
// 查表函数 x = 横坐标取点值 y = 纵坐标取点值 z =返回查表结果
public float GetElementAt(float x, float y)
{
uint x_index, y_index;
float x_offset, y_offset;
float x_distance, y_distance, result;
// 计算X轴 起始坐标索引、偏移量、起始坐标索引至下一个坐标索引点的距离
SearchDistrX(x, out x_index, out x_offset, out x_distance);
// 计算Y轴 起始坐标索引、偏移量、起始坐标索引至下一个坐标索引点的距离
SearchDistrY(y, out y_index, out y_offset, out y_distance);
// 根据X,Y轴坐标信息计算MAP插值
return result = GetDeltaAt(x_index, x_offset, x_distance, y_index, y_offset, y_distance);
}
获取 X=18,Y=850时,Z点的取值?
float Z = GetElementAt(18.00 , 850)
2、首先计算X在起始坐标索引、偏移量、起始坐标索引至下一个坐标索引点的距离,out关键字类似指针的效果,表示此处输出参数值
SearchDistrX(x, out x_index, out x_offset, out x_distance);
运算结果 SearchDistrX(18, 3, 3, 5);
如图所示,将x=18带入函数可得( x 值在[15,20]的坐标区间中)
x_index = 3; 区间起始坐标点对应的下标值(X3)
x_offset = 3; x值(18) - 区间起始坐标点(15)
x_distance = 5;区间结束坐标点(20) - 区间起始坐标点(15)
3、同理计算Y在起始坐标索引、偏移量、起始坐标索引至下一个坐标索引点的距离
SearchDistrY(y, out y_index, out y_offset, out y_distance);
运算结果 SearchDistrY(850, 1, 422.5, 427.25);
4、将上述计算结果带入MAP插值计算函数中
// 根据X,Y轴坐标信息计算MAP插值
result = GetDeltaAt(3, 3, 5, 1, 422.5, 427.25);
public float GetDeltaAt(uint x_index, float x_offset, float x_distance, uint y_index, float y_offset, float y_distance)
{
float v00, v01, v10, v11, v0, v1, result;
// 获取需查询的MAP值所在的左上角单元格数值
v00 = this.zMapValue[y_index, x_index]; /* base value at vMat[x1,y1]*/
// 需查询的MAP值在二维数组范围内
if ((x_index < (this.xAxisLen - 1)) && (y_index < (this.yAxisLen - 1)))
{
// 获取需查询的MAP值所在的右上角单元格数值
v01 = this.zMapValue[y_index, x_index + 1];
// 获取需查询的MAP值所在的左下角单元格数值
v10 = this.zMapValue[y_index + 1, x_index];
// 获取需查询的MAP值所在的右下角单元格数值
v11 = this.zMapValue[y_index + 1, x_index + 1];
}
// 如果需查询的MAP值Y坐标超过最大边界
else if ((x_index < (this.xAxisLen - 1)) && (y_index == (this.yAxisLen - 1)))
{
// // 获取需查询的MAP值所在的右上角单元格数值
v01 = this.zMapValue[y_index, x_index + 1];
// 因为Y轴超边界, 左下角单元格数值 == 左上角单元格数值
v10 = v00;
// 因为Y轴超边界, 右下角单元格数值 == 右上角单元格数值
v11 = v01;
}
// 如果需查询的MAP值X坐标超过最大边界
else if ((x_index == (this.xAxisLen - 1)) && (y_index < (this.yAxisLen - 1)))
{
// 获取需查询的MAP值所在的左下角单元格数值
v10 = this.zMapValue[y_index + 1, x_index];
// 因为X轴超边界, 右上角单元格数值 == 左上角单元格数值
v01 = v00;
// 因为X轴超边界, 右下角单元格数值 == 左下角单元格数值
v11 = v10;
}
// 如果需查询的MAP值X坐标和Y坐标超过最小边界
else
{
// 四个单元格的值都等于左上角单元格数值
v01 = v00;
v10 = v00;
v11 = v00;
}
// 获取需查询的Y点坐标值在左上角与右上角单元格之间的差值
v0 = Interpolate(v00, v01, x_offset, x_distance);
// 获取需查询的Y点坐标值在左下角与右下角单元格之间的差值
v1 = Interpolate(v10, v11, x_offset, x_distance);
// 获取需查询的X点坐标值在 差值点v0,v1的之间的差值
return result = Interpolate(v0, v1, y_offset, y_distance);
}
5、上述函数的第一步是根据计算出的X,Y值坐标索引值(x_index,y_index),可知当X=18,Y=850时,Z值务必在四个黄色单元格内:
分别对应函数的v00(左上1150),v01(左下1275),v10(右上1175),v11(右下1300)
6、选取四个单元格完成后,根据x_offset和x_distance之间的比值,计算出左上角与右上角之间的v0值,计算出左下角与右下角之间的v1值
插值公式:
配图说明:
// 获取需查询的Y点坐标值在左上角与右上角单元格之间的差值
v0 = Interpolate(1150, 1175, 3, 5)
v0 =1165
// 获取需查询的Y点坐标值在左下角与右下角单元格之间的差值
v1 = Interpolate(1275, 1300, 422.5, 427.25);
v1 = 1290
7、使用y_offset,y_distance值在计算出来的v0,v1值之间在进行最后一次插值计算
// 获取需查询的X点坐标值在 差值点v0,v1的之间的差值
result = Interpolate(v0, v1, y_offset, y_distance);
result = 1288.61
最终二维查表插值结果:
1288.61 = GetElementAt(18.00 , 850)
工具下载地址(含插值算法源代码):
更多推荐
所有评论(0)