我正在尝试使用某个库绘制大量点。这些点按时间排序,它们的值可以被认为是不可预测的。
目前我的问题是,点的数量太多了,使得绘图库渲染时间过长。许多点是冗余的(也就是说,它们在由函数y = ax + b定义的同一条线上)。有没有一种方法来检测和去除冗余的点以加速渲染?
感谢您的时间。
我正在尝试使用某个库绘制大量点。这些点按时间排序,它们的值可以被认为是不可预测的。
目前我的问题是,点的数量太多了,使得绘图库渲染时间过长。许多点是冗余的(也就是说,它们在由函数y = ax + b定义的同一条线上)。有没有一种方法来检测和去除冗余的点以加速渲染?
感谢您的时间。
def simplify(pts, eps):
if len(pts) < 3:
return pts
x0, y0 = pts[0]
x1, y1 = pts[-1]
m = float(y1 - y0) / float(x1 - x0)
q = y0 - m*x0
worst_err = -1
worst_index = -1
for i in xrange(1, len(pts) - 1):
x, y = pts[i]
err = abs(m*x + q - y)
if err > worst_err:
worst_err = err
worst_index = i
if worst_err < eps:
return [(x0, y0), (x1, y1)]
else:
first = simplify(pts[:worst_index+1], eps)
second = simplify(pts[worst_index:], eps)
return first + second[1:]
print simplify([(0,0), (10,10), (20,20), (30,30), (50,0)], 0.1)
输出结果为[(0, 0), (30, 30), (50, 0)]
。
关于Python数组语法的一些可能不太明显的部分:
x[a:b]
是从索引a
到索引b
(不包括)的数组部分x[n:]
是使用x
中从索引n
到结尾的元素构成的数组x[:n]
是使用x
的前n
个元素构成的数组a+b
,当a
和b
是数组时,表示连接x[-1]
是数组的最后一个元素在具有100,000个点的图上使用递增的eps
值运行此实现的结果示例可以在这里看到。
我在想法后遇到了这个编程问题。跳过图表中的冗余点。我相信我想出了一个更好、更简单的解决办法,很高兴将其作为我的第一个SO建议解决方案分享。我已经编写并测试了它,效果很好。它还考虑了屏幕比例因素。在这些图表点之间可能有100个值,但如果用户的图表尺寸较小,他们就无法看到这些值。
因此,在迭代数据/图表循环之前,在绘制/添加下一个数据点之前,查看前面的下一个值并计算屏幕比例(或值)的变化(但我认为由于上述原因,屏幕比例更好)。现在对于往后的下一个值做同样的操作(获取这些值只是通过查看您的数组/集合/列表等向前推进一步进行增量添加(可能是1/2)到当前的值而已),如果 2个值相同(或者根据自己的喜好可能存在非常小的变化),则可以通过在循环中简单地添加“continue”来跳过图表中的这一个点,跳过添加数据点,因为该点恰好位于其前后点之间的斜率上。
使用这种方法,我将一个具有963点的图表减少到427点,而绝对没有视觉变化。
我认为你可能需要多读几遍才能理解,但这比其他提到的最佳解决方案简单得多,更轻量级,并且对你的绘图没有任何视觉影响。
我可能会应用“最小二乘法”算法来获得最佳拟合直线。然后,您可以浏览您的点并向下过滤接近该直线的连续点。您只需要绘制异常值和将曲线带回最佳拟合直线的点。
编辑:您可能不需要使用“最小二乘法”;如果您的输入预计围绕“y = ax + b”徘徊,那么这已经是您的最佳拟合直线,您可以直接使用它。 :)