Nonparametric quadratic Bezier curve through 3 points in 2D (in R)

This is about explicit / nonparametric quadratic Bezier curves. Usually you cannot match a quadratic Bezier curve with 3 points, because the X-variable is also a function (Bézier = parametric function), but when the control points are equidistant, you can: it is called an explicit / non-parametric Bezier function. I want to put Bernstein's quadratic polynomial at 3 random points in a two-dimensional plane, and the x-axis coordinates of the three control points must be equidistant. In addition, (external) control points must not coincide with two external data points, as usual.

I assume that this requires solving a set of equations, but which ones? And how do I do this in R, given the limitations that I set (a curve through 3 data points, control points of the same horizontal distance, and control points not necessarily at data points?

The quadratic Bezier function is B (t) = (1-t) ^ 2 * P0 + 2 * t * (1-t) * P1 + t ^ 2 * P2,

if you run this in R, you will see what I had in mind:

# control points are equidistant: here the horizontal distance is 20 cpx<-c(-20,0,20) # y-values can be random cpy<-c(0,2,-4) t<-seq(0,1,len=101) # the 3 control points P0<-matrix(data=c(cpx[1],cpy[1]),nrow=1,ncol=2,byrow=FALSE,dimnames=NULL) P1<-matrix(data=c(cpx[2],cpy[2]),nrow=1,ncol=2,byrow=FALSE,dimnames=NULL) P2<-matrix(data=c(cpx[3],cpy[3]),nrow=1,ncol=2,byrow=FALSE,dimnames=NULL) # the quadratic Bernstein polynomial: B<-(1-t)^2%*%P0+2*t*(1-t)%*%P1+t^2%*%P2 par(mfrow=c(1,1)) plot(cpx,cpy,type="p",pch=20,xlab="",ylab="") abline(v=c(min(cpx),max(cpx)),lty=3,col='red') text(cpx[1],cpy[1],"P0",cex=.8,pos=4) text(cpx[2],cpy[2],"P1",cex=.8,pos=1) text(cpx[3],cpy[3],"P2",cex=.8,pos=2) segments(cpx[1],cpy[1],cpx[2],cpy[2],lty=3);segments(cpx[2],cpy[2],cpx[3],cpy[3],lty=3) lines(B,col="DeepSkyBlue") # 3 random points on the curve: pnts<-sort(sample(1:length(t),3,replace=F),decreasing=F) point1<-pnts[1] point2<-pnts[2] point3<-pnts[3] points(B[point1,1],B[point1,2],col='orange',pch=20) points(B[point2,1],B[point2,2],col='orange',pch=20) points(B[point3,1],B[point3,2],col='orange',pch=20) segments(B[point1,1],B[point1,2],B[point2,1],B[point2,2],lwd=2,col='orange',lty=1) segments(B[point2,1],B[point2,2],B[point3,1],B[point3,2],lwd=2,col='orange',lty=1) 

Here is a similar, but not equal topic. Here and here are some nice Bezier animations.

+1
r bezier polynomial-math
source share
1 answer

Usually you cannot match a quadratic Bezier curve with three points

A quadratic Bezier curve has 3 control points, which means that it has 3 degrees of freedom and should be able to place any 3 points without problems. A linear Bezier curve will have problems, but quadratic or higher will be fine. To match the parametric Bézier, you need to specify t values ​​for each of the points you want to place, but this is the only difficult bit.

If you want an explicit Bezier, we will probably do it. I assume that the points you are trying to set will be in your x range [-20..20]?

If so, then the first thing you need to do is find the x value of each suitable point and then convert it to a t value. In your example, your range of x is [-20..20], and your range of t [0..1], if I read your code correctly, so we need to normalize. Your value is (x + 20) / 40.

Now that you have all the 3 t values, you are solving 3 equations for 3 unknowns, where the unknown y values ​​of the control points. All three equations have the same form, in particular:

(1-tfit) ^ 2 * y0 + 2 * tfit * (1-tfit) * y1 + tfit ^ 2 * y2 = yfit

where tfit is the t value of the point you are trying to place, and yfit is the y value of the same point.

Solve many equations for y0, y1 and y2.


So, let's look at some data examples. We will take your 3 data points as input:

 d0 = (-4.8000, 0.3648) d1 = (7.2000, -0.9792) d2 = (8.4000, -1.1928) 

We will also take as a value the range of your explicit quadratic Bezier curve.

 rmin = -20 rmax = 20 

Now we calculate t values ​​for your data points

 t0 = (d0.x - rmin) / (rmax - rmin) t1 = (d1.x - rmin) / (rmax - rmin) t2 = (d2.x - rmin) / (rmax - rmin) 

In particular, these are:

 t0 = 0.38000000000000000 t1 = 0.68000000000000005 t2 = 0.70999999999999996 

Now we have 3 equations:

 (1-t0)*(1-t0)*y0 + 2*(1-t0)*t0*y1 + t0*t0*y2 = d0.y (1-t1)*(1-t1)*y0 + 2*(1-t1)*t1*y1 + t1*t1*y2 = d1.y (1-t2)*(1-t2)*y0 + 2*(1-t2)*t2*y1 + t2*t2*y2 = d2.y 

We solve for y0, y1 and y2, which are y values ​​of the explicit bezier curve.

I had an LSQ helper, so I used it, but other methods will work fine.

Here is the matrix I set (A | b):

 0.38440000000000002 0.47120000000000001 0.14440000000000000 | 0.36480000000000001 0.10239999999999996 0.43519999999999998 0.46240000000000009 | -0.97919999999999996 0.084100000000000022 0.41180000000000005 0.50409999999999999 | -1.1928000000000001 

and here is the solution that it produced:

 y0 = -2.6513220228646483e-014 y1 = 2.0000000000000262 y2 = -4.0000000000000169 

Hope that helps .. :)

0
source share

All Articles