Matlab 插值面上分段恒定的二维数据
我有一个由两个变量描述的不规则网格-一个面数组存储构成每个面的顶点的索引,一个顶点数组存储每个顶点的坐标。我还有一个函数,假设它在每个面上是分段常数,它以每个面上的值数组的形式存储 我正在寻找一种从这些数据构造函数Matlab 插值面上分段恒定的二维数据,matlab,scipy,interpolation,piecewise,Matlab,Scipy,Interpolation,Piecewise,我有一个由两个变量描述的不规则网格-一个面数组存储构成每个面的顶点的索引,一个顶点数组存储每个顶点的坐标。我还有一个函数,假设它在每个面上是分段常数,它以每个面上的值数组的形式存储 我正在寻找一种从这些数据构造函数f。大致如下: faces = [[0,1,2], [1,2,3], [2,3,4] ...] verts = [[0,0], [0,1], [1,0], [1,1],....] vals = [0.0, 1.0, 0.5, 3.0,....] f = interpolate(fac
f
。大致如下:
faces = [[0,1,2], [1,2,3], [2,3,4] ...]
verts = [[0,0], [0,1], [1,0], [1,1],....]
vals = [0.0, 1.0, 0.5, 3.0,....]
f = interpolate(faces, verts, vals)
f(0.2, 0.2) = 0.0 # point inside face [0,1,2]
f(0.6, 0.6) = 1.0 # point inside face [1,2,3]
手动计算
f(x,y)
的方法是找到点x,y
所在的对应面,并返回存储在该面中的值。是否有一个函数已经在scipy(或matlab)中实现了这一点 对于我来说,这听起来不像是插值,而是找到点在哪个三角形面内部。查看测试每个三角形面的方法。您的函数将只确定它在哪个面内并返回相应的值。当然,如果你有很多面,或者你做了很多,那么你会想找到优化的方法(存储每个三角形在x和y方向上最远的+和-点,并将其与面一起存储。如果该点不在此边界框内,则最好不要检查它是否位于三角形内部)
我真的怀疑你是否能找到Matlab或scipy内置的东西来做你想做的事情,但我可能错了。你可能想使用桥接模块;如果我没记错的话,CGAL提供了三角搜索功能。但是,如果你以增量方式构建三角剖分,它可能最有效对于一个快速而肮脏的例子,你可以通过Voronoi图找到离查询点最近的网格顶点(Matlab中的功能不是很好),或者,对于单个查询,计算所有距离并找到最小值,然后搜索具有该顶点的所有三角形。Matlab具有内置函数,可用于测试您是否在三角形内。我不知道有哪个函数可以识别您在哪个面内
如果你要编写这样一个函数,我会首先测试你的点最接近哪个顶点,然后对所有共享该顶点的面进行多边形求值,直到找到匹配。这应该相当快。看看
matplotlib.delaunay.interpolate
,这是一个很好的C代码包装程序。(然而,
class LinearInterpolator
“目前,仅支持常规矩形网格进行插值。”)MATLAB中没有内置函数可以满足您的需要。您可以使用函数as构建自己的算法,但您可以使用一些标准算法自己创建一个更快的实现,以查找点是否在多边形内 不久前,我编写了自己的代码,用于在3-D中查找线段和一组三角形曲面之间的交点,我发现这对实现该算法最有帮助。我的案例比你的更复杂。因为你在2-D中工作,你可以忽略链接的第一部分,即查找线段与三角形的平面相交 我在下面提供了一个简化版的MATLAB代码供您使用。
插值
函数将把您的面
、顶点
和值
矩阵作为输入,并返回可在给定(x,y)下计算的函数句柄f
指向以获取边界三角形内的分段值。以下是此代码的一些功能:
- 计算
时要完成的处理包含在f
evaluate\u函数中。此函数可以访问
中的其他变量,因此预计算三角形内测试所需的许多变量,以便interpolate
尽可能快地运行evaluate\u函数
- 如果您有很多三角形,测试您的点是否在所有三角形内可能会很昂贵。因此,代码首先查找位于您的点的给定半径(即三角形最长腿的长度)内的三角形。仅测试这些附近的三角形,以查看该点是否在三角形内
- 如果点不在任何三角形区域内,
将返回值f
- 输入检查:代码当前假定
是一个N×3矩阵,面
是一个M×2矩阵,顶点
是一个长度N向量。您可能希望添加错误检查,以确保输入符合这些要求,并抛出一个错误,指示一个或多个他们是不正确的值
- 退化三角形检查:由
和面
输入定义的一个或多个三角形可能退化(即,它们的面积可能为0)。当两个或多个三角形顶点是同一精确点时,或当三角形的所有三个顶点都位于一条直线上时,会发生这种情况。在计算顶点
时,您可能希望添加一个将忽略此类三角形的检查f
- 处理边缘情况:一个点可能最终位于两个或多个三角形区域的边缘。因此,您必须确定该点将采用的值(即面值的最大值、面值的平均值等).对于这样的边缘情况,下面的代码将自动拾取面的值
function f = interpolate(faces,vertices,values) %# Precompute some data (helps increase speed): triVertex = vertices(faces(:,2),:); %# Triangles main vertices triLegLeft = vertices(faces(:,1),:)-triVertex; %# Triangles left legs triLegRight = vertices(faces(:,3),:)-triVertex; %# Triangles right legs C1 = sum(triLegLeft.*triLegRight,2); %# Dot product of legs C2 = sum(triLegLeft.^2,2); %# Squared length of left leg C3 = sum(triLegRight.^2,2); %# Squared length of right leg triBoundary = max(C2,C3); %# Squared radius of triangle boundary scale = C1.^2-C2.*C3; C1 = C1./scale; C2 = C2./scale; C3 = C3./scale; %# Return a function handle to the nested function: f = @evaluate_function; %# The nested evaluation function: function val = evaluate_function(x,y) w = [x-triVertex(:,1) y-triVertex(:,2)]; nearIndex = find(sum(w.^2,2) <= triBoundary); %# Find nearby triangles if isempty(nearIndex) val = NaN; %# Return NaN if no triangles are nearby return end w = w(nearIndex,:); wdotu = sum(w.*triLegLeft(nearIndex,:),2); wdotv = sum(w.*triLegRight(nearIndex,:),2); C = C1(nearIndex); s = C.*wdotv-C3(nearIndex).*wdotu; t = C.*wdotu-C2(nearIndex).*wdotv; inIndex = find((s >= 0) & (t >= 0) & (s+t <= 1),1); if isempty(inIndex) val = NaN; %# Return NaN if point is outside all triangles else val = values(nearIndex(inIndex)); end end end