3

我正在尝试使用一些库来绘制大量点。这些点按时间排序,它们的值可以被认为是不可预测的。

我目前的问题是,点的绝对数量使库渲染时间过长。许多点是多余的(也就是说,它们“在”由函数 y = ax + b 定义的同一条线上)。有没有办法检测和删除冗余点以加快渲染速度?

感谢您的时间。

4

3 回答 3

6

以下是针对 1.5d 图的Ramer-Douglas-Peucker算法的变体:

  1. 计算第一个点和最后一个点之间的直线方程
  2. 检查所有其他点以找到离线最远的点
  3. 如果最差点低于您想要的容差,则输出单个段
  4. 否则递归调用考虑两个子数组,使用最差点作为分离器

在 python 中,这可能是

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]是使用第一个n元素组成的数组x
  • a+bwhenabare 数组意味着连接
  • x[-1]是数组的最后一个元素

eps可以在此处看到在具有 100,000 个点且 值增加的图形上运行此实现的结果示例。

于 2011-01-16T22:05:45.143 回答
0

在我有这个想法之后,我遇到了这个问题。跳过绘图上的冗余点。我相信我想出了一个更好、更简单的解决方案,我很高兴分享我在 SO 上提出的第一个解决方案。我已经对其进行了编码,并且对我来说效果很好。它还考虑了屏幕比例。这些绘图点之间可能有 100 个值,但如果用户的图表尺寸较小,他们将看不到它们。

因此,遍历数据/绘图循环,在绘制/添加下一个数据点之前,先查看下一个值并计算屏幕比例的变化(或值,但我认为出于上述原因的屏幕比例更好)。现在对前面的下一个值执行相同的操作(获取这些值只是在您的数组/集合/列表/等中向前窥视的问题,在循环中将 for next step 增量(可能是 1/2)添加到当前 for 值)。如果 2 个值相同(或者可能是非常小的变化,根据您自己的喜好),您可以通过简单地在循环中添加“继续”来跳过图表中的这一点,跳过添加数据点,因为该点正好位于前后点之间的斜率。

使用这种方法,我将图表从 963 点减少到 427 点,视觉变化绝对为零。

我想你可能需要读几遍才能理解,但它比这里提到的其他最佳解决方案要简单得多,重量更轻,对你的情节的视觉影响为零。

于 2021-03-06T07:05:59.697 回答
-2

我可能会应用“最小二乘”算法来获得最佳拟合线。然后,您可以遍历您的点并向下过滤靠近该线的连续点。您只需要绘制异常值,以及将曲线带回最佳拟合线的点。

编辑:您可能不需要使用“最小二乘法”;如果您的输入预计会像您所说的那样徘徊在“y = ax + b”附近,那么这已经是您最合适的路线,您可以使用它。:)

于 2011-01-16T22:02:58.467 回答