如何比较贝塞尔曲线的形状

Posted

技术标签:

【中文标题】如何比较贝塞尔曲线的形状【英文标题】:How to compare shape of Bezier curves 【发布时间】:2015-04-19 19:35:02 【问题描述】:

我想比较 2 条贝塞尔曲线。我知道端点和控制点的坐标,但是对于 2 条比较曲线,这个坐标可能不一样。我需要比较这条曲线的形状。要“真实”,形状必须大致相同。

我使用 javascript 和 paper.js。

请看图片:

https://habrastorage.org/files/825/6e5/36c/8256e536c9ce4f01bf12d792473038d5.png

出路在哪里?谢谢。

【问题讨论】:

【参考方案1】:

首先通过计算 T(转换)矩阵 (-P0) 尝试 X 轴对齐三次曲线,P0 是曲线的第一个控制点。和一个 R(otation) 矩阵(旋转角度需要将最后一个控制点 P3 降落在轴上,你可以算出)。

一旦曲线与轴对齐,您只需要担心曲线的核心(P1 和 P2)。您可以将它们与另一条曲线的值进行比较,以获得自定义的预定义错误阈值,并查看两条曲线是否匹配。

【讨论】:

【参考方案2】:

三次贝塞尔样条曲线由任意四个点定义:start、control-1、control-2 和 end,我将其编号为 0、1、2、3。现在我们假设这四个点是不同,而且没有三个在一条直线上。

曲线可以采取三种根本不同的形式,取决于线 0--1 和 1--2 之间、1--2 和 2--3 之间的转弯方向,以及 0--1 和2--3交叉。

在类型 1 中,两个转弯都在右侧,或者都在左侧,并且 0--1 不与 2--3 交叉。在提问者的例子中,这给出了一条曲线,如 a、b 或 c。在类型 2 中,第一个转向左侧,第二个转向右侧,或反之亦然,给出类似于提问者示例中的 d 的曲线,带有一个扭结。在类型 3 中,两个转弯的方向相同,但线 0--1 和 2--3 交叉,形成带环的曲线。

我们可以首先将单个三次样条分类为三种类型之一,给它们一个类型字符串:普通('' - 空字符串),扭结('K')和循环('L')。

但是,示例 e 由两个平滑连接的三次样条组成。为了处理这样的序列,我们遍历它们并创建一个字符串,为每个扭结曲线附加一个 K,为每个循环曲线附加一个 L。我们还为两条样条线之间的每个连接添加一个 K,其中连接之前的转弯与之后的转弯相反:先左后右,或先右后左。

这为我们提供了类型字符串“K”,例如 e,根据需要将其与 d 匹配。

我们还允许一种类型字符串与另一种类型字符串相反的匹配:因此 'KL' 匹配 'LK'。

【讨论】:

【参考方案3】:

根据您提供的示例,我假设

大小不相关 形状可以扭曲到一个点

如果旋转曲线不相同

    N 个点采样曲线

    只需逐步执行参数... 对于三次曲线,我将使用 16 到 32 个采样点 点越多,比较越精确 但是更大的运行时间...

    计算每段的角度

    使用 atan2 或 atanxy 将这些角度存储在数组中

    比较这些数组

    正确执行此操作的最佳和最简单的方法是correlation coefficient 如果相关系数接近+1,则形状相似或相同

如果旋转相似的曲线应该是相同的

    轮换

    然后执行上述操作几圈(例如 0,10,20,...,350 度) 如果有,如果它们是相同的,则停止并返回 true 如果没有则返回 false 曲线的旋转实际上只是为其所有角度添加一个常数...

    旋转不变性

    如果您偏移两个比较曲线角度以从角度 0 开始 所以只需从曲线的所有角度中减去第一个角度 然后将两条曲线相互对齐,因此只需要 2 个位置进行比较 所以你比较一下 如果不相同,则在一条曲线上添加 180 度并再次比较 够了

[备注]

您应该在相关之前对所有角度进行归一化(使其达到区间<0.0,2.0*PI>) 更多想法请看这里How to compare two shapes?

【讨论】:

以上是关于如何比较贝塞尔曲线的形状的主要内容,如果未能解决你的问题,请参考以下文章

以曲线形状剪切贝塞尔路径

贝塞尔曲线原理(实现图真漂亮)

贝塞尔曲线

bezier曲线的应用

如何检测贝塞尔曲线和圆形物体之间的碰撞?

如何计算三次贝塞尔曲线的长度