计算等高线长度

计算科学 算法
2021-11-27 13:12:26

我想知道计算轮廓线长度的算法。假设我们有一个函数的数值数据集f(x,y).

我如何计算线的长度(x1,y1)(x2,y2)在轮廓上f=f0? 我正在使用 Fortran 进行此操作,但使用任何其他语言的示例都可以。

2个回答

正如 Doug Lipinski 所说,您需要:

1) 找到轮廓
2) 计算弧长。

找到轮廓

要找到轮廓,您可以使用Marching Squares,您可以在其中重写

f(x,y)=f0f(x,y)f0=0.

您为每个单独的单元格分配一个图元(例如,每个 4 个单元格可以被认为是双线性插值的角)。因此,您考虑顶点处的值的符号;交叉点出现在符号改变的边上有 16 个选项,虽然只有 4 个拓扑不同

  • 无交叉:4 条边具有相同的符号
  • 单峰:1 条不同符号的边
  • 双相邻
  • 双对面

双重相反的情况下,可能会有一些歧义,应该计算鞍点的符号。

作为最后一步,您确定交叉点的位置(使用沿网格边缘的插值)。

计算弧长

您想要执行数值积分以获得弧长,即

s=ab[x(t)]2+[y(t)]2dt.

在哪里t是一个参数x(t)y(t).

由于您的输入是数字数据xy,您可以直接进行数值积分。最简单的情况是用线连接你的点并添加所有这些段

sk=1N(xkxk1)2+(ykyk1)2

Python中的一个例子

import numpy as np

def arc_length(x, y):
    npts = len(x)
    arc = np.sqrt((x[1] - x[0])**2 + (y[1] - y[0])**2)
    for k in range(1, npts):
        arc = arc + np.sqrt((x[k] - x[k-1])**2 + (y[k] - y[k-1])**2)

    return arc


# Parabolic segment
npts = 1000
a = 3.
h = 5.
x = np.linspace(-a, a, npts)
y = h*(1 - x**2/a**2)
analytic = np.sqrt(a**2 + 4*h**2) + a**2/(2*h)*np.arcsinh(2*h/a)
numeric = arc_length(x, y)
print analytic, numeric

# Semicircle
npts = 1000
x = np.linspace(-1, 1, npts)
y = np.sqrt(1 - x**2)
analytic = np.pi
numeric = arc_length(x, y)
print analytic, numeric

带输出

12.1673133338 12.1881924551
3.14159265359 3.20484351644

您可以使用高阶导数(插值或 B 样条,如 Model_Math 建议的那样)以获得更准确的结果,但概念是相同的。

即使我知道轮廓的点f0对于一些有用的近似值是恒定的,我可能仍然会使用B-Splines来自适应地细化点序列以收敛到弧长。(如果那是 gobblety gook,我将要给出的参考将在更高级的样条细节中涵盖这一点。)

考虑阅读(可能需要购买) 使用递归平滑样条重建轮廓 - 机器人和自治系统第 57 卷,第 6-7 期,2009 年 6 月 30 日,第 617-628 页的算法和实验验证

如果它们更适合您,那篇文章将回答您的问题或为您指出更基本的方向。