通过matlab中的数据点集,从B样条曲线中找到控制点

通过matlab中的数据点集,从B样条曲线中找到控制点,matlab,graphics,reverse-engineering,curve,bspline,Matlab,Graphics,Reverse Engineering,Curve,Bspline,我使用200个数据点的数据集来绘制B样条曲线,我想从这条曲线中提取100个原始控制点,用它在一个算法中解决一个问题。控制点的结果与B样条曲线的数据点的值相比太小了,所以我不知道我是否在下面的代码中出错,我需要帮助知道这一点,因为我必须使用这些控制点在一个算法中完成我的研究 数据点集的链接: 代码: % read data set dataset = importdata("path of data set here"); x = dataset(:,1); y = dataset(:,

我使用200个数据点的数据集来绘制B样条曲线,我想从这条曲线中提取100个原始控制点,用它在一个算法中解决一个问题。控制点的结果与B样条曲线的数据点的值相比太小了,所以我不知道我是否在下面的代码中出错,我需要帮助知道这一点,因为我必须使用这些控制点在一个算法中完成我的研究

数据点集的链接:

代码:

% read data set

dataset = importdata("path of data set here"); 
x = dataset(:,1);  
y = dataset(:,2);

for i=1:200
controlpoints(i,1) = x(i);
controlpoints(i,2) = y(i);
controlpoints(i,3) = 0;


end

% Create Q with some points from originla matrix controlpoints ( I take only 103 points)
counter =1;
for i=1:200
   if (i==11) || (i==20) || (i==198)
      Q(counter,:) = F(i,:);
      counter = counter +1;
   end
   if ne(mod(i,2),0)
    Q(counter,:) = F(i,:);
    counter = counter+1;
   end

  end
我使用向心方法从曲线中找到控制点,如下图所示

完成我的代码:

% 2- Create Centripetal Nodes array from Q
   CP(1) = 0;
   CP(103) =1;

     for i=2:102
       sum = 0;
       for j=2:102
         sum = sum + sqrt(sqrt((Q(j,1)-Q(j-1,1))^2+(Q(j,2)-Q(j-1,2))^2));
       end
     CP(i) = CP(i-1) + (sqrt(sqrt((Q(i,1)-Q(i-1,1))^2+(Q(i,2)-Q(i-1,2))^2))/sum);
   end

   p=3;  % degree 

   % 3- Create U_K  array from CP array    

     for i=1:103
       U_K(i) = CP(i);
     end
为了计算控制点,我们必须遵循这个方程p=Qx(R')-->R'是R矩阵的逆矩阵,因此我们必须找到R矩阵,然后通过上面的方程计算p(控制点矩阵)。以下场景用于查找R矩阵

为了计算B样条曲线中的N,我们必须使用这些递归函数

完成我的代码:

% 5- Calculate R_i_p matrix
  for a=1:100
    for b=1:100

       R_i_p(a,b) = NCalculate(b,p,U_K(a),U_K);
    end
  end

% 6- Find inverse of R_i_p matrix
  R_i_p_invers = inv(R_i_p);

% 7- Find Control points ( 100 points because we have curve with 3 degree  )


 for i=1:100
     for k=1:100
       PX(i) = R_inv(i,k) * Q(k,1);
       PY(i) = R_inv(i,k) * Q(k,2); 
     end
 end

 PX2 = transpose(PX);
 PY2 = transpose(PY);
 P = horzcat(PX2,PY2);  % The final control points you can see the values is very small compared with the original data points vlaues
查找上一个R矩阵的递归函数:

function z = NCalculate(j,k,u,U)
    if (k == 1 )
        if ( (u > U(j)) && (u <= U(j+1)) )
           z = 1;
        else
           z = 0;
        end
    else
           z = (u-U(j)/U(j+k-1)-U(j)* NCalculate(j,k-1,u,U) ) + (U(j+k)-u/U(j+k)-U(j+1) *  NCalculate(j+1,k-1,u,U));
    end
  end
注意:我更新了nCalCalculate递归函数,如果结果为NaN(不是数字),则为0

函数z=NCalculate(j,k,u,u)
如果(k==1)
如果((u>=u(j))&(u

结束

我认为在你的方法中有几个值得怀疑的问题:

  • 首先,如果尝试创建一条插值103个输入点的b样条曲线(并且没有施加其他边界条件),则无论b样条曲线的阶数是多少,b样条曲线都将有103个控制点
  • U_K数组是分配给每个输入点的参数。它们与Cox-DeBoor递归公式使用的结序列ti不同。如果b样条曲线的阶数为3,则节点序列中应有(103+3+1)个节点值。可以通过以下方式创建结值:
0)将参数表示为p[i],其中i=0至(n-1),p[0]=0.0,n为点数
1) 创建节点值,如下所示

knot[0] = (p[1]+p[2]+p[3])/D  (where D is degree)
knot[1] = (p[2]+p[3]+p[4])/D
knot[2] = (p[3]+p[4]+p[5])/D 
...... 
这些是内部结值。您应该注意,p[0]和p[n-1]将不会在该步骤中使用。您将有(n-D-1)个内部结


2) 现在,将p[0]添加到结值的前面(D+1)次,将p[n-1]添加到结值的末尾(D+1)次,就完成了。最后,总共将有(N+D+1)个结。

向心节点数组计算不应嵌套两个sqrt()。这是一个简单的输入错误,还是你在计算中实际使用了两个嵌套的sqrt()。@fang我使用它依赖于上面关于使用欧几里德距离计算向心的方程,我在一篇论文中发现了这个方程,所以我根据这个方程编写代码!这是错的还是怎么的?我没想清楚。公式是正确的。@你可以在帖子中看到我的更新,也可以在下面看到我的评论。结向量在你的更新代码中似乎不正确。对于三次b样条曲线,节点向量需要以四个0.0开始,以四个1.0结束。我不想创建b样条曲线,我有一条来自200个点的曲线,但我想应用反向工程来获得该曲线的原始控制点,曲线的阶数=3,我知道如果我只想要103个控制点,我必须在结向量上有103+p+1个元素,但实际上,如果我想在给定曲线上应用反向工程来找到原始控制点,我不会使用结向量(如果我认为是真的),我100%理解你所说的,请快速看一下这篇文章,读一下这篇文章。听起来你仍然想创建B样条曲线作为PESA的一部分。你是对的,但我们必须找到控制点,然后尝试用最少数量的控制点再次绘制此曲线。我的帖子告诉你如何以正确的方式找到控制点。我认为你目前的做法不对。你为什么不试试看它是否有效。好吧,我试过了,我把我的帖子改成了updated2,现在的问题是R矩阵的逆的值,它总是无穷大,所以在我的代码中,我把它设为零,但在这种情况下,所有控制点的结果都变成了零!
function z = NCalculate(j,k,u,U)
if (k == 1 )
    if ( (u >= U(j)) && (u < U(j+1)) )
        z = 1;
    else
        z = 0;
    end
else
    z = (u-U(j)/U(j+k-1)-U(j)* NCalculate(j,k-1,u,U) ) + (U(j+k)-u/U(j+k)-U(j+1) *  NCalculate(j+1,k-1,u,U));
end

if isnan(z)
    z =0;
end
knot[0] = (p[1]+p[2]+p[3])/D  (where D is degree)
knot[1] = (p[2]+p[3]+p[4])/D
knot[2] = (p[3]+p[4]+p[5])/D 
......