|
@@ -1,4 +1,5 @@
|
|
|
package com.fdkankan.indoor.base.convert.kesar;
|
|
|
+
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
import java.util.PriorityQueue;
|
|
@@ -8,201 +9,172 @@ import net.sf.json.JSONArray;
|
|
|
import net.sf.json.JSONObject;
|
|
|
|
|
|
/**
|
|
|
- *
|
|
|
- * ClassName: AStar
|
|
|
- * @Description: A鏄熺畻娉�
|
|
|
+ * ClassName: AStar
|
|
|
+ *
|
|
|
* @author kesar
|
|
|
+ * @Description: A星算法
|
|
|
*/
|
|
|
-public class AStar
|
|
|
-{
|
|
|
- public final static int BAR = 1; // 闅滅鍊�
|
|
|
- public final static int PATH = 2; // 璺緞
|
|
|
- public final static int DIRECT_VALUE = 10; // 妯珫绉诲姩浠d环
|
|
|
- public final static int OBLIQUE_VALUE = 14; // 鏂滅Щ鍔ㄤ唬浠�
|
|
|
-
|
|
|
- Queue<Node> openList = new PriorityQueue<Node>(); // 浼樺厛闃熷垪(鍗囧簭)
|
|
|
- List<Node> closeList = new ArrayList<Node>();
|
|
|
-
|
|
|
- /**
|
|
|
- * 寮�濮嬬畻娉�
|
|
|
- */
|
|
|
- public List<Node> start(MapInfo mapInfo)
|
|
|
- {
|
|
|
- if(mapInfo==null) return null;
|
|
|
- // clean
|
|
|
- openList.clear();
|
|
|
- closeList.clear();
|
|
|
- // 寮�濮嬫悳绱�
|
|
|
- openList.add(mapInfo.start);
|
|
|
- return moveNodes(mapInfo);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 绉诲姩褰撳墠缁撶偣
|
|
|
- */
|
|
|
- private List<Node> moveNodes(MapInfo mapInfo)
|
|
|
- {
|
|
|
- while (!openList.isEmpty())
|
|
|
- {
|
|
|
- Node current = openList.poll();
|
|
|
- closeList.add(current);
|
|
|
- addNeighborNodeInOpen(mapInfo,current);
|
|
|
- if (isCoordInClose(mapInfo.end.id))
|
|
|
- {
|
|
|
- List<Node> list = drawPath(mapInfo.maps, mapInfo.end);
|
|
|
- return list;
|
|
|
- }
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 鍦ㄤ簩缁存暟缁勪腑缁樺埗璺緞
|
|
|
- */
|
|
|
- private List<Node> drawPath(JSONArray maps, Node end)
|
|
|
- {
|
|
|
- if(end==null||maps==null) return null;
|
|
|
- System.out.println("路线" + end.id);
|
|
|
- List<Node> list = new ArrayList<Node>();
|
|
|
- while (end != null)
|
|
|
- {
|
|
|
- System.out.println("路线" + end.id);
|
|
|
- list.add(end);
|
|
|
- Coord c = end.coord;
|
|
|
- //maps[c.y][c.x] = PATH;
|
|
|
- end = end.parent;
|
|
|
- }
|
|
|
- return list;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 娣诲姞鎵�鏈夐偦缁撶偣鍒皁pen琛�
|
|
|
- */
|
|
|
- private void addNeighborNodeInOpen(MapInfo mapInfo,Node current)
|
|
|
- {
|
|
|
- int id = current.id;
|
|
|
- JSONObject item = mapInfo.maps.getJSONObject(id);
|
|
|
- String[] linkedIds = item.getString("linkedIds").split(",");
|
|
|
-
|
|
|
- for(int i=0;i<linkedIds.length;++i) {
|
|
|
- int linkedId = Integer.valueOf(linkedIds[i])-1;
|
|
|
- if (canAddNodeToOpen(mapInfo,linkedId))
|
|
|
- {
|
|
|
- Node end=mapInfo.end;
|
|
|
- //Coord coord = new Coord(x, y);
|
|
|
- //Double G = current.G + current.weight; // 计算邻结点的G值
|
|
|
-
|
|
|
- JSONObject linkedNode = mapInfo.maps.getJSONObject(linkedId);
|
|
|
- double weight = calcH(current.coord,new Coord(linkedNode.getDouble("x"),linkedNode.getDouble("y"),linkedNode.getDouble("z")));
|
|
|
- Double G = current.G + weight; // 计算邻结点的G值
|
|
|
- //Double G = current.G + current.weight; // 计算邻结点的G值
|
|
|
- Node child = findNodeInOpen(linkedId);
|
|
|
- if (child == null)
|
|
|
- {
|
|
|
- Double H=calcH(end.coord,current.coord); // 璁$畻H鍊�
|
|
|
- if(isEndNode(end.id,linkedId))
|
|
|
- {
|
|
|
- child=end;
|
|
|
- child.G=G;
|
|
|
- child.H=H;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- JSONObject neighItem = mapInfo.maps.getJSONObject(linkedId);
|
|
|
- child = new Node(linkedId, neighItem.getDouble("weight"),
|
|
|
- new Coord(neighItem.getDouble("x"), neighItem.getDouble("y"),neighItem.getDouble("z")), null, G, H);
|
|
|
- }
|
|
|
- child.parent=current;
|
|
|
- openList.add(child);
|
|
|
- }
|
|
|
- else if (child.G > G)
|
|
|
- {
|
|
|
- child.G = G;
|
|
|
- child.parent = current;
|
|
|
- openList.add(child);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 浠嶰pen鍒楄〃涓煡鎵剧粨鐐�
|
|
|
- */
|
|
|
- private Node findNodeInOpen(int id)
|
|
|
- {
|
|
|
- if (openList.isEmpty()) return null;
|
|
|
- for (Node node : openList)
|
|
|
- {
|
|
|
- if (node.id == id)
|
|
|
- {
|
|
|
- return node;
|
|
|
- }
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 璁$畻H鐨勪及鍊硷細鈥滄浖鍝堥】鈥濇硶锛屽潗鏍囧垎鍒彇宸�肩浉鍔�
|
|
|
- */
|
|
|
- public Double calcH(Coord end,Coord coord)
|
|
|
- {
|
|
|
- return Math.sqrt(Math.pow(end.x - coord.x,2)+ Math.pow(end.y - coord.y,2)+ Math.pow(end.z - coord.z,2));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 鍒ゆ柇缁撶偣鏄惁鏄渶缁堢粨鐐�
|
|
|
- */
|
|
|
- private boolean isEndNode(int endId,int id)
|
|
|
- {
|
|
|
- return endId == id;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 鍒ゆ柇缁撶偣鑳藉惁鏀惧叆Open鍒楄〃
|
|
|
- */
|
|
|
- private boolean canAddNodeToOpen(MapInfo mapInfo,int id)
|
|
|
- {
|
|
|
- // 鏄惁鍦ㄥ湴鍥句腑
|
|
|
- //if (x < 0 || x >= mapInfo.width || y < 0 || y >= mapInfo.hight) return false;
|
|
|
- // 鍒ゆ柇鏄惁鏄笉鍙�氳繃鐨勭粨鐐�
|
|
|
- //if (mapInfo.maps[y][x] == BAR) return false;
|
|
|
- // 鍒ゆ柇缁撶偣鏄惁瀛樺湪close琛�
|
|
|
- if (isCoordInClose(id)) return false;
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 鍒ゆ柇鍧愭爣鏄惁鍦╟lose琛ㄤ腑
|
|
|
- */
|
|
|
- private boolean isCoordInClose(int id)
|
|
|
- {
|
|
|
- if (closeList.isEmpty()) return false;
|
|
|
- for (Node node : closeList)
|
|
|
- {
|
|
|
- if (node.id == id)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 鍒ゆ柇鍧愭爣鏄惁鍦╟lose琛ㄤ腑
|
|
|
- */
|
|
|
- private boolean isCoordInClose(int x, int y)
|
|
|
- {
|
|
|
- if (closeList.isEmpty()) return false;
|
|
|
- for (Node node : closeList)
|
|
|
- {
|
|
|
- if (node.coord.x == x && node.coord.y == y)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
+public class AStar {
|
|
|
+ public final static int BAR = 1; // 障碍值
|
|
|
+ public final static int PATH = 2; // 路径
|
|
|
+ public final static int DIRECT_VALUE = 10; // 横竖移动代价
|
|
|
+ public final static int OBLIQUE_VALUE = 14; // 斜移动代价
|
|
|
+
|
|
|
+ Queue<Node> openList = new PriorityQueue<Node>(); // 优先队列(升序)
|
|
|
+ List<Node> closeList = new ArrayList<Node>();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 开始算法
|
|
|
+ */
|
|
|
+ public List<Node> start(MapInfo mapInfo) {
|
|
|
+ if (mapInfo == null) return null;
|
|
|
+ // clean
|
|
|
+ openList.clear();
|
|
|
+ closeList.clear();
|
|
|
+ // 开始算法
|
|
|
+ openList.add(mapInfo.start);
|
|
|
+ return moveNodes(mapInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 移动当前结点
|
|
|
+ */
|
|
|
+ private List<Node> moveNodes(MapInfo mapInfo) {
|
|
|
+ while (!openList.isEmpty()) {
|
|
|
+ Node current = openList.poll();
|
|
|
+ closeList.add(current);
|
|
|
+ addNeighborNodeInOpen(mapInfo, current);
|
|
|
+ if (isCoordInClose(mapInfo.end.id)) {
|
|
|
+ List<Node> list = drawPath(mapInfo.maps, mapInfo.end);
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 在二维数组中绘制路径
|
|
|
+ */
|
|
|
+ private List<Node> drawPath(JSONArray maps, Node end) {
|
|
|
+ if (end == null || maps == null) return null;
|
|
|
+ System.out.println("路线" + end.id);
|
|
|
+ List<Node> list = new ArrayList<Node>();
|
|
|
+ while (end != null) {
|
|
|
+ System.out.println("路线" + end.id);
|
|
|
+ list.add(end);
|
|
|
+ Coord c = end.coord;
|
|
|
+ //maps[c.y][c.x] = PATH;
|
|
|
+ end = end.parent;
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加所有邻结点到open表
|
|
|
+ */
|
|
|
+ private void addNeighborNodeInOpen(MapInfo mapInfo, Node current) {
|
|
|
+ int id = current.id;
|
|
|
+ JSONObject item = mapInfo.maps.getJSONObject(id);
|
|
|
+ String[] linkedIds = item.getString("linkedIds").split(",");
|
|
|
+
|
|
|
+ for (int i = 0; i < linkedIds.length; ++i) {
|
|
|
+ int linkedId = Integer.valueOf(linkedIds[i]) - 1;
|
|
|
+ //是否在close表里
|
|
|
+ if (canAddNodeToOpen(mapInfo, linkedId)) {
|
|
|
+ Node end = mapInfo.end;
|
|
|
+ //Coord coord = new Coord(x, y);
|
|
|
+ //Double G = current.G + current.weight; // 计算邻结点的G值
|
|
|
+
|
|
|
+ JSONObject linkedNode = mapInfo.maps.getJSONObject(linkedId);
|
|
|
+ double weight = calcH(current.coord, new Coord(linkedNode.getDouble("x"), linkedNode.getDouble("y"), linkedNode.getDouble("z")));
|
|
|
+ Double G = current.G + weight; // 计算邻结点的G值
|
|
|
+ //Double G = current.G + current.weight; // 计算邻结点的G值
|
|
|
+ Node child = findNodeInOpen(linkedId);
|
|
|
+ if (child == null) {
|
|
|
+ Double H = calcH(end.coord, current.coord); // 璁$畻H鍊�
|
|
|
+ if (isEndNode(end.id, linkedId)) {
|
|
|
+ child = end;
|
|
|
+ child.G = G;
|
|
|
+ child.H = H;
|
|
|
+ } else {
|
|
|
+ JSONObject neighItem = mapInfo.maps.getJSONObject(linkedId);
|
|
|
+ child = new Node(linkedId, neighItem.getDouble("weight"),
|
|
|
+ new Coord(neighItem.getDouble("x"), neighItem.getDouble("y"), neighItem.getDouble("z")), null, G, H);
|
|
|
+ }
|
|
|
+ child.parent = current;
|
|
|
+ openList.add(child);
|
|
|
+ } else if (child.G > G) {
|
|
|
+ child.G = G;
|
|
|
+ child.parent = current;
|
|
|
+ openList.add(child);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从Open列表中查找结点
|
|
|
+ */
|
|
|
+ private Node findNodeInOpen(int id) {
|
|
|
+ if (openList.isEmpty()) return null;
|
|
|
+ for (Node node : openList) {
|
|
|
+ if (node.id == id) {
|
|
|
+ return node;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算H的估值:“曼哈顿”法,坐标分别取差值相加
|
|
|
+ */
|
|
|
+ public Double calcH(Coord end, Coord coord) {
|
|
|
+ return Math.sqrt(Math.pow(end.x - coord.x, 2) + Math.pow(end.y - coord.y, 2) + Math.pow(end.z - coord.z, 2));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断结点是否是最终结点
|
|
|
+ */
|
|
|
+ private boolean isEndNode(int endId, int id) {
|
|
|
+ return endId == id;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 鍒ゆ柇缁撶偣鑳藉惁鏀惧叆Open鍒楄〃
|
|
|
+ */
|
|
|
+ private boolean canAddNodeToOpen(MapInfo mapInfo, int id) {
|
|
|
+
|
|
|
+ // 判断结点是否存在close表
|
|
|
+ if (isCoordInClose(id)) return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 鍒ゆ柇鍧愭爣鏄惁鍦╟lose琛ㄤ腑
|
|
|
+ */
|
|
|
+ private boolean isCoordInClose(int id) {
|
|
|
+ if (closeList.isEmpty()) return false;
|
|
|
+ for (Node node : closeList) {
|
|
|
+ if (node.id == id) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 鍒ゆ柇鍧愭爣鏄惁鍦╟lose琛ㄤ腑
|
|
|
+ */
|
|
|
+ private boolean isCoordInClose(int x, int y) {
|
|
|
+ if (closeList.isEmpty()) return false;
|
|
|
+ for (Node node : closeList) {
|
|
|
+ if (node.coord.x == x && node.coord.y == y) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|