删除线图的冗余点

发布于 2024-10-12 00:45:53 字数 168 浏览 8 评论 0原文

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

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

谢谢您的宝贵时间。

I am trying to plot large amounts of points using some library. The points are ordered by time and their values can be considered unpredictable.

My problem at the moment is that the sheer number of points makes the library take too long to render. Many of the points are redundant (that is - they are "on" the same line as defined by a function y = ax + b). Is there a way to detect and remove redundant points in order to speed rendering ?

Thank you for your time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

物价感观 2024-10-19 00:45:53

以下是 Ramer-Douglas-Peucker< 的变体/a> 1.5d 图的算法:

  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 使用 x a+b 的前 n 个元素组成的数组
  • ] 是当 a 和 < 时 code>b 是数组,表示串联
  • x[-1] 是数组的最后一个元素 在

具有 100,000 个点且 < 值不断增加的图上运行此实现的结果示例code>eps 可以在此处查看。

The following is a variation on the Ramer-Douglas-Peucker algorithm for 1.5d graphs:

  1. Compute the line equation between first and last point
  2. Check all other points to find what is the most distant from the line
  3. If the worst point is below the tolerance you want then output a single segment
  4. Otherwise call recursively considering two sub-arrays, using the worst point as splitter

In python this could be

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)

The output is [(0, 0), (30, 30), (50, 0)].

About python syntax for arrays that may be non obvious:

  • x[a:b] is the part of array from index a up to index b (excluded)
  • x[n:] is the array made using elements of x from index n to the end
  • x[:n] is the array made using first n elements of x
  • a+b when a and b are arrays means concatenation
  • x[-1] is the last element of an array

An example of the results of running this implementation on a graph with 100,000 points with increasing values of eps can be seen here.

七分※倦醒 2024-10-19 00:45:53

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

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

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

我认为您可能需要阅读几次才能理解,但它比这里提到的其他最佳解决方案简单得多,重量轻得多,并且对您的情节的视觉效果为零。

I came across this question after I had this very idea. Skip redundant points on plots. I believe I came up with a far better and simpler solution and I'm happy to share as my first proposed solution on SO. I've coded it and it works well for me. It also takes into account the screen scale. There may be 100 points in value between those plot points, but if the user has a chart sized small, they won't see them.

So, iterating through your data/plot loop, before you draw/add your next data point, look at the next value ahead and calculate the change in screen scale (or value, but I think screen scale for the above-mentioned reason is better). Now do the same for the next value ahead (getting these values is just a matter of peeking ahead in your array/collection/list/etc adding the for next step increment (probably 1/2) to the current for value whilst in the loop). If the 2 values are the same (or perhaps very minor change, per your own preference), you can skip this one point in your chart by simply adding 'continue' in the loop, skipping adding the data point as the point lies exactly on the slope between the point before and after it.

Using this method, I reduce a chart from 963 points to 427 for example, with absolutely zero visual change.

I think you might need to perhaps read this a couple of times to understand, but it's far simpler than the other best solution mentioned here, much lighter weight, and has zero visual effect on your plot.

各空 2024-10-19 00:45:53

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

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

I would probably apply a "least squares" algorithm to obtain a line of best fit. You can then go through your points and downfilter consecutive points that lie close to the line. You only need to plot the outliers, and the points that take the curve back to the line of best fit.

Edit: You may not need to employ "least squares"; if your input is expected to hover around "y=ax+b" as you say, then that's already your line of best fit and you can just use that. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文