javascript 通过随机点绘制好看的贝塞尔曲线
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7008006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Draw good-looking Bezier Curve through random points
提问by Nameless
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.
我正在使用带有 RaphaelJS 的 javascript 通过随机点绘制一条平滑的线,并输出到 SVG。这条线严格水平地走,不返回 X 轴。目前,我使用三次贝塞尔曲线从一个点到另一个点绘制线。
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?
问题是,这条线看起来不够好。两条曲线在一个点上有一个难看的连接,一条曲线结束,另一条曲线开始,连接处的角度非常随机。如何让上一条曲线平滑地转换为下一条曲线,同时仍然保持直线通过给定点?
采纳答案by heycam
Catmull-Rom curves work well for going through points. http://schepers.cc/getting-to-the-point
Catmull-Rom 曲线适用于通过点。http://schepers.cc/getting-to-the-point
回答by Phil H
Cubic splines
三次样条
If you want to draw lines throughpoints, 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 articlefor more detail on the maths.
如果你想画线,通过点,那么你要插。贝塞尔曲线是具有曲线外控制节点的三次曲线,但三次样条是通过 n 个点的一组三次曲线,从每个点到下一个点都有平滑的变化。有关数学的更多详细信息,请参阅维基百科文章。
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.
不幸的是,要通过一组点构造三次样条,您必须执行迭代过程;您实际上是在制作 n-1 条三次曲线并将它们的参数匹配在一起,这为您提供了 n+1 个联立方程来求解。一旦你完成了一次,当你移动这些点时,你可以使用你以前的解决方案作为起点。
To do this in Raphael you'll need to generate the cubic spline, then calculate the equivalent Bezier control values for each segment.
要在 Raphael 中执行此操作,您需要生成三次样条,然后计算每个段的等效 Bezier 控制值。
There are pieces of javascript out there to calculate cubic splines for you, for example Cubic splines in JavaScript (via CoffeeScript).
有一些 javascript 可以为您计算三次样条,例如 JavaScript 中的三次样条(通过 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.
三次样条的替代方法是将三次(或更高)多项式拟合到每组几个点;例如三次到每 4 个点,包括重叠。因此,点 10-13 构成了 11 到 12 线的三次方。它不会像三次样条那样平滑,但应该更接近。这与三次样条非常相似,但没有方程求解曲线参数以使一切变得平滑。
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.
要在 Raphael 中绘制它,您可能最好只是更频繁地对线进行采样并使用直线来绘制它。
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).
一个重要的考虑因素是你想画什么样的线。如果您只想要平滑的线条,请执行三次样条。但是如果你正在绘制统计数据或其他一些特定类型的线,你最好研究一下高斯分解或其他东西:三次样条是三次多项式(ax 3+ bx 2+ cx + d = 0),所以你不能近似正弦曲线很好(音频/信号),或高斯(信号/统计),或指数(衰减曲线,长尾统计)。
回答by Joe V?lker
What about averaging the angles of the tangents at your points? This gets rid of the 'unsightly joint'.
如何平均您点处的切线角度?这摆脱了“难看的关节”。
回答by luser droog
I recommend you pull out your Foley and van Dam Fundamentals of Interactive Computer Graphicsand 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.
我建议你拿出你的 Foley and van Dam Fundamentals of Interactive Computer Graphics并查看参数曲线的 Hermite 形式。Hermite 曲线由两个端点(曲线通过的端点)和两个切向量定义,当曲线通过这些点时控制曲线的方向。它很容易通过一些矩阵乘法转换为 Bezier 形式,但优点是:对于平滑连接,曲线的相邻部分将在重合点使用完全相同的切线,而使用 Bezier,您必须强制三个点共线。