在两个xy点之间计算二次曲线

7
我有两个(x,y)的起点和终点。我想要从起点到终点进行动画,但不是按线性方式前进,而是要创建一条曲线路径。
我很确定我不需要缓动效果,因为我不想影响动画速度,我只想计算出一条曲线路径。
我发现我需要某种控制点,就像这张图片中所示:
但我不知道如何实现它。我希望创建一个函数,接受以下参数:
function calculateXY(start, end, controlpoint, percentage);

百分比值应该是0-100%之间的数字,其中0将返回起始位置,而100%将返回结束位置。

解决方案不需要使用Objective-C,它可以用任何编程语言来实现。我只是无法理解数学计算 :)

3个回答

0
解决方案并不需要使用Objective-C编写,可以使用任何编程语言。我只是无法理解其中的数学问题。
我不能提供代码,但如果您想了解涉及的数学知识,我可以解释一下如何在Quad曲线中实现。
首先要了解控制点在数学上的影响。控制点和两个定义的点定义了当前点和终点处所绘制直线的梯度。您可以使用m=(y-y1)/(x-x1)计算出两条线的梯度。
接下来在数学上要解决的问题是求解a、b、c这三个变量的方程组:
ax^2+bx+c包含起点和终点
2ax+b等于相应x值处的梯度。
此时可以得到一个用于绘制直线的二次方程。

0

我在工作中看到了这个,想在家里试一试。经过一段时间观察维基百科上的这个例子,我认为我明白该怎么做了,下面你将看到一个我将要解释的例子。

我将使用0到1之间的时间间隔。在任何两个数字之间都是动画的时间分数。你想要的是在给定时间分数时获取“兴趣点”的位置。第一步是,你有三个点ABC,它们由两条线连接(g => [AB]h => [BC])。对于这些线中的每一条,你都需要计算出在起始点和重心点P(g)之间或者在重心点和结束点P(h)之间,在给定时间分数下漫游的点。

在这两个计算出来的点(P(g)P(h))之间,你要画出第三条线(我们叫它y)。这条线上会有一个“感兴趣的点”。但是在哪里呢?你需要再次计算从P(g)P(h)沿着线y移动时的某个点的位置(称为P(y))。
你要寻找的是P(y)的位置。

function setup() {
  createCanvas(400, 400);
  fraction = 0;
  drawnPoints = [];
}

function draw() {
  background(100);
  let start = new Point(30, 50, 5);
  let end = new Point(300, 170, 5);
  let weight = new Point(200, 300, 5);

  let lineStartWeight = new Line(start, weight);
  let lineStartWeightPoint = lineStartWeight.getPointAt(fraction);
  let lineWeightEnd = new Line(weight, end);
  let lineWeightEndPoint = lineWeightEnd.getPointAt(fraction);

  let drawingLine = new Line(lineStartWeightPoint, lineWeightEndPoint);

  start.draw('red');
  end.draw('blue');
  weight.draw('#0f0');
  lineStartWeight.draw('#ff0');

  lineWeightEnd.draw('#0ff');

  lineStartWeightPoint.draw('#000');
  lineWeightEndPoint.draw('#fff')

  drawingLine.draw('#f66');

  drawnPoints.push(drawingLine.getPointAt(fraction));

  drawnPoints.forEach(p => p.draw(''));

  fraction += 0.01

  if (fraction > 1) {
    fraction = 0;
    drawnPoints = [];
  }

}

class Point {
  constructor(x, y, size = 1) {
    this.x = x;
    this.y = y;
    this.size = size;
  }

  draw(color) {
    fill(color);
    noStroke();
    ellipse(this.x, this.y, this.size, this.size);
  }
}

class Line {
  constructor(pointStart, pointEnd) {
    this.pointStart = pointStart;
    this.pointEnd = pointEnd;
  }

  draw(color) {
    stroke(color);
    line(this.pointStart.x, this.pointStart.y, this.pointEnd.x, this.pointEnd.y);
  }

  getPointAt(fraction) {
    let xCoord = (this.pointEnd.x - this.pointStart.x) * fraction + this.pointStart.x;
    let yCoord = (this.pointEnd.y - this.pointStart.y) * fraction + this.pointStart.y;
    return new Point(xCoord, yCoord, 5);
  }
}
html, body {
  margin: 0;
  padding: 0;
}
<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.1/p5.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.1/addons/p5.dom.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.1/addons/p5.sound.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>
  <body>
    <script src="sketch.js"></script>
  </body>
</html>


编辑

这归结为一个简单的函数。我只会在 x 值上说明它,但 y 值的情况类似。

起点(x1|y1),终点(x2|y2),控制点(x3|y3),f = 动画时间的占比

要获得时间 f 点上的 x 值,你需要:

x = (((x2-x3)*f+x3)-((x3-x1)*f+x1))*f+((x3-x1)*f+x1)

经过一些简化,你可以得到:

x = f2(x1+x2-2x3) +2f(x3-x1)+x1


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接