1

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

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

二次贝塞尔函数为 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)

是一个相似但不相等的话题。 这里这里有一些不错的贝塞尔动画。

4

1 回答 1

0

通常你不能将二次贝塞尔曲线拟合到 3 个点

二次贝塞尔曲线有 3 个控制点,这意味着它有 3 个自由度,应该能够毫无问题地拟合任意 3 个点。线性贝塞尔曲线会有问题,但二次或更高就可以了。要拟合参数化贝塞尔曲线,您需要为要拟合的每个点指定 t 值,但这是唯一棘手的问题。

如果你想要一个明确的贝塞尔曲线,我们可能会这样做。我假设您尝试拟合的点将在您的 x 范围 [-20..20] 内?

如果是这样,那么您需要做的第一件事就是找到您要拟合的每个点的 x 值,然后将其转换为 at 值。在您的示例中,如果我正确阅读您的代码,您的 x 范围为 [-20..20] 并且您的 t 范围为 [0..1],因此我们需要进行规范化。您的 t 值为 (x+20)/40。

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

(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

希望有帮助.. :)

于 2013-08-28T10:34:52.710 回答