【问题标题】:Calculating a quad curve between two xy points计算两个 xy 点之间的四边形曲线
【发布时间】:2011-12-16 18:35:08
【问题描述】:

我有两个 (x,y) 点起点和终点。我想从头到尾制作动画,但我想创建一条曲线路径,而不是采用线性方式。

我很确定我不是在寻找缓动,因为我不想影响动画速度,我只想计算曲线路径。

我发现我需要某种控制点,如下图所示:

但我不知道如何实现它。我很想创建一个采用以下参数的函数

function calculateXY(start, end, controlpoint, percentage);

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

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

【问题讨论】:

    标签: java ios animation math bezier


    【解决方案1】:

    Cocoa's bezier paths: (NSBezierPath)

    看起来它可能不支持二次贝塞尔曲线,所以你需要convert to cubic

    【讨论】:

      【解决方案2】:

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

      我无法提供代码,但如果您对所涉及的数学有所了解,我可以解释它如何适用于四边形曲线。

      首先了解控制点在数学上的影响。控制点和两个定义点定义了绘制线在当前点和端点处的渐变。您可以使用 m = (y - y1)/(x - x1) 计算两条线的梯度。

      从数学上讲,您接下来要解决的是 a、b、c 的这组方程:

      ax^2 + bx + c 包含起点和终点

      2ax + b 等于对应 x 值处的对应梯度。

      此时,您就有了可用于画线的二次方。

      【讨论】:

        【解决方案3】:

        我在工作中看到了这个,想在家里试一试。看了this example from Wikipedia一段时间后,我想我明白了,该怎么做,下面你会找到一个例子,我现在就解释一下。

        我将使用 0 到 1 之间的时间间隔。介于两者之间的任何数字都是动画的时间分数。您想要的是在给定的时间段内获得您“兴趣点”的位置。第一步是,你有三个点ABC 由两条线连接(g => [AB]h => [BC])。对于这些线中的每一条,您都必须计算点,这些点在 startPoint 和 weightPoint P(g) 之间徘徊,分别在 weightPoint 和 endPoint 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 的工作方式类似。

        start(x1|y1), end(x2|y2) , 控制点(x3|y3), f = 动画时间的分数

        要在某个时间点获取 x 值 f 你有:

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

        经过一些简化后,您得出:

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

        【讨论】:

          猜你喜欢
          • 2012-04-06
          • 1970-01-01
          • 1970-01-01
          • 2018-09-28
          • 2012-11-10
          • 2014-06-21
          • 1970-01-01
          • 2017-10-12
          相关资源
          最近更新 更多