贝塞尔曲线与曲线内的控制点

时间:2017-09-28 09:58:54

标签: java c# math bezier curve

请参阅下图。 image below 此路径对象在每侧使用4个贝塞尔曲线创建。 目前,当我尝试使用立方火盆曲线创建此路径对象的边界时,我遇到了一个问题。正如您所看到的那样,顶部和底部的控制点远离曲线,这使得边界完全不准确。

所以我的问题是,是否有可能在图像中创建一个拼图块,其中所有控制点都位于曲线的水平面上。 (这就是创建一条曲线和完美的镜像,所有点都在曲线的范围内)

3 个答案:

答案 0 :(得分:1)

然后,不要使用控制点来计算边界。至少如果您需要紧密边界并且不希望快速检查给定剪切矩形中的潜在可见性。 This令人敬畏的网站可以帮助您完成常见的贝塞尔曲线计算,包括bounding box

或者,切换到控制点位于曲线上的样条曲线,但最终会产生相反的效果,即曲线超出其控制点施加的界限。

答案 1 :(得分:0)

您可以轻松地将BEZIER立方控制点转换为插值立方。只需扭转这一点:

这样:

/*                              bezier = interpol
1  |                           (    x0)=X1;
t  |                  (3.0*x1)-(3.0*x0)=(0.5*(X2-X0));
tt |         (3.0*x2)-(6.0*x1)+(3.0*x0)=(3.0*(X2-X1))-(X2-X0)-(0.5*(X3-X1));
ttt|(    x3)-(3.0*x2)+(3.0*x1)-(    x0)=(0.5*(X2-X0))+(0.5*(X3-X1))+(2.0*(-X2+X1));
1  |                           (    y0)=Y1;
t  |                  (3.0*y1)-(3.0*y0)=(0.5*(Y2-Y0));
tt |         (3.0*y2)-(6.0*y1)+(3.0*y0)=(3.0*(Y2-Y1))-(Y2-Y0)-(0.5*(Y3-Y1));
ttt|(    y3)-(3.0*y2)+(3.0*y1)-(    y0)=(0.5*(Y2-Y0))+(0.5*(Y3-Y1))+(2.0*(-Y2+Y1));
*/

// input: x0,y0,..x3,y3 ... Bezier control points
// output: X0,Y0,..X3,Y3  ... interpolation control points
    double x0,y0,x1,y1,x2,y2,x3,y3,m=1.0/9.0;
    X0=x0-(x1-x0)/m; Y0=y0-(y1-y0)/m;
    X1=x0;           Y1=y0;
    X2=x3;           Y2=y3;
    X3=x3+(x3-x2)/m; Y3=y3+(y3-y2)/m;

希望我没有犯任何代数错误。这将直接将所有控制点移动到曲线中,同时形状将保持不变。请注意,对于BBOX计算,您应该只使用(X1,Y1)(X2,Y2),因为使用的参数t=<0,1>正在它们之间进行插值!!!。

但即使这样也会提供不准确性,因为你可以在没有控制点的情况下有一些极端情况。如果这是一个问题(BBOX比应该小一点)你可以重新采样你的形状到曲线上的一组点(例如每立方10个)和一些步骤(0.1)并且做BBOX来自那些点。这将更精确,但更粗糙......

答案 2 :(得分:0)

Bezier曲线的一个特性是,当你将它们分开时,平滑曲线和CV之间的距离会缩小。

因此,在顶部和底部修复这些CV的一种方法是使用De Casteljau算法将相关的Bezier分割成两个Bezier。

您甚至可以通过算法进行此操作:

  • 找到紧密的边界框和基于CV的边界框。
  • 如果差异大于您的容差,请找到最大/最小CV及其相关贝塞尔曲线
  • 将所有相关的贝塞尔曲线分成两条贝塞尔曲线
  • 重复

最终你会达到你的容忍度。如果你有一个非常严格的容忍度或棘手的数据,你可能会有很多Beziers。