创建立方和/或二次贝塞尔曲线来适应路径。

我正在使用 Lua 制作一个 2D 游戏。 我有一条由多个点组成的路径,例如点 A 到点 L: points A to L 我想要让一个物体顺利地沿着这条路径移动。为了实现这一点,我希望基于这些点创建二次或三次贝塞尔曲线,并插值这些曲线。然而,如何正确地拟合这些曲线,以避免出现问题,例如曲线在点 F 停止并在另一个点重新开始?

点赞
用户1560821
用户1560821

你不需要懂数学就可以做到这个。

使用单独的贝塞尔曲线将每个点连接到下一个点。

贝塞尔曲线具有附着在其端点上的“控制点”。这些控制点在曲线上(在端点处)是切向的。要使“平滑”的路径,您需要做的就是使每两个相邻的贝塞尔曲线的控制点“坐”在一条直线上。

要理解这一点,请尝试使用绘画程序(例如GIMP,但几乎任何其他软件都可以)。这些程序甚至有一个特殊的键可以使相邻曲线的“控制点”坐在一条直线上(并且具有相同的长度)。

您唯一需要做出的“困难”数学决策是确定这些控制点的长度。尝试一下。您可能希望使其取决于每3个相邻点偏离一条直线的程度,或者取决于点之间的距离。

最后,关于在看似恒定的速度下沿着曲线移动一个点(您的“对象”):您可以使用像这样的方法的调整

2015-04-14 08:44:44
用户15947
用户15947

Curve fitting

这篇问题介绍了贝塞尔曲线的拟合方法:How can I fit a Bézier curve to a set of data?

然而,有一种更简单的插值方法,见下:

  1. Refine: 在每条线段的中点上放置一个点。
  2. Dual: 在每条边的中点上放置一个点,并删除旧点。
  3. 重复 Dual 步骤多次。
  4. 从第一步重复,直到曲线足够平滑。

可以很容易地看出,在纸上进行这些操作是可行的。 生成的曲线开始逼近一系列贝塞尔样条曲线。

更正式的说明可以在这个 PDF 文件中找到(第 3 节):http://www.cc.gatech.edu/~jarek/courses/handouts/curves.pdf

这里是一些 Javascript 代码来执行它:

function bspline_smooth(points, order) {

    // insert a point in the middle of each edge.
    function _refine(points) {
      var i, index, len, point, refined;
      points = [points[0]].concat(points).concat(points[points.length-1]);
      refined = [];
      index = 0;
      for (i = 0, len = points.length; i < len; i++) {
        point = points[i];
        refined[index * 2] = point;
        if (points[index + 1]) {
          refined[index * 2 + 1] = _mid(point, points[index + 1]);
        }
        index += 1;
      }
      return refined;
    }

    // insert point in the middle of each edge and remove the old points.
    function _dual(points) {
      var dualed, i, index, len, point;
      dualed = [];
      index = 0;
      for (i = 0, len = points.length; i < len; i++) {
        point = points[i];
        if (points[index + 1]) {
          dualed[index] = _mid(point, points[index + 1]);
        }
        index += 1;
      }
      return dualed;
    }

    function _mid(a, b) {
      return new Point(
        a.x + ((b.x - a.x) / 2),
        a.y + ((b.y - a.y) / 2) );
    }

    if (!order) {
       return points;
    }
    return bspline_smooth(_dual(_dual(_refine(points))), order - 1);
}
2015-11-05 15:07:01