0

我们正在尝试创建一个用于校准硬件的曲线编辑器程序。因此,贝塞尔曲线似乎是人们最容易使用的 UI。但是,贝塞尔曲线的问题在于,可以创建一条曲线,其中特定 X 有多个 Y 值,反之亦然。

现在我知道我可以将控制点 (P1, P2) 约束到由锚点 (P0, P3) 定义的区域,这将阻止创建 S,但它也限制了其他有效曲线。

我想知道是否有一些测试可以运行,而不是手动走曲线,你可以判断你的曲线是否有 S 形弯曲,如果有,拒绝该曲线。

顺便说一句,这是针对跨平台应用程序的,因此 WPF 和 NSBezierCurve 是关键字。

4

1 回答 1

2

好消息是我们可以找到关于贝塞尔曲线的各种信息。有几种形状查询技术(对于较低阶的曲线效果相当好,立方在较低的一侧:))。

S形三次贝塞尔曲线

首先,S形三次贝塞尔曲线有一个拐点。拐点是曲线上凹度变为凸度或相反的点。这也意味着在拐点处,曲线的曲率为零(嗯,如果任何曲线必须从凹形变为凸形,则必须在曲线笔直的位置之间存在某个位置——只需查看“S”)。

https://en.wikipedia.org/wiki/Inflection_point

参数曲线曲率的方程是

曲率

我们可以要求 Mathematica 简化这一点,以便我们可以进行一些快速测试。

Mathematica 曲率

这是一些 Javascript 代码(使用paper.js库),它们做同样的事情:

// Method1 - Find inflection points
function hasInflection(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y){
    var CURV_EPSILON = 1e-3;
    var e2 = 1 + CURV_EPSILON;
    var roots = [], a, b, c;

    // Solve for Numerator[k] == 0
    // Where, Curvature k = (dx d^2y - d^2x dy) / (dx^2 - dy^2)^(3/2)
    // Coefficients from Mathematica
    a = -p1x*p0y + 2*p2x*p0y - p3x*p0y + p0x*p1y - 3*p2x*p1y + 2*p3x*p1y - 2*p0x*p2y + 3*p1x*p2y - p3x*p2y + p0x*p3y - 2*p1x*p3y + p2x*p3y;
    b = (2*p1x*p0y - 3*p2x*p0y + p3x*p0y - 2*p0x*p1y + 3*p2x*p1y - p3x*p1y + 3*p0x*p2y - 3*p1x*p2y - p0x*p3y + p1x*p3y);
    c = (-p1x*p0y + p2x*p0y + p0x*p1y - p2x*p1y - p0x*p2y + p1x*p2y);

    // Use any method to solve the quadratic equation (a x^2 + b x + c = 0)
    Numerical.solveQuadratic(a, b, c, roots, 0, 1);
    // Find the root where, the curve changes from concave to convex
    for (i = 0, l = roots.length; i < l; ++i) {
        r = roots[i];
        if( r > -CURV_EPSILON && r < e2 ){
            // Here we basically evaluate the signed normals and look if they are of different signs
            if( Curve.evaluate(v,r-CURV_EPSILON,3) * Curve.evaluate(v,r+CURV_EPSILON,3) < 0 )
                return true;
        }
    }
    return false;
}

在此处查看完整示例

曲线,其中,任何 X 都有多个 Y 值

从你的问题来看,我认为有更好的定义你想要什么的空间。

即使曲线不是S形,任何 X(或反之亦然)都可能出现大于 Y 值的情况——曲率永远不会改变符号。

在此处输入图像描述

即使曲线不自相交也是如此。因此,对于您要查找的内容,这可能不是一个很好的测试。

如果您需要X 和 Y 方向单调的曲线——即 X 和 Y 值沿曲线长度单调递减或递增;您可以改为求解三次方程的导数(在 X 和 Y 中)。

于 2014-05-31T00:53:46.630 回答