绘制/使用100万个节点



我正忙于在窗格上绘制节点的练习。我的第一个目标是使用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中的节点。

我希望能在这方面提供一些指导,以及如何处理这样的大数据结构。我是朝着正确的方向前进,还是错过了一个明显的"窍门"。

需要考虑以下几点:

  1. 您的节点有多复杂?如果它们只是点,你可以考虑把它们画在可写图像上,这样可以节省很多内存。对于更复杂的情况,您可能需要使用Canvas。无论哪种方式,您都可以节省事件处理程序、属性和其他数量较大的小事。

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

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

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

您想要的属于空间分区结构的类别。

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

如果你的数据集是非均匀的,即有紧密的团块和大的空白空间,你可能想尝试一种替代结构,比如四叉树。

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

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

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

  • graphical:使用一个非常大的画布(比如10M x 10M),一次绘制小瓷砖(比如1K x 1K像素),然后缩小这些瓷砖来组成最终图像(例如,1K x 1K->10 x 10,两次,可以将10M x 10M的虚拟画布缩小为1K x 1T图像)。

  • 语义:将节点簇聚合为单个节点,并绘制簇节点而不是单个节点。你可以在几个层次上做到这一点。事实上,如果你计划绘制图形,这正是下面的图形绘制算法所要做的(没有一种图形绘制算法在合理的时间内处理>50K个节点,而不进行某种层次分解)。

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

最新更新