非参数二次Bézier曲线,通过2D中的3个点(在R中)

时间:2013-08-27 22:10:07

标签: r bezier polynomial-math

这是关于显式/非参数二次Bézier曲线。通常你不能将二次Bézier曲线拟合到3个点,因为X变量也是一个函数(Bézier=参数函数),但是当控制点是等距的时,你可以:它被称为显式/非参数Bézier功能。我想将二次bernstein多项式拟合到2D平面中的3个随机点,并且3个控制点的x轴坐标必须是等距的。此外,(外部)控制点不必像通常那样与2个外部数据点重合。

我想这需要解决一组方程式,但哪些方程?考虑到我设置的限制,我如何在R中做到这一点(曲线通过3个数据点,控制点相同的水平距离,控制点不一定在数据点上?

二次Bézier函数是B(t)=(1-t)^ 2 * P0 + 2 * t *(1-t)* P1 + t ^ 2 * P2,

如果你在R中运行它,你会看到我的意思:

# 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是一个相似但不相同的话题。 Herehere一些不错的Bézier动画。

1 个答案:

答案 0 :(得分:0)

  

通常你不能将二次Bézier曲线拟合为3点

二次Bézier曲线有3个控制点,这意味着它有3个自由度,并且能够毫无问题地适应任意3个点。线性Bézier曲线会有问题,但二次或更高的曲线会很好。要拟合参数化Bézier,您需要为要拟合的每个点指定t值,但这是唯一棘手的一点。

如果你想要一个明确的Bézier,我们可能会这样做。我假设你想要适合的点数将在你的x范围内[-20..20]?

如果是这样,那么你需要做的第一件事就是找到你所适合的每个点的x值,然后将其转换为t值。在你的例子中,你的x范围是[-20..20],如果我正确地读你的代码,你的t范围是[0..1],所以我们需要规范化。你的t值是(x + 20)/ 40。

现在您拥有所有3个t值,您可以为3个未知数求解3个方程,其中未知数是控制点的y值。这3个方程式具有相同的形式,具体为:

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

其中tfit是你想要拟合的点的t值,而yfit是同一点的y值。

求解y0,y1和y2的方程组。


那么,让我们看看一些示例数据。我们将3个数据点作为输入:

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

我们还将显式二次贝塞尔曲线的范围作为输入

rmin = -20
rmax = 20

现在我们计算数据点的t值

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

更具体地说,这些是:

t0 = 0.38000000000000000
t1 = 0.68000000000000005
t2 = 0.70999999999999996

我们现在有3个方程式:

(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

我们正在求解y0,y1和y2,它们是显式贝塞尔曲线的y值。

我有一个方便的LSQ求解器,所以我使用它,但其他方法可以正常工作。

这是我放入的矩阵(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

以下是它产生的解决方案:

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

希望有帮助......:)