Qt鼠标绘制平滑曲线解决方案(2)

Qt鼠标实时绘制平滑曲线(2)

(接上篇文章)
    采用Paper.js的拟合算法,,每添加一个点就重新拟合一次,会导致每次拟合出的路径多处地方不相同。如下图(仅作示意):

    
    (图中黑色的点为拟合出来的Bezier曲线的端点,绿色的线为绘制的曲线。)

    端点一定是在采集到的点集中,曲线则距离点集中的点有一定的误差。
    在后续的拟合中,每增加一个点,拟合出的端点位置都会变化,绘制的曲线也相应变化。但总体又在误差范围内。

解决办法:
    对于点集[P0,P1,…Pn],拟合出的曲线一定是固定的,所以如果在所有的点集合中,固定插入一些端点,这些相邻的固定端点内拟合出的曲线则能保证唯一。至少能够保证,在已经插入固定端点的区间,曲线时固定的,不会因为增加新的点而产生抖动。

算法思路:
    假设所有点集合为T,定义一个f(P),表示是否将该点作为一个固定端点。
    在采集点的过程中,依据f(P)将点集T分割多多个子点集[S0, S1, … Sn]。在拟合时,对每个子点集进行拟合即可,并生成最终的Bezier曲线集合。
    不过,对一点集S拟合时,首尾端点的控制点的方向需要指定。假设P0的控制点为Pc0,向量P0Pc0的方向与P0Pn平行,Pn也一样。拟合过程中新增的端点Pi的控制点方向与Pi-1Pi+1平行。
    所以对于子点集集合[S0, S1, … Sn],假设S0=[P0,0, P01,, … P0,n],S1=[P1,0, P1,1, … P1,n],其中P0,n与P1,0为同一个点,其控制点方向与向量P0,n-1P1,1平行 ,需要在拟合子点集时指定。



试验结果:

以每15个点插入一个固定的端点,拟合误差范围在10个像素,不同的绘制速度表现也不同。
    a. 缓慢移动鼠标时:
    
    (锯齿现象降低,但波动仍然明显)

    b. 较快移动鼠标时:
    
    (平滑效果很好,且实时性不错)

但在更快的速度绘制时,最近的一些曲线仍会抖动。原因是,由于未产生新的固定端点,假设最后插入的固定端点为Pi,那么点集[Pi, …Pn]的拟合出的曲线则是不断变化的。

附上试验的代码:
链接:http://pan.baidu.com/s/1mhYbL7y 密码:x8gu
算法的代码是从Paper.js中直接提取的,仅改了很少的部分。临时测试,写的比较随意。

一些优化:
目前为止,算法的已经完成,也存在一些可以优化的地方,提升效果和效率:
1. 降低采集频率,采集频率可以根据移动的速度来调整,移动速度慢时,采集到的点间距比较小,可以忽略掉一些点。
2. 由于每次都是对所有采集的点进行拟合,已经固定下来子点集已经不需要重新拟合,甚至不需要重新绘制。

猜你喜欢

转载自blog.csdn.net/eiilpux17/article/details/78633113