尝试找到4点的贝塞尔曲线的长度 [英] Trying to find length of a bezier curve with 4 points

查看:516
本文介绍了尝试找到4点的贝塞尔曲线的长度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现这个问题有1000个答案,但我没有一个可以使用,因为我对我的曲线使用了4个控制点。



也就是说,我偶然发现了这个家伙这里

  double BezierArcLength(point2d p1,point2d p2,point2d p3,point2d p4)
{
point2d k1,k2,k3,k4;

k1 = -p1 + 3 *(p2-p3)+ p4;
k2 = 3 *(p1 + p3)-6 * p2;
k3 = 3 *(p2 - p1);
k4 = p1;

q1 = 9.0 *(sqr(k1.x)+ sqr(k1.y));
q2 = 12.0 *(k1.x * k2.x + k1.y * k2.y);
q3 = 3.0 *(k1.x * k3.x + k1.y * k3.y)+ 4.0 *(sqr(k2.x)+ sqr(k2.y));
q4 = 4.0 *(k2.x * k3.x + k2.y * k3.y);
q5 = sqr(k3.x)+ sqr(k3.y);

double result = Simpson(balf,0,1,1024,0.001);
return result;
}

它看起来像是完美的解决方案,完全混淆我:

  k1 = -p1 + 3 *(p2  -  p3)+ p4; 
k2 = 3 *(p1 + p3)-6 * p2;
k3 = 3 *(p2 - p1);
k4 = p1;

我应该对二维对象进行加,减和乘法等操作我假设point2d是一个对象结构,如 {x:0,y:0} )?我感到茫然,但这是唯一让我从实际实施这个怪物。



FWIW,我使用这个方程来标准化实体的速度,当经过曲线在游戏中。

解决方案

这里是如何遍历你的立方贝塞尔曲线以均匀速度



没有一个简单的公式用于沿着三次贝塞尔曲线获得均匀长度段(甚至意味着弧长段) 。所涉及的是计算沿曲线的许多点,然后使用插值微调每个点为大致等距离。



我可以让你几乎在那里,而不必得到数学的PH.D。



使用公共公式来计算从t = 0到t = 1的曲线上的x / y点,其中t = 0表示曲线的起点,t = 1表示曲线的终点。这是常用公式:

  //计算t间隔处的x / y点
// t = 0在startPt,t = 1 at endPt
var x = CubicN(t,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
var y = CubicN(t,startPt.y,controlPt1.y,controlPt2.y,endPt.y);

//在t间隔的立方体辅助公式
函数CubicN(t,a,b,c,d){
var t2 = t * t;
var t3 = t2 * t;
return a +(-a * 3 + t *(3 * a- a * t))* t
+(3 * b + t *(-6 * b + b * 3 * t )* t
+(c * 3-c * 3 * t)* t2
+ d * t3;
}

如果你计算足够的间隔,说100个间隔(t + = .01 each循环),那么你将得到一个非常好的曲线近似。



这意味着如果你用线连接100点,结果看起来非常像一个立方贝塞尔曲线。



但你还没有完成!



上面计算的一系列x / y点在弧距上彼此不一致。



要计算均匀分布的点数:


  1. 用线连接所有点(创建折线)。

  2. 计算该折线的总距离(T)。

  3. 用所需的统一线段数除以(T) length(SL)

  4. 最后,从开始到结束,计算距离上一个点的距离为(SL)的每个点。

结果:您可以使用这些等距点来遍历曲线。



其他细化:这将导致视觉平滑沿着Bezier路径的运动。但如果你想要更平滑,只要计算超过100点 - 更多的积分==更平滑。


I've found about a 1000 answers to this question, but none of them I can use, because I'm using 4 control points with my curves.

That said, I stumbled on this guy here:

double BezierArcLength(point2d p1, point2d p2, point2d p3, point2d p4)
{
    point2d k1, k2, k3, k4;

    k1 = -p1 + 3*(p2 - p3) + p4;
    k2 = 3*(p1 + p3) - 6*p2;
    k3 = 3*(p2 - p1);
    k4 = p1;

    q1 = 9.0*(sqr(k1.x) + sqr(k1.y));
    q2 = 12.0*(k1.x*k2.x + k1.y*k2.y);
    q3 = 3.0*(k1.x*k3.x + k1.y*k3.y) + 4.0*(sqr(k2.x) + sqr(k2.y));
    q4 = 4.0*(k2.x*k3.x + k2.y*k3.y);
    q5 = sqr(k3.x) + sqr(k3.y);

    double result = Simpson(balf, 0, 1, 1024, 0.001);
    return result;
}

It looks like it'd be the perfect solution, but that beginning part is utterly confusing to me:

k1 = -p1 + 3*(p2 - p3) + p4;
k2 = 3*(p1 + p3) - 6*p2;
k3 = 3*(p2 - p1);
k4 = p1;

How on earth am I supposed to do operations like add, subtract and multiply on 2-dimensional objects (I presume point2d is an object structure like {x: 0, y: 0})? I feel idiotic, but this is the only thing keeping me from actually implementing this monstrosity.

FWIW, I'm using this equation to normalize an entity's speed when traversing the curve in a game. If you know a better way of doing this altogether, I'm all ears.

解决方案

Here’s how to traverse your cubic bezier curve at uniform speed

There isn't one simple formula for getting even length segments along a cubic bezier curve (meaning even arc-length segments). What's involved is calculating many points along the curve and then using interpolation to "nudge" each point into being roughly equidistant.

I can get you nearly there without your having to get a PH.D in Mathematics.

Start by using the common formula to calculate x/y points on the curve from t=0 to t=1 where t=0 represents the startpoint of the curve and t=1 represents the endpoint of the curve. This is the common formula:

// calc the x/y point at t interval
// t=0 at startPt, t=1 at endPt
var x=CubicN(t,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
var y=CubicN(t,startPt.y,controlPt1.y,controlPt2.y,endPt.y);

// cubic helper formula at t interval
function CubicN(t, a,b,c,d) {
    var t2 = t * t;
    var t3 = t2 * t;
    return a + (-a * 3 + t * (3 * a - a * t)) * t
    + (3 * b + t * (-6 * b + b * 3 * t)) * t
    + (c * 3 - c * 3 * t) * t2
    + d * t3;
}

If you calculate enough intervals, say 100 intervals (t += .01 each loop) then you will get a very good approximation of the curve.

That means if you connect the 100 points with lines, the result would look very much like a cubic bezier curve.

But you're not done!

The series of x/y points calculated above are not uniform in arc-distance from each other.

Some neighboring points are close together and some neighboring points are farther apart.

To calculate evenly distributed points:

  1. Connect all the points with lines (creating a polyline).
  2. Calculate the total distance (T) of that polyline.
  3. Divide (T) by the number of uniform segments you desire, getting the uniform segment length (SL)
  4. Finally, walk the polyline from start to end, calculating each point that is (SL) distance from the previous point.

Result: you can use these equidistant points to traverse your curve.

Additional Refinement: This should result in a visually smooth movement along your Bezier path. But if you desire even more smoothness, just calculate more than 100 points--more points == more smoothness.

这篇关于尝试找到4点的贝塞尔曲线的长度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆