Domanda

I'm trying to work a simple Bezier curve but I just can't understand the maths behind it, if someone could explain to me this simple Bezier curve it would be awesome :)

We have

point1
X: 0
Y: 0

point2
X: 100
Y: 100

control point1
X: 0
Y: 100

So basically we have a line that starts from the top left and will get a diagonal line from the top left to the bottom right of a 100 by 100 pixel square, but now I want to try and pull that line to the control point at X position 0 and Y position 100, could someone explain to me the simple maths that happens here, can if possible show the calculations with my values :).

Thank you

P.S. a basic picture

enter image description here

UPDATE

Here is my simple javascript code that uses the equation

canvasHolder = document.getElementById( 'canvas' );
canvas = canvasHolder.getContext('2d');

var deltaT = 0.10;
var point1 = new Point(300,300);
var point2 = new Point(400,400);
var controlPoint1 = new Point(100,200);
//Bezier cruve
for( var i = 0; i < 10; i++ )
{
    var t = (i/10) * 0.1;
    var xPos = ( 1.0 * - t*t ) * point1.x + 2.0 * ( 1 - t ) * t * controlPoint1.x + t * t * point2.x;
    var yPos = ( 1.0 * - t*t ) * point1.y + 2.0 * ( 1 - t ) * t * controlPoint1.y + t * t * point2.y;
    console.log( "xPos = " + xPos + ", yPos = " + yPos );
    var particle = new Particle( "circle", xPos, yPos, 5, "#FF0000", "#333333");
    particles[i] = particle;
}

here is the output for that

xPos = 0, yPos = 0 bezierCurve.js:35
xPos = 1.9900000000000004, yPos = 3.970000000000001 bezierCurve.js:35
xPos = 3.9600000000000004, yPos = 7.880000000000001 bezierCurve.js:35
xPos = 5.909999999999999, yPos = 11.729999999999999 bezierCurve.js:35
xPos = 7.840000000000001, yPos = 15.520000000000001 bezierCurve.js:35
xPos = 9.75, yPos = 19.25 bezierCurve.js:35
xPos = 11.639999999999997, yPos = 22.919999999999998 bezierCurve.js:35
xPos = 13.509999999999996, yPos = 26.529999999999998 bezierCurve.js:35
xPos = 15.360000000000003, yPos = 30.080000000000005 bezierCurve.js:35
xPos = 17.190000000000005, yPos = 33.57000000000001

any reason on why I am getting this result

Edit,

its ok i was doing this

var xPos = ( 1.0 * - t*t ) * point1.x + 2.0 * ( 1 - t ) * t * controlPoint1.x + t * t * point2.x;

when it is this

var xPos = ( 1.0 - t*t ) * point1.x + 2.0 * ( 1 - t ) * t * controlPoint1.x + t * t * point2.x;
È stato utile?

Soluzione

Bezier curves are parametric curves. That means that you will have 2 equations: 1 for the x coordinates over the curve, and the other for the y coordinates over the curve.

In this case, you're working with a quadratic bezier. The equation for quadratic beziers is:

x(t) = (1.0 - t^2) * p0.x + 2.0 * (1 - t) * t * p1.x + t^2 * p2.x;
y(t) = (1.0 - t^2) * p0.y + 2.0 * (1 - t) * t * p1.y + t^2 * p2.y;

In this case, p0 is the start point, p1 is the control point, and p2 is the end point.

t varies from 0 to 1 over the curve. So to draw it using a standard line drawing function, you'd do the following:

float numDivisions = 100.0; // <- You need to decide what this value should be. See below
float t;
float deltaT = t / numDivisions;
MoveTo (p0.x, p0.y);
for (t = 0; t <= 1.0; t += deltaT)
{
    x = (1.0 - t*t) * p0.x + 2.0 * (1 - t) * t * p1.x + t * t * p2.x;
    y = (1.0 - t*t) * p0.y + 2.0 * (1 - t) * t * p1.y + t * t * p2.y;
    LineTo (x, y);
}

The numDivisions will control the resolution of the curves. If you only have 3 divisions, you'll get the start point, 1 point in the middle (parametrically speaking), and the end point. If you use 10,000 points, you'll probably draw much more than you need to. A rule of thumb is that the straight lines connecting the points will always be longer than the actual curve, so you never need to use a number of divisions greater than that. (You can use a Euclidean distance between the points.)

Altri suggerimenti

You can derive the parametric equations for a bezier curve from the geometrical representation:

  (a)--A-----(c)
          x    \
                C
                 \
                  \
                  (b)

Draw a line from a->c->b

Subdivide the line from a->c by a point A, where A = t *(c- a) + a, i.e. t units from a towards c (0<=t<=1). Using the same ratio t, advance from c towards b, the same t units (point C).

(Recursively) subdivide A->C to sections of t and 1-t, placing the point x at the splitting point. That's the true point located at the Bezier curve.

The same procedure can be used to generate cubic Beziers -- adding one more step to the process.

Summing: (a = { ax, ay }), A = { Ax, Ay }) etc.

  A = (c-a)*t + a = { cx-ax * t + ax, cy-ay * t + ay }
  B = (b-c)*t + c = { bx-cx * t + cx, by-cy * t + cy }       
  x = (C-A)*t + A = { Cx-Ax * t + Ax, Cy-Ay * y + Ay }

(Notice, that if a = { ax, ay, az } i.e. a 3D point, the same principle holds)

These formulas can now be combined to produce a closed form equation for Cx, Cy, [Cz] as a quadratic function of t, and constants ax,ay,cx,cy,bx,by, as in the first answer by user1118321.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top