凸面多边形寻路算法

写在前面

什么是凸面多边形

凸多边形是一个内部为凸集的简单多边形。凸多边形(Convex Polygon)指如果把一个多边形的所有边中,任意一条边向两方无限延长成为一直线时,其他各边都在此直线的同旁,那么这个多边形就叫做凸多边形,其内角应该全不是钝角,任意两个顶点间的线段位于多边形的内部或边上。

凸面多边形在寻路应用中有什么性质

凸面多边形一条边上的任意一点到另外一条边上的任意一点总是可达的。

什么是floyd算法

http://blog.****.net/qq_35644234/article/details/60875818

什么是地图网格

地图网格就是一个凸面多边形的集合
如果可视化就是这样
凸面多边形寻路算法

数据结构定义

三维向量(Vector3):

Created with Raphaël 2.1.2xxVector3Vector3yyzzdoubledoubledouble

顶点(Vertex):

Created with Raphaël 2.1.2postionpostionVertexVertexididVector3int

边(Edge):

Created with Raphaël 2.1.2v1v1EdgeEdgev2v2VertexVertex

凸面(Convex):

Created with Raphaël 2.1.2vertexsvertexsConvexConvexArrayList<Vertex>

网格(Mesh):

Created with Raphaël 2.1.2convexsconvexsMeshMeshedgeNodeSplitLengthedgeNodeSplitLengthnamenameList<Convex>doubleString

UML:

Created with Raphaël 2.1.2doubledoubleVector3Vector3VertexVertexintintEdgeEdgeConvexConvexMeshMeshStringStringNodeNodeConnectionConnectionConvexInfoConvexInfoEdgeInfoEdgeInfoIntegerIntegerRectRectxyzpostionidv1v2ArrayList<Vertex> vertexsList<Convex> convexsedgeNodeSplitLengthnameidpostionHashMap<Integer, Connection>() connectionsArrayList<ConvexInfo> convexsedgecosttoedgeArrayList<Node> nodesArrayList<ConvexInfo>idconvexArrayList<EdgeInfo> edgesArrayList<Node> nodesHashSet<Integer> nodeIdsbox

步骤

1.数据预处理
2.通过floyd算法生成P矩阵
3.利用P矩阵求出路径列表
4.优化路径
5.输出

数据预处理

1.遍历Mesh中每个Convex,生成多边形所有的边
2.将每条边进行切割生成对应的点
3.将位于同一个Convex的点之间建立连通关系并计算权值(通过距离)

通过floyd算法生成P矩阵

1.初始化floyd算法需要的D矩阵和P矩阵
2.通过之前的连通图执行floyd算法
3.生成P矩阵

利用P矩阵求出路径列表

1.输入起点from,终点to
2.在P矩阵中查找P[from][to]查询下一步的节点next
3.将查询到的结果记录下来,并让from = next
4.循环以上操作获得路径列表

优化路径

为什么要优化路径

未优化的路径:
凸面多边形寻路算法
优化后的路径:
凸面多边形寻路算法
1.优化后经过的节点数更少
2.优化后路径更自然
3.优化后路径更短

如何优化

首先我们挨个判断每个点是否需要保留。这里通过一种基于视点范围的方法来判断,
我们首先令from点为视点(viewPosition)(及路径中的第一个点),
那么第二个点则为cur点,
我们令cur所在edge的两端点到视点的向量为最小左视野(minLegLeft)和最小右视野(minLegRight)。

现在将cur赋值为第三个点,
我们令cur所在edge的两端点到视点的向量为左视野(legLeft)和右视野(legRight)。
如果cur到viewPosition的向量没有在最小视野当中,证明cur是不可达的,
那么此时最小左视野所在边上的路径点就叫做拐点。
我们首先调整拐点位置,将拐点加入优化后的路径表中,并将拐点作为viewPosition重新进行上述循环。
如果legLeft在minLegLeft右边那么我们令minLegLeft = legLeft
如果legRight在minLegLeft左边那么我们令minLegRight = legRight

如何调整拐点位置

调整拐点位置是为了使路径更自然,所以我们应该让视点到拐点与下一个到拐点的向量的夹角变小。
如果此时拐点到下一点的连线在最小左视野左边则拐点往左移,反之往右移。