贝塞尔曲线评估
我在这里使用 de Casteljau 算法http://www.cgafaq.info/ wiki/B%C3%A9zier_curve_evaluation 并且我尝试使用主题 在 C++、OpenGL 中使用 De Casteljau 算法绘制贝塞尔曲线 提供帮助。没有成功。
我的贝塞尔曲线在评估时看起来像这样
正如你所看到的,即使它没有达到我想要的效果,所有点确实都在曲线上。我不认为这个算法因此就不准确。
以下是我在该图像顶部曲线上的观点: (0,0) (2,0) (2,2) (4,2) 第二条曲线使用同一组点,但第三个点是 (0,2),即比第一个点高两个单位,形成更陡的曲线。
有问题。我应该为 t
输入 0.25,它应该为 X 值输出 1.0,而 .75 应始终返回 3。假设 t
是时间。它应该以恒定的速度进步,是吗?恰好 25% 处,X 值应为 1.0,然后 Y 应与该值关联。
有没有适当的方法来评估贝塞尔曲线?有谁知道这是怎么回事?
感谢您的帮助! :)
编辑------
我在谷歌搜索中找到了这本书http://www.tsplines.com/resources/class_notes/Bezier_curves.pdf 这是我在显式/非参数贝塞尔曲线上找到的页面曲线。它们是表示为贝塞尔曲线的多项式,这就是我在这里想要的。这是书中的页面:
有人知道如何将贝塞尔曲线转换为参数曲线吗?我现在可能会打开一个不同的线程...
自 2011 年 11 月 1 日起再次编辑------
我意识到我只问了这个问题一半的问题。我正在尝试构建类似于 Maya 的动画图形编辑器,例如 http: //www.youtube.com/watch?v=tckN35eYJtg&t=240 其中用于修改曲线的贝塞尔控制点较多就像等长度的切线修饰符一样。老实说,我不记得它们的长度相等。通过强制使用这样的系统,您可以 100% 确保结果是一个函数并且不包含重叠的段。
我找到了这个,这可能有我的答案 http://create.msdn .com/en-US/education/catalog/utility/curve_editor
I am following this paper here using de Casteljau's Algorithm http://www.cgafaq.info/wiki/B%C3%A9zier_curve_evaluation and I have tried using the topic Drawing Bezier curves using De Casteljau Algorithm in C++ , OpenGL to help. No success.
My bezier curves look like this when evaluated
As you can see, even though it doesn't work the wanted I wanted it to, all the points are indeed on the curve. I do not think that this algorithm is inaccurate for this reason.
Here are my points on the top curve in that image:
(0,0)
(2,0)
(2,2)
(4,2) The second curve uses the same set of points, except the third point is (0,2), that is, two units above the first point, forming a steeper curve.
Something is wrong. I should put in 0.25 for t
and it should spit out 1.0 for the X value, and .75 should always return 3. Assume t
is time. It should progress at a constant rate, yeah? Exactly 25% of the way in, the X value should be 1.0 and then the Y should be associated with that value.
Are there any adequate ways to evaluate a bezier curve? Does anyone know what is going on here?
Thanks for any help! :)
EDIT------
I found this book in a google search http://www.tsplines.com/resources/class_notes/Bezier_curves.pdf and here is the page I found on explicit / non-parametric bezier curves. They are polynomials represented as bezier curves, which is what I am going for here. Here is that page from the book:
Anyone know how to convert a bezier curve to a parametric curve? I may open a different thread now...
EDIT AGAIN AS OF 1 NOVEMBER 2011-------
I've realized that I was only asking the question about half as clear as I should have. What I'm trying to build is like Maya's animation graph editor such as this http://www.youtube.com/watch?v=tckN35eYJtg&t=240 where the bezier control points that are used to modify the curve are more like tangent modifiers of equal length. I didn't remember them as being equal length, to be honest. By forcing a system like this, you can insure 100% that the result is a function and contains no overlapping segments.
I found this, which may have my answer http://create.msdn.com/en-US/education/catalog/utility/curve_editor
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在这里,您可以按照链接中的命名法查看 Mathematica 中实现的算法,以及你的两个图:
顺便说一句,曲线由以下参数定义方程,它们是上面代码中的函数 pts3[t]:
并
尝试绘制它们!
采用任何这些曲线方程,并通过求解三次多项式,在这些情况下您可以得到 y[x] 的表达式,这当然并不总是可能的。只是为了让您体验一下它,从您得到的第一条曲线(C 语法):
尝试绘制它!
编辑
只是一个娱乐:
Mathematica 是一种非常强大的函数式语言,事实上整个算法可以表示为一行:
如
上面给出结果,但支持任意数量点。
让我们尝试使用六个随机点:
此外,相同的函数也适用于 3D:
Here you can see the algorithm implemented in Mathematica following the nomenclature in your link, and your two plots:
BTW, the curves are defined by the following parametric equations, which are the functions
pts3[t]
in the code above:and
Try plotting them!
Taking any of these curve equations, and by solving a cubic polynomial you can in these cases get an expression for y[x], which is certainly not always possible. Just for you to get a flavor of it, from the first curve you get (C syntax):
Try plotting it!
Edit
Just an amusement:
Mathematica is a quite powerful functional language, and in fact the whole algorithm can be expressed as a one liner:
Such as
gives the above results, but supports any number of points.
Let's try with six random points:
Moreover, the same function works in 3D:
贝塞尔曲线可以通过求解 x、y 和 z 坐标的以下参数方程来求解(如果只是 2D,则仅求解 x 和 y):
您还可以通过乘以矩阵方程 ABC = X 来求解,其中
t
矩阵的幂的值t
幂的系数,是一个下三角 4x4 矩阵如下所示:
(更新 - 左下角 1 应该是 -1)
两种形式的方程(参数和矩阵)的重要说明形式)的原因是
t
在 [0, 1] 范围内。与其尝试求解
t
的值,而是给出x
和y
的整数值,这将非常耗时如果您基本上是在求解 3 次多项式的实根,那么最好在您的t
值中创建一个足够小的微分,这样曲线上任意两点之间的差为小于像素值增量。换句话说,两点P(t1)
和P(t2)
之间的距离小于像素值。或者,您可以在t
中使用更大的差异,并在P(t1)
和P(t2)
之间简单地进行线性插值,请记住如果P(t1)
和P(t2)
之间的差异对于给定的t< 范围不够小,则曲线可能不“平滑” /code> 来自 [0, 1]。
从视觉角度来看,找到 t 中必要的微分以创建相当“平滑”的曲线的一个好方法是实际测量定义贝塞尔曲线的四个点之间的距离。测量 P1 到 P2、P2 到 P3 以及 P3 到 P4 的距离。然后取最长距离,并使用该值的倒数作为
t
的微分。您可能仍然需要在点之间进行一些线性插值,但每个“线性”子曲线中的像素数量应该相当小,因此曲线本身会显得相当平滑。您始终可以从该初始值减小t
上的微分值,使其“更平滑”。最后回答一下你的问题:
不,这是不正确的,原因是向量 (P2 - P1) 和 (P3 - P4) 不仅与 P1 和 P4 处的贝塞尔曲线相切,而且它们的长度定义了速度 也沿着曲线在这些点处。因此,如果向量 (P2 - P1) 距离很短,则意味着在给定的时间
t
内,您不会距离 P1 点很远……这转化为 x对于给定的固定微分t
,沿曲线的 y 值非常紧密地组合在一起。当您向 P1 移动时,您的速度实际上“减慢”了。根据矢量的长度 (P3 - P4),曲线上的 P4 处也会发生相同的效果。沿着曲线的速度是“恒定”的唯一方法,因此t
的公共微分的任何点之间的距离将是相同的,如果所有三个段的长度( P2-P1)、(P3-P2)和(P4-P3)相同。这表明沿着曲线的速度没有变化。A bezier curve can be solved by solving the following parametric equations for the x, y, and z coordinates (if it's just 2D, do only x and y):
You can also solve this by multiplying the matrix equation ABC = X where:
t
t
, and is a lower-triangular 4x4 matrixThis would look like the following:
(Update - the bottom left 1 ought to be a -1)
An important note in both forms of the equation (the parametric and the matrix forms) is that
t
is in the range [0, 1].Rather than attempting to solve the values for
t
that will give you integral values ofx
andy
, which is going to be time-consuming given that you're basically solving for the real root of a 3rd-degree polynomial, it's much better to simply create a small enough differential in yourt
value such that the difference between any two points on the curve is smaller than a pixel-value increment. In other words the distance between the two pointsP(t1)
andP(t2)
is such that it is less than a pixel value. Alternatively, you can use a larger differential int
, and simply linearly interpolate betweenP(t1)
andP(t2)
, keeping in mind that the curve may not be "smooth" if the differential betweenP(t1)
andP(t2)
is not small enough for the given range oft
from [0, 1].A good way to find the necessary differential in
t
to create a fairly "smooth" curve from a visual standpoint is to actually measure the distance between the four points that define the bezier curve. Measure the distance from P1 to P2, P2, to P3, and P3 to P4. Then take the longest distance, and use the inverse of that value as the differential fort
. You may still need to-do some linear interpolation between points, but the number of pixels in each "linear" sub-curve should be fairly small, and therefore the curve itself will appear fairly smooth. You can always decrease the differential value ont
from this initial value to make it "smoother".Finally, to answer your question:
No, that is not correct, and the reason is that the vectors (P2 - P1) and (P3 - P4) are not only tangent to the bezier curve at P1 and P4, but their lengths define the velocity along the curve at those points as well. Thus if the vector (P2 - P1) is a short distance, then that means for a given amount of time
t
, you will not travel very far from the point P1 ... this translates into the x,y values along the curve being packed together very closely for a given fixed differential oft
. You are effectively "slowing down" in velocity as you move towards P1. The same effect takes place at P4 on the curve depending on the length of the vector (P3 - P4). The only way that the velocity along the curve would be "constant", and therefore the distance between any points for a common differential oft
would be the same, would be if the lengths of all three segements (P2 - P1), (P3 - P2), and (P4 - P3) were the same. That would then indicate that there was no change in velocity along the curve.听起来您实际上只想要一维三次贝塞尔曲线,而不是您拥有的二维贝塞尔曲线。具体来说,您真正想要的只是一个从 0 开始并在 0 到 4 的域上计算时达到 2 的三次多项式段。因此,您可以使用一些基本数学并找到多项式:
这留下了两个自由度.
取函数的导数:
如果你希望它在开始时很陡峭,然后在最后趋于平稳,你可能会这样说:
然后我们可以插入值。 a 和 b 是免费的,因为我们的评估为零。
那么我们就有了:
这是一个非常容易解决的线性系统。为了完整起见,我们得到:
因此
,如果您决定使用 Bezier 控制点,只需选择 4 个 y 值控制点并认识到这一点,即可在 [0 中获得 t ,1],您只需说
t=x/4
(请记住,如果您还需要导数,则也必须在那里进行更改)。补充:
如果你碰巧知道你想要开始和结束的点和导数,但你想使用贝塞尔曲线控制点P1,P2,P3< /strong> 和 P4,映射就是这样的(假设曲线参数化为 0 到 1):
如果出于某种原因,您想坚持使用 2D Bezier 控制点并希望确保认为随着 t 从 0 前进到 1,x 维度从 0 线性前进到 2,那么您可以使用控制点
(0,y1) (2/3 ,y2)(4/3,y3)(2,y4)
。您可以看到,我刚刚将 x 维度设置为从 0 开始,到 2 结束,并且斜率(导数)恒定为 2(相对于 t)。然后你只需将 y 坐标设置为你需要的任何坐标即可。不同的维度本质上是相互独立的。It sounds like you actually just want a 1D cubic Bezier curve instead of the 2D that you have. Specifically, what you actually want is just a cubic polynomial segment that starts at 0 and goes up to 2 when evaluated over the domain of 0 to 4. So you could use some basic math and just find the polynomial:
That leaves two degrees of freedom.
Take the derivative of the function:
If you want it to be steep at the beginning and then level off at the end you might say something like:
Then we can plug in values. a and b come for free because we're evaluating at zero.
So then we have:
That's a pretty easy linear system to solve. For completeness, we get:
So-
If, instead, you decide that you want to use Bezier control points, just pick your 4 y-value control points and recognize that in order to get t in [0,1], you just have to say
t=x/4
(remembering that if you also need derivatives, you'll have to do a change there too).Added:
If you happen to know the points and derivatives you want to begin and end with, but you want to use Bezier control points P1, P2, P3, and P4, the mapping is just this (assuming a curve parametrized over 0 to 1):
If, for some reason, you wanted to stick with your 2D Bezier control points and wanted to ensure that the x dimension advanced linearly from 0 to 2 as t advanced from 0 to 1, then you could do that with control points
(0,y1) (2/3,y2) (4/3,y3) (2,y4)
. You can see that I just made the x dimension start at 0, end at 2, and have a constant slope (derivative) of 2 (with respect to t). Then you just make the y-coordinate be whatever you need it to be. The different dimensions are essentially independent of each other.经过这么长时间,我一直在寻找隐士曲线。 Hermites 很好,因为在一维中,它们可以保证生成一条可以评估为 XY 点的函数曲线。我把 Hermites 和 Bezier 搞混了。
After all this time, I was looking for hermite curves. Hermites are good because in one dimension they're guaranteed to produce a functional curve that can be evaluated to an XY point. I was confusing Hermites with Bezier.
“假设时间到了。”
这就是问题所在——时机未到。曲线有自己的 t 变化率,具体取决于切线的大小。正如 Jason 所说,后续点之间的距离必须相同,t 的顺序才能与时间相同。这正是 Maya 曲线编辑器中的非加权模式(默认使用)。所以这是关于如何解决这个问题的完美答案。要使其适用于任意切线,必须将时间转换为 t。您可以通过计算 x(或时间)方向的贝塞尔方程来找到 t。
Px = (1-t)^3(P1x) + 3t(1-t)^2(P2x) + 3t^2(1-t)(P3x) + t^3(P4x)
Px 是你的时间,所以你了解这里的一切,但是t。您必须解三次方程才能找到根。不过,找到您需要的确切根有一个棘手的部分。然后求解另一个方程以找到 Py(您正在寻找的实际值),现在知道 t:
Py = (1-t)^3(P1y) + 3t(1-t)^2(P2y) + 3t^ 2(1-t)(P3y) + t^3(P4y)
这就是 Maya 中的加权曲线。
我知道这个问题很老了,但是我花了一整天的时间来研究这个简单的事情,而且没有人准确解释发生了什么。否则,计算过程本身就写在很多地方,例如 Maya API 手册。 Maya 开发工具包也有一个源代码来执行此操作。
"Assume t is time."
This is the problem - t is not the time. The curve has it's own rate of change of t, depending on the magnitude of the tangents. Like Jason said, the distance between the consequent points must be the same in order of t to be the same as the time. This is exactly what the non-weighted mode (which is used by default) in the Maya's curve editor is. So this was a perfectly good answer for how to fix this issue. To make this work for arbitrary tangents, you must convert the time to t. You can find t by calculating the bezier equation in the x (or time) direction.
Px = (1-t)^3(P1x) + 3t(1-t)^2(P2x) + 3t^2(1-t)(P3x) + t^3(P4x)
Px is your time, so you know everything here, but t. You must solve a cubic equation to find the roots. There is a tricky part to find the exact root you need though. Then you solve the other equation to find Py (the actual value you are looking for), knowing now t:
Py = (1-t)^3(P1y) + 3t(1-t)^2(P2y) + 3t^2(1-t)(P3y) + t^3(P4y)
This is what the weighted curves in Maya are.
I know the question is old, but I lost a whole day researching this simple thing, and nobody explains exactly what happens. Otherwise, the calculation process itself is written on many places, the Maya API manual for example. The Maya devkit also has a source code to do this.