From 3e07449c8790b817b2fb3304432244b5ea11f369 Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Tue, 20 Jun 2023 11:17:23 +0800 Subject: [PATCH] =?UTF-8?q?:art:=20=E6=B3=A8=E9=87=8A=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/astar/astar.go | 21 +++++++++++++- utils/astar/graph.go | 4 +-- utils/geometry/geometry.go | 2 +- utils/geometry/navmesh/navmesh.go | 47 +++++++++++++++++++++++++++++-- 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/utils/astar/astar.go b/utils/astar/astar.go index 9122db1..994cfed 100644 --- a/utils/astar/astar.go +++ b/utils/astar/astar.go @@ -5,7 +5,26 @@ import ( "github.com/kercylan98/minotaur/utils/generic" ) -// Find 使用成本函数和成本启发式函数在图中找到起点和终点之间的最低成本路径。 +// Find 使用 A* 算法在导航网格上查找从起点到终点的最短路径,并返回路径上的节点序列。 +// +// 参数: +// - graph: 图对象,类型为 Graph[Node],表示导航网格。 +// - start: 起点节点,类型为 Node,表示路径的起点。 +// - end: 终点节点,类型为 Node,表示路径的终点。 +// - cost: 路径代价函数,类型为 func(a, b Node) V,用于计算两个节点之间的代价。 +// - heuristic: 启发函数,类型为 func(a, b Node) V,用于估计从当前节点到目标节点的启发式代价。 +// +// 返回值: +// - []Node: 节点序列,表示从起点到终点的最短路径。如果找不到路径,则返回空序列。 +// +// 注意事项: +// - graph 对象表示导航网格,其中包含了节点和连接节点的边。 +// - start 和 end 分别表示路径的起点和终点。 +// - cost 函数用于计算两个节点之间的代价,可以根据实际情况自定义实现。 +// - heuristic 函数用于估计从当前节点到目标节点的启发式代价,可以根据实际情况自定义实现。 +// - 函数使用了 A* 算法来搜索最短路径。 +// - 函数内部使用了堆数据结构来管理待处理的节点。 +// - 函数返回一个节点序列,表示从起点到终点的最短路径。如果找不到路径,则返回空序列。 func Find[Node comparable, V generic.SignedNumber](graph Graph[Node], start, end Node, cost, heuristic func(a, b Node) V) []Node { closed := make(map[Node]bool) diff --git a/utils/astar/graph.go b/utils/astar/graph.go index 74b2d24..e9852b2 100644 --- a/utils/astar/graph.go +++ b/utils/astar/graph.go @@ -1,7 +1,7 @@ package astar -// Graph 适用于 A* 算法的图数据结构接口定义 +// Graph 适用于 A* 算法的图数据结构接口定义,表示导航网格,其中包含了节点和连接节点的边。 type Graph[Node comparable] interface { - // Neighbours 返回特定节点的邻居节点 + // Neighbours 返回与给定节点相邻的节点列表。 Neighbours(node Node) []Node } diff --git a/utils/geometry/geometry.go b/utils/geometry/geometry.go index 0d24c69..0d88d10 100644 --- a/utils/geometry/geometry.go +++ b/utils/geometry/geometry.go @@ -147,6 +147,6 @@ func CalcAngleDifference[V generic.Number](angleA, angleB V) V { a := t + V(pi) b := V(pi) * 2 t = V(math.Floor(float64(a/b))) * b - t -= pi + t -= V(pi) return t } diff --git a/utils/geometry/navmesh/navmesh.go b/utils/geometry/navmesh/navmesh.go index 4c7b9f7..1f6a0ee 100644 --- a/utils/geometry/navmesh/navmesh.go +++ b/utils/geometry/navmesh/navmesh.go @@ -7,6 +7,20 @@ import ( "github.com/kercylan98/minotaur/utils/maths" ) +// NewNavMesh 创建一个新的导航网格,并返回一个指向该导航网格的指针。 +// +// 参数: +// - shapes: 形状切片,类型为 []geometry.Shape[V],表示导航网格中的形状。 +// - meshShrinkAmount: 网格缩小量,类型为 V,表示导航网格的缩小量。 +// +// 返回值: +// - *NavMesh[V]: 指向创建的导航网格的指针。 +// +// 注意事项: +// - 导航网格的形状可以是任何几何形状。 +// - meshShrinkAmount 表示导航网格的缩小量,用于在形状之间创建链接时考虑形状的缩小效果。 +// - 函数内部使用了泛型类型参数 V,可以根据需要指定形状的坐标类型。 +// - 函数返回一个指向创建的导航网格的指针。 func NewNavMesh[V generic.SignedNumber](shapes []geometry.Shape[V], meshShrinkAmount V) *NavMesh[V] { nm := &NavMesh[V]{ meshShapes: make([]*shape[V], len(shapes)), @@ -24,11 +38,27 @@ type NavMesh[V generic.SignedNumber] struct { meshShrinkAmount V } +// Neighbours 实现 astar.Graph 的接口,用于向 A* 算法提供相邻图形 func (slf *NavMesh[V]) Neighbours(node *shape[V]) []*shape[V] { return node.links } -// Find 在网格中找到与给定点最近的点。如果该点已经在网格中,这将为您提供该点。如果点在网格之外,这将尝试将此点投影到网格中(直到给定的 maxDistance) +// Find 用于在 NavMesh 中查找离给定点最近的形状,并返回距离、找到的点和找到的形状。 +// +// 参数: +// - point: 给定的点,类型为 geometry.Point[V],表示一个 V 维度的点坐标。 +// - maxDistance: 最大距离,类型为 V,表示查找的最大距离限制。 +// +// 返回值: +// - distance: 距离,类型为 V,表示离给定点最近的形状的距离。 +// - findPoint: 找到的点,类型为 geometry.Point[V],表示离给定点最近的点坐标。 +// - findShape: 找到的形状,类型为 geometry.Shape[V],表示离给定点最近的形状。 +// +// 注意事项: +// - 如果给定点在 NavMesh 中的某个形状内部或者在形状的边上,距离为 0,找到的形状为该形状,找到的点为给定点。 +// - 如果给定点不在任何形状内部或者形状的边上,将计算给定点到每个形状的距离,并找到最近的形状和对应的点。 +// - 距离的计算采用几何学中的投影点到形状的距离。 +// - 函数返回离给定点最近的形状的距离、找到的点和找到的形状。 func (slf *NavMesh[V]) Find(point geometry.Point[V], maxDistance V) (distance V, findPoint geometry.Point[V], findShape geometry.Shape[V]) { var minDistance = maxDistance var closest *shape[V] @@ -57,7 +87,20 @@ func (slf *NavMesh[V]) Find(point geometry.Point[V], maxDistance V) (distance V, return minDistance, pointOnClosest, closest.Shape } -// FindPath 使用此导航网格查找从起点到终点的路径。 +// FindPath 函数用于在 NavMesh 中查找从起点到终点的路径,并返回路径上的点序列。 +// +// 参数: +// - start: 起点,类型为 geometry.Point[V],表示路径的起始点。 +// - end: 终点,类型为 geometry.Point[V],表示路径的终点。 +// +// 返回值: +// - result: 路径上的点序列,类型为 []geometry.Point[V]。 +// +// 注意事项: +// - 函数首先根据起点和终点的位置,找到离它们最近的形状作为起点形状和终点形状。 +// - 如果起点或终点不在任何形状内部,且 NavMesh 的 meshShrinkAmount 大于0,则会考虑缩小的形状。 +// - 使用 A* 算法在 NavMesh 上搜索从起点形状到终点形状的最短路径。 +// - 使用漏斗算法对路径进行优化,以得到最终的路径点序列。 func (slf *NavMesh[V]) FindPath(start, end geometry.Point[V]) (result []geometry.Point[V]) { var startShape, endShape *shape[V] var startDistance, endDistance = V(-1), V(-1)