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