3

我正忙于在窗格上绘制节点的练习。我的第一个目标是使用 100 万个节点,然后将其增加到 1500 万个。

我有一个自定义对象图,我可以向这个对象添加边和节点。每个节点对象都有一个椭圆,我可以调用和绘制它,并且与边缘对象相同。目前我有一个为节点生成随机位置的函数。

我目前正在使用滚动窗格来启用窗格周围的平移并查看所有节点。

我认为一个好主意是使用哈希图

Map<String, ArrayList<Node>> mapX = new HashMap<String, ArrayList<Node>>();
Map<String, ArrayList<Node>> mapY = new HashMap<String, ArrayList<Node>>();

我使用以下代码将节点添加到哈希图中:

int  tempXFloor = (int)Math.floor(tempX);
ArrayList<Node> tempList = mapX.get(tempXFloor+"");
if(tempList == null){
tempList = new ArrayList<>();
}
tempList.add(node); 
mapX.put(tempXFloor+"",tempList);

然后,当我平移时,我得到当前位置,将其放置并检查地图中是否存在条目。如果存在条目,我将 ArrayList 中的所有节点添加到 nodesOnScreen。nodesOnScreen 是一个 ArrayList 类型,我将在平移时将节点添加到该列表中,同样,屏幕外的节点将从 nodesOnScreen 变量中删除。

我只绘制 ArrayList nodesOnScreen 中的节点。

我将不胜感激在这件事上的一些指导,以及如何处理这样的大数据结构。我是朝着正确的方向前进还是我错过了一个明显的“技巧”来做到这一点。

4

4 回答 4

3

你想要的属于空间分区结构的范畴。

你所描述的东西是一种特殊形式的统一网格或垃圾箱。通用版本与您的不同,因为每个 bin 的大小可能超过 1 个单位,因此更适合不同分辨率的数据集。Bins 通常对于或多或少均匀分布的数据集很有用,实现起来也非常简单。查找屏幕上的元素只需要查找您的视口所在的所有 bin。

如果您的数据集不均匀,即有紧密的团块和大的空白空间,您可能想尝试另一种结构,如四叉树

此外,如果您使用的是哈希表或任何其他 java 容器,请通过将 int 装箱为 Integer ( Map<Integer, ...>) 来使用 int,不要将其转换为字符串,这会慢得多并且消耗更多内存。

于 2012-12-18T13:19:39.053 回答
3

有几点需要思考:

  1. 你的节点有多复杂?如果它们只是点,您可以考虑在WritableImage上绘制它们并节省大量内存。对于更复杂的情况,您可能需要使用Canvas。无论哪种方式,您都将节省大量的事件处理程序、属性和其他小东西。

  2. 另一个重要的问题是数据视图的相关性。如果您提供地图或类似的东西,那么用户只关心可见部分。其余的可以存储在磁盘缓存中,根据帕累托原则,只有 20% 的数据会有很大用处。因此,您可以相应地进行计划,并且仅针对可见部分使用真实的图形节点(并且可能为了用户体验而预加载一些调整后的部分)。

  3. “分而治之”的构想。即使您不想根据计划 (2) 限制用户视图,您也不能一直需要 1500 万个节点。不在 UI 库中,恐怕没有足够大的显示器。因此,将您的数据分成多个段并一次加载一个段。如果您需要对整个集合执行任何类型的计算——不要使用节点,使用最简单的实现并在某些后台进程中执行计算。

  4. 现有的解决方案总是在做大事之前进行调查。例如,有很多像PojoCache这样的缓存库,只有在您将数十亿个节点分成组时,它们才能无缝地允许您使用相关数据。

于 2012-12-18T17:21:17.467 回答
2

您可以尝试使用数据虚拟化和数据提供程序“即时”构建它。不要使用 RAM 来保存大数据。使用数据库查询。实现您的 List 类型并在那里实现索引器,它将从数据库中返回一个项目。

于 2012-12-18T13:31:53.520 回答
1

考虑详细程度。您不可能在屏幕上看到 1500 万个不同的点(没有足够的像素使单个节点前景在背景之上可见)。有两种类型的详细级别方法可用:

  • 图形:使用一个非常大的画布(例如,10M x 10M),一次绘制小图块(例如,1K x 1K 像素)并缩小这些图块以组成最终图像(例如,1K x 1K -> 10 x 10,两次,允许您的 10M x 10M 虚拟画布缩小为 1K x 1K 图像)。

  • 语义:将节点簇聚合成单个节点,并绘制簇节点而不是单个节点。您可以在多个级别上执行此操作。实际上,如果您计划绘制图形,这正是图形绘制算法将在下面执行的操作(在没有某种层次分解的情况下,没有图形绘制算法在合理的时间内处理超过 50K 的节点)。

在这两种情况下,您都会按需提供某种缩放和详细信息;主概览仅用于平移和放大特定细节。某种空间索引(四叉树是最常见的)将允许您从磁盘或辅助存储中快速检索切片。在语义缩放场景中,您将改为向每个节点添加“父”字段,构建一个巨大的(外部序列化;除非您真的必须在内存中加载 15M 节点,否则不要在内存中加载)节点树。

于 2012-12-18T17:47:40.443 回答