【问题标题】:Mapping Pixels to Data将像素映射到数据
【发布时间】:2010-08-11 13:25:31
【问题描述】:

我在修改过的 JPanel 的图形上下文中使用 drawLine() 在 Clojure/Java 中编写了一些基本的图形软件。绘图本身运行良好,但我在尝试将点击的像素转换为最近的数据点时陷入了僵局。

我在标记线条端点的所有像素列表和我的实际原始数据之间有一个简单的双射。我需要的是从我的图形窗口的所有像素(例如,1200x600 px2)到我的像素列表中的像素的一个投影,给我一个从它到我的实际数据点的简单映射。

例如

<x,y>(px) ----> <~x,~y>(pixel points) ----> <x,y>(data)

这就是我现在想象的情况:

  • 在主图形窗口中单击了一个像素,MouseListener 捕获该事件并为我提供操作的&lt;x,y&gt; 坐标。

  • 该信息被传递给一个函数,该函数返回一个谓词,该谓词确定传递给它的值是否“足够好”,并通过具有该 pred 的列表进行过滤,并取第一个值。

    • 可能,它不是一个谓词,而是返回一个函数,该函数传递像素点列表,并返回一个元组列表(x index),这表明该点在x的大小下有多好,以及那一点是index。我会用 x 点和 y 点来做这件事。然后我过滤它并找到具有最大 x 的那个,并将那个作为最有可能是用户想要的那个点。

这些是解决这个问题的合理方法吗?似乎涉及置信度等级(可能与 pix-pt 的距离)的解决方案可能是处理器太重,如果我再次将所有点都保存在内存中,那么内存会有点重。仅使用谓词的另一种解决方案似乎并不总是准确的。

这是一个已解决的问题,正如其他图形库所展示的那样,但是除了在其中一些程序的源代码中之外很难找到有关它的信息,并且必须有更好的方法然后挖掘数千行 Java 代码来找出答案。

如果可能的话,我正在寻找更好的解决方案,或者只是针对我提供的解决方案提供一般性的指示和建议。

【问题讨论】:

    标签: java plot clojure graphing


    【解决方案1】:

    所以我猜JFreeChart 之类的东西不是为您的应用剪裁的吗?如果您还没有走这条路,我建议您在尝试自己动手之前先检查一下。

    无论如何,如果您正在寻找最接近鼠标事件的点,则获取具有最小值 Euclidean distance 的点(如果它低于某个阈值)并呈现该点将为用户提供最可预测的行为。缺点是欧几里得距离对于大型数据集来说相对较慢。您可以使用忽略平方根或BSP trees 等技巧来加快速度。但是,如果这些优化甚至是必要的,实际上取决于您正在使用多少数据点。在进入优化模式之前,在典型案例中分析一个有点幼稚的解决方案。

    【讨论】:

    • JFreeChart 会增加一层我不想处理的复杂性,但主要是它太慢了。我每秒多次重绘数千个点。欧几里得距离是有道理的;它本质上就是我现在正在玩的东西,但是将它具体化为一种方法——sqrt (sq xdiff) (sq ydiff)——是有帮助的。谢谢!
    • @Isaac:哇。所以你实际上是在每秒多次重绘所有这些点?如果您还没有使用加速表面,可能值得研究一下。另外:如果您正在搜索数千个点并想要一个交互式响应,那么某种空间优化(如 BSP 树)将是必要的。这也将是一个主要的无赖写作。不过,BSP 的并行性相对较好。当您深入研究解决方案时,请随时更新我们。我对你最终的结果很感兴趣。
    • 感谢您的提示:加速表面;当我加快绘图速度时,我可能会看一下。目前,这不是太大的问题。我通常不会每秒重绘超过几千个点,这并不算太多。至于 BSP,从 Wikipedia 文章来看,它们听起来并不特别适用:也许我遗漏了什么?
    • 最后,欧几里得距离并没有我想象的那么好,因为 x-pts 之间的距离总是一个固定的区间,而且是一个很小的区间,但是两个 y 点之间的差异可以变化疯狂地(这是一个电压随时间变化的图表,所以这是有道理的。)问题是y-vals比x-vals获得了更多的可信度,尽管实际上它们应该获得相同的相对可信度。标准化 ys 似乎也没有多大帮助……我会报告更多结果!感谢您的帮助:)
    • @Isaac:回复:BSP:BSP 树所能做的就是允许您对空间进行分区,这样您就不会为每次点击检查每个点。由于每个子区域都嵌套在一个更大的父区域中,因此您只需找到子叶子并沿着树向上走,但是需要执行许多步骤才能确保找到最近的点。回复:欧几里得距离:由于它是固定的 x 间隔并且 y 波动很大,欧几里得可能不是要走的路。沿 x 轴的一维曼哈顿可能更好。也许检查左右两个相邻点,并为明显的情况做一些 y 轴仲裁。
    【解决方案2】:

    我认为你的方法很不错。这基本上只需要对您的数据数组进行一次迭代,进行一些简单的数学运算,并且每一步都不需要分配,因此应该非常快。

    除非您开始使用某种形式的空间分区方案(如四叉树),否则它可能与您将获得的一样好,只有当您的数据数组非常大时才会真正有意义。

    一些可能有帮助的 Clojure 代码:

    (defn squared-distance [x y point]
      (let [dx (- x (.x point))
            dy (- y (.y point))]
         (+ (* dx dx) (* dy dy))))
    
    (defn closest 
      ([x y points]
        (let [v (first points)] 
          (closest x y (rest points) (squared-distance x y v) v)))
      ([x y points bestdist best]
        (if (empty? points)
          best
          (let [v (first points)
                dist (squared-distance x y v)] 
            (if (< dist bestdist)
              (recur x y (rest points) dist v)
              (recur x y (rest points) bestdist best))))))
    

    【讨论】:

    • 谢谢!在这种情况下,距离对我来说不是很好,但空间分区可能——我会研究一下。
    猜你喜欢
    • 1970-01-01
    • 2015-12-10
    • 2020-07-01
    • 1970-01-01
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    相关资源
    最近更新 更多