通过随机点绘制好看的贝塞尔曲线
我使用 javascript 和 RaphaelJS 来通过随机点绘制一条平滑的线,并输出到 SVG。 该线严格水平移动,不会沿 X 轴返回。 目前,我正在使用三次贝塞尔曲线来绘制从一点到另一点的线。
问题是,这条线看起来不够好。两条曲线在一个点处有一个难看的连接点,一条曲线结束,另一条曲线开始,连接处的角度相当随机。 如何使上一条曲线平滑地转换为下一条曲线,同时仍然保持线穿过给定点?
I'm using javascript with RaphaelJS to draw a smooth line through random points with output to SVG.
The line goes strictly horizontally, without returning back in axis X.
Currently, I'm using cubic Bezier curves to draw the line from one point to another.
Problem is, the line doesn't look good enough. Two curves have an unsightly join at a point, where one curve ends and another curve starts, with quite random angle in the joint.
How do I get the previous curve to transform into next one smoothly, while still keeping the line passing through given point?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Catmull-Rom 曲线非常适合穿过点。 http://schepers.cc/getting-to-the-point
Catmull-Rom curves work well for going through points. http://schepers.cc/getting-to-the-point
三次样条
如果您想通过点绘制直线,那么您需要插值。贝塞尔曲线是具有偏离曲线控制节点的三次曲线,但三次样条曲线是一组通过 n 个点的三次曲线,每个点到下一个点的变化平滑。有关数学的更多详细信息,请参阅维基百科文章。
不幸的是,要通过一组点构造三次样条,您必须执行迭代过程;你本质上是在制作 n-1 条三次曲线并将它们的参数匹配在一起,这给你提供了 n+1 个联立方程来求解。完成一次后,当您移动点时,您可以使用以前的解决方案作为起点。
要在 Raphael 中执行此操作,您需要生成三次样条曲线,然后计算每个段的等效贝塞尔曲线控制值。
例如,有一些 javascript 可以为您计算三次样条
JavaScript 中的三次样条线(通过 CoffeeScript)。
分段多项式
三次样条的替代方法是对每组几个点拟合三次(或更高)多项式;例如,每 4 个点都有三次方,包括重叠。因此,点 10-13 是从 11 到 12 的直线的三次方。它不会像三次样条那样平滑,但应该更接近。这与三次样条非常相似,但没有对曲线参数进行方程求解以使一切变得平滑。
分段多项式的问题在于它使用不稳定的高阶多项式,当点不位于多项式线上或点靠近时,您可能会出现大的扭结和摆动。
要在 Raphael 中绘制此图,您可能最好只是更频繁地采样线条并使用直线来绘制它。
线条形状
一个重要的考虑因素是您想要绘制什么样的线条。如果您只想要一条平滑的线,请执行三次样条。但是,如果您正在绘制统计数据或其他特定类型的线,您最好研究高斯分解或其他东西:三次样条是三次多项式(ax3 + bx2 + cx + d = 0),因此您无法很好地近似正弦曲线(音频/信号)、高斯曲线(信号/统计)或指数曲线(衰减曲线、长尾曲线) 统计数据)。
Cubic splines
If you want to draw lines through points, then you want interpolation. Beziers are cubic curves with off-curve control nodes, but a cubic spline is a set of cubic curves through n points, with smooth changes from each to the next. See the Wikipedia article for more detail on the maths.
To construct a cubic spline through a set of points, you unfortunately have to perform an iterative procedure; you are essentially making n-1 cubic curves and matching their parameters together, which gives you n+1 simultaneous equations to solve. Once you have done that once, as you move the points you can use your previous solution as a starting point.
To do this in Raphael you'll need to generate the cubic spline, then calculate the equivalent Bezier control values for each segment.
There are pieces of javascript out there to calculate cubic splines for you, for example
Cubic splines in JavaScript (via CoffeeScript).
Piecewise polynomial
An alternative to cubic splines is to fit a cubic (or higher) polynomial to each set of a few points; e.g. cubic to each 4 points, including overlaps. So points 10-13 make the cubic for the line from 11 to 12. It will not be as smooth as a cubic spline, but it should be much closer. This is pretty similar to cubic spline, but without equation solve for the curve parameters to make everything smooth.
The problem with piecewise polynomial is that it uses higher order polynomials, which are unstable, and you can get large kinks and wiggles when the points don't lie on polynomial lines or when the points are close together.
To draw this in Raphael you are probably best just sampling the line more frequently and using straight lines to draw it.
Line shape
One big consideration is what kind of line you want to draw. If you just want a smooth line, do cubic spline. But if you are drawing statistics or some other specific kind of line you may be better off looking into gaussian decomposition or other things: Cubic splines are cubic polynomials (ax3 + bx2 + cx + d = 0), so you cannot approximate sine curves very well (audio/signals), or Gaussians (signals/statistics), or exponentials (decay curves, long tail statistics).
求各点切线角度的平均值怎么样?这样就消除了“难看的接头”。
What about averaging the angles of the tangents at your points? This gets rid of the 'unsightly joint'.
我建议您拿出 Foley 和 van Dam 交互式计算机图形学基础,看看参数曲线的 Hermite 形式。 Hermite 曲线由两个端点(曲线经过的点)和两个切向量定义,切向量控制曲线经过这些点时的方向。它可以通过一些矩阵乘法轻松转换为贝塞尔曲线形式,但优点是:为了平滑连接,曲线的相邻部分将在重合点处使用完全相同的切线,而使用贝塞尔曲线则必须强制三个点共线。
I recommend you pull out your Foley and van Dam Fundamentals of Interactive Computer Graphics and take a look at the Hermite form for a parametric curve. The Hermite curve is defined by two end-points (which the curve passes through) and two tangent vectors controlling the direction of the curve as it passes through those points. It is readily convertible into Bezier form with a few matrix multiplications, but the advantage is: for smooth joins, adjacent sections of the curve will use exactly the same tangents at coinciding points, whereas with Beziers you have to force three points to be collinear.