前端使用 Konva 实现可视化设计器(13)- 折线 - 最优路径应用【思路篇】

konva · 浏览次数 : 0

小编点评

**优化后的数组矩阵与折线表示** 考虑到在 800x800 画布上进行路径规划的不现实性,我们需要通过优化算法来降低内存占用和提高计算效率。 首先,我们采用一个更紧凑的数据结构——动态二叉树(Binary Tree),而非二维数组矩阵。这样做的好处是可以有效节省存储空间,并允许我们在每个层级上维护更复杂的结构。 具体来说,我们将原始的二维数组矩阵简化为一个动态的二叉树,其中父节点和子节点之间的关系由元素的值决定。此外,我们还引入了一个标志位 `wall` 来标记边界上的位置是不可通过的。 以下是基于优化后的数组矩阵与折线表示的主要内容总结: 1. **数组矩阵简化**:我们将原始的二维数组矩阵简化为一个动态的二叉树,其中父节点和子节点之间的关系由元素的值(通常为 0 或 1)决定。 2. **动态规划**:我们利用动态规划的思想,在每个节点处保存从根节点到该节点的最短路径代价和两倍最短路径代价(通常用于父节点计算)。 3. **曼哈顿距离计算**:在计算两点之间的最短路径时,我们采用曼哈顿距离作为启发式函数,即沿着当前节点水平和垂直方向移动的距离之和。 4. **禁止对角线移动**:为了确保算法的正确性和性能,我们约定在数组矩阵中,对于每个节点,只有左上方和右上方的位置可以被访问,即“墙”的数量为 0 或 1。 5. **连接点与折线表示**: - 连接点:我们可以将这些位置视为折线上的节点,并将它们表示为数字数组中的索引。 - 折线:折线表示则是通过一组有限的连接点和它们之间的距离来描述的,这些连接点是用户通过交互或算法生成的。 **优势分析与后续工作** 使用动态二叉树表示折线路径相较于原始的二维数组矩阵实现,具有更高的灵活性和更快的运行速度,因为它能够更有效地管理内存并减少不必要的计算。在未来的工作中,我们可能会进一步完善算法以支持更复杂的场景,如具有障碍物的环境或更复杂的路径约束条件。同时,我们也考虑将这种转换方法推广到其他类型的数据结构和算法设计中。

正文

这一章把直线连接改为折线连接,沿用原来连接点的关系信息。关于折线的计算,使用的是开源的 AStar 算法进行路径规划,启发方式为 曼哈顿距离,且不允许对角线移动。

请大家动动小手,给我一个免费的 Star 吧~

大家如果发现了 Bug,欢迎来提 Issue 哟~

github源码

gitee源码

示例地址

灵感来源主要来自于下面优秀的文章:

关联线探究,如何连接流程图的两个节点

主要参考了:如何挑选连接点及其真正的出入口、算法的选型。具体代码没有仔细了解,毕竟布局和元素的想法不一样,没必要参考代码。

路径规划之 A* 算法

主要了解一下算法的介绍。

欧式距离、曼哈顿距离、切比雪夫距离、Octile距离

主要了解一下 AStar 算法的各种启发方式的差异。

路径规划可视化动画

形象的感受路径搜索的差异。

至于算法本身,在目前阶段下不是必须深入分析,这里应用为主。

最优路径

image

参考这张图,基于当前案例,可以把折线想象为路径,目标就是查找最优路径,例如:
image

又或者:
image

上面明显不是我们直觉最优的路径选择,如:

  • 太贴近节点了
  • 转弯太多

更希望是这样:
image
image

开启调试模式,来说说连接点的出入口:
image

人为地,距离”连接点“偏离一些,定义所谓的”出入口“(途中绿色的点),作为折线真的起点和终点。

把连线先移除,看看其他点:
image

一共定义了 3 种点:

  • 连接点(红色)
  • 出入口(绿色)
  • 途径点(蓝色)

关于途径点,是人为挑选的,主要(中心点除外)来自于图中不同颜色区域(线框),这里定义了 ?种区域:

  • 连接点最小区域

为什么叫节点区域呢?因为此前设计的连接点是动态的,它可以节点内部的其他位置,只是目前定义的都是上下左右边缘而已。所以,它可能比节点区域更小。

image

  • 连线不可通过区域

image

  • 连线不可通过扩展区域

两个区域共同所在的最小区域

image

  • 连线通过区域

image

  • 连线通过扩展区域

同理,两个区域共同所在的最小区域

image

算法建模(关键)

上面说了那么多点和区域,最终目的就是为了建模,可供算法使用。
这个模型,就是一个数组矩阵 matrix,可以理解成一个格子地图,如:
image

0 代表可通过,1 代表不可通过(称之为“墙”吧),对应的数组矩阵,就是

[
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]

计算结果是一个途径格子坐标数组:

坐标就是数组1、2层下标,可以视作 x、y 轴。
image

[
	[5, 3],
	[6, 3],
	[7, 3],
	[8, 3],
	[8, 4],
	[8, 5]
]

主要问题来了,毕竟在这里的画板,不同于算法示例那样“走格子”,800x800 的画布大小,不可能建一个 800x800 数组矩阵,性能可吃不消,别说更大的画布了。

所以,如何建模才是这个案例画折线的关键!

这里,那一个大一点的例子说明:
image

既然,拿“像素”当作格子不现实,可以拿“点”作为格子不就好了吗?
image

数组矩阵变成:

[
	[0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0]
]

这里缺少了“墙”,哪些是墙?其实就是上面说的不可通过区域:
image

“墙”不同于连接点,需要补充一些点:
image

数组矩阵变成(增加了 2 列、2 行):

[
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]

然后给数组矩阵设置“墙”:

这里把 2 定义为墙,所以 0、1 均能通过,方便后面区分和理解。

[
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
	[0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0],
	[0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0], 
	[0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0],
	[0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0],
	[0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0],
	[0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0], 
	[0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0],
	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]

连接点、连接线的出入口不应该是“墙”,调整一下:

设置为 1,方便区分

image

起点:[2, 3]
终点:[8, 5]
image

现在交给算法,计算结果得出:
image

就是:
image

画成线:
image

主要思路就是如此,虽然不是完美的,请看:
image

原因主要是算法并不知道拐弯的“代价”,暂且如此吧。
思路的介绍到此为止,下一章再说说代码大概是如何实现的。

More Stars please!勾勾手指~

源码

gitee源码

示例地址

与前端使用 Konva 实现可视化设计器(13)- 折线 - 最优路径应用【思路篇】相似的内容:

前端使用 Konva 实现可视化设计器(13)- 折线 - 最优路径应用【思路篇】

这一章把直线连接改为折线连接,沿用原来连接点的关系信息。关于折线的计算,使用的是开源的 AStar 算法进行路径规划,启发方式为 曼哈顿距离,且不允许对角线移动。 请大家动动小手,给我一个免费的 Star 吧~ 大家如果发现了 Bug,欢迎来提 Issue 哟~ github源码 gitee源码 示

前端使用 Konva 实现可视化设计器(14)- 折线 - 最优路径应用【代码篇】

话接上回[《前端使用 Konva 实现可视化设计器(13)- 折线 - 最优路径应用【思路篇】》](https://www.cnblogs.com/xachary/p/18238704),这一章继续说说相关的代码如何构思的,如何一步步构建数据模型可供 AStar 算法进行路径规划,最终画出节点之间的...

前端使用 Konva 实现可视化设计器(16)- 旋转对齐、触摸板操作的优化

这一章解决两个缺陷,一是调整一些快捷键,使得 Mac 触摸板可以正常操作;二是修复一个 Issue,使得即使素材节点即使被旋转之后,也能正常触发磁贴对齐效果,有个小坑需要注意。

前端使用 Konva 实现可视化设计器(15)- 自定义连接点、连接优化

本章将处理一些缺陷的同时,实现支持连接点的自定义,一个节点可以定义多个连接点,最终可以满足类似图元接线的效果。

前端使用 Konva 实现可视化设计器(12)- 连接线 - 直线

这一章实现的连接线,目前仅支持直线连接,为了能够不影响原有的其它功能,尝试了2、3个实现思路,最终实测这个实现方式目前来说最为合适了。 请大家动动小手,给我一个免费的 Star 吧~ 大家如果发现了 Bug,欢迎来提 Issue 哟~ github源码 gitee源码 示例地址 相关定义 连接点 记

前端使用 Konva 实现可视化设计器(11)- 对齐效果

这一章补充一个效果,在多选的情况下,对目标进行对齐。基于多选整体区域对齐的基础上,还支持基于其中一个节点进行对齐。

前端使用 Konva 实现可视化设计器(10)- 对齐线

前端使用 Konva 实现可视化设计器,这次实现对齐线的交互功能,单个、多个、多选都可以对齐,同时还能磁贴。

前端使用 Konva 实现可视化设计器(9)- 另存为SVG

请大家动动小手,给我一个免费的 Star 吧~ 大家如果发现了 Bug,欢迎来提 Issue 哟~ github源码 gitee源码 示例地址 另存为SVG 这一章增强了另存为的能力,实现“另存为SVG”,大概是全网唯一的实例分享了吧。 灵感来源:react-konva-custom-context

前端使用 Konva 实现可视化设计器(8)- 预览框

请大家动动小手,给我一个免费的 Star 吧~ 大家如果发现了明显的 Bug,可以提 Issue 哟~ 这一章我们实现一个预览框,实时、可交互定位的。 github源码 gitee源码 示例地址 预览框 定位方法 移动画布,将传入 x,y 作为画布中心: // 更新中心位置 updateCenter

前端使用 Konva 实现可视化设计器(7)- 导入导出、上一步、下一步

请大家动动小手,给我一个免费的 Star 吧~ 这一章实现导入导出为JSON文件、另存为图片、上一步、下一步。 github源码 gitee源码 示例地址 导出为JSON文件 提取需要导出的内容 getView() { // 复制画布 const copy = this.render.stage.c