使用networkx绘制任务关系图
想要绘制管理学上,任务与任务之间的指向(前置)关系,发现并没有现成的库可以用来解决相关问题。后来发现networkx可以用来指定Node和edge之间的关系,具体的networkx的教程,可以参考各个博主的文章。
networkx可以方便的添加node和edge,但是networkx现有的layout对于流程图式的从左推到右的图形并不支持。已有的例如,随机布局,星状布局,圆形布局等,都不满足流程图布局,为了实现,流程图的最终调用关系(见下图),我们需要自己来指定各个节点在画板上的位置问题,此文做为一个算法的实现,效果仅做参考。
解决方案
为了能够使得networks能够生成如上的图片,我们需要解决的核心问题是指定每个节点在于图上的位置,也就是networkx中的pos参数。pos是一个字典列表,其中每一个元素指定了某一个节点对应的二维坐标,从左下角(0,0)–>右上角(1,1)之间。
需求
1:紧后节点位于当前节点右边
2:尽量少的交叉线
3:节点布局尽量均匀
4:给出足够的信息()
算法
我们发明的算法的核心思想为,在横坐标和纵坐标上尽可能均匀分布。给出一个概念,记任意节点的横坐标为x,则其紧后任务的横坐标为x+1,表示先后关系,多个节点有同一个紧后节点时,取最大值,确保其横坐标在所有紧前任务之后。每个点的x值记做阶段值,任务1通常为开始任务,阶段记做0,最后的结束任务一定有最大的阶段值。
为了能在图上尽可能的均匀分布,横坐标我们使用了阶段值来分配,对于纵坐标则使用同一阶段的节点来均匀分布。所以核心算法为,知道每个节点对应的阶段值,以及该阶段一共有多少个任务。
类似于计数排序算法加广度优先算法,由于遍历暂不知道最后的各阶段节点数目,所以需要先记录
- 以开始节点1作为第0层,横坐标为0的节点,标志1号任务在图形最左边
- 从节点1开始遍历,所有的当前的节点的横坐标 = 当前节点横坐标 + 1,如果有多次被指向,取最大值覆盖。
- 使用列表,记录每一个属于此横坐标的节点
- 去除不同横坐标对应的列表中的节点的重复值,以下标大的列表生效。
- 遍历列表组,对每一个i列表的j元素,给定pos值为pos[node] = [ (1.0/maxCol)(i)+(0.5/maxCol),(1.0/listLen)(j)+(0.5/listLen)],其中MaxCol表示结束任务的阶段值,listLen表示当前i列表的元素个数。
效果
效果见上图,均匀分布以及先后关系已经完成,而且因为是广度优先,下一阶段节点的添加顺序,与当前阶段的节点的紧后节点的顺序一致,确保尽量少的交叉线。
尚未解决
1:未找到添加节点多个标签的方式,否则可以直接展示整个单代号节点的全部信息。
2:实际上后续的节点可能会变少,图片分配可以更加均匀一些。