如何比较贝塞尔曲线的形状
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?
【讨论】:
以上是关于如何比较贝塞尔曲线的形状的主要内容,如果未能解决你的问题,请参考以下文章