android百度地图开发--自定义最短路径搜索图层
原文:http://blog.****.net/wb7931021/article/details/38958957
由于需要,需要在百度地图的基础上实现小范围(例如校园,景区等地)内的详细最短路径导航,百度地图无法实现,因此通过SQLite数据库自行添加地点坐标信息,然后通过Dijkstra算法实现了两地点间的最短路径搜索。
直接上代码:
首先是定义的一个节点雷:Side.java
用于存放以及获取节点信息
[java] view plain copy
- package com.xjdx.suanfa;
- public class Side {
- private int preNode; //前驱节点
- private int nextNode;//后继节点
- private int weight;//权重
- public Side(int preNode,int nextNode,int weight){
- this.preNode = preNode;
- this.nextNode = nextNode;
- this.weight = weight;
- }
- public int getPreNode(){
- return this.preNode;
- }
- public void setPreNode(int preNode){
- this.preNode = preNode;
- }
- public int getNextNode(){
- return this.nextNode;
- }
- public void setNextNode(int nextNode){
- this.nextNode = nextNode;
- }
- public int getWeight(){
- return this.weight;
- }
- public void setWeight(int weight){
- this.weight = weight;
- }
- }
然后是一个用于存储以及获取最短路径类:MinShortPath.java
[java] view plain copy
- package com.xjdx.suanfa;
- import java.util.ArrayList;
- public class MinShortPath {
- private ArrayList<Integer> nodeList;//最短路径集
- private int weight;//最短路径
- public MinShortPath(int node){
- nodeList = new ArrayList<Integer>();
- nodeList.add(node);
- weight = -1;
- }
- public ArrayList<Integer> getNodeList(){
- return nodeList;
- }
- public void setNodeList(ArrayList<Integer> nodeList){
- this.nodeList = nodeList;
- }
- public void addNode(int node){
- if(nodeList == null){
- nodeList = new ArrayList<Integer>();
- }
- nodeList.add(0,node);
- }
- public int getLastNode(){
- int size = nodeList.size();
- return nodeList.get(size-1);
- }
- public int getWeight(){
- return weight;
- }
- public void setWeight(int weight){
- this.weight = weight;
- }
- public void outputPath(){
- outputPath(-1);
- }
- public void outputPath(int srcNode){
- String result = "[";
- if(srcNode != -1){
- nodeList.add(srcNode);
- }
- for(int i=0;i<nodeList.size();i++){
- result += "" + nodeList.get(i);
- if(i<nodeList.size()-1){
- result += ",";
- }
- }
- result +="]:"+weight;
- System.out.println(result);
- }
- public void addWeight(int w){
- if(weight == -1){
- weight = w;
- }
- else{
- weight += w;
- }
- }
- }
最后是主类linjiejuzhen.java
通过邻接矩阵实现
[java] view plain copy
- package com.xjdx.xxxy;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import com.xjdx.suanfa.MinShortPath;
- import com.xjdx.suanfa.Side;
- import android.app.Activity;
- import android.database.Cursor;
- import android.database.SQLException;
- import android.database.sqlite.SQLiteDatabase;
- import android.os.Bundle;
- import android.widget.TextView;
- import android.widget.Toast;
- public class linjiejuzhen extends Activity {
- TextView textView = null;
- int col, row = 0;
- private static final String DB_PATH = "/data/data/com.xjdx.xxxy/databases/";
- private static final String DB_NAME = "PLACE";
- static ArrayList<Side> map = null;
- static ArrayList<Integer> redAgg = null;
- static ArrayList<Integer> blueAgg = null;
- static Side[] parents = null;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- super.setContentView(R.layout.linjiejuzhen);
- if ((new File(DB_PATH + DB_NAME)).exists() == false) { // 如 SQLite
- // 数据库文件不存在,再检查一下 database 目录是否存在
- File f = new File(DB_PATH); // 如
- // database 目录不存在,新建该目录
- if (!f.exists()) {
- System.out.println("******************");
- f.mkdir();
- }
- try {
- // 得到 assets 目录下我们实现准备好的 SQLite 数据库作为输入流
- InputStream is = getBaseContext().getAssets().open(DB_NAME);
- // 输出流
- OutputStream os = new FileOutputStream(DB_PATH + DB_NAME);
- // 文件写入
- byte[] buffer = new byte[1024];
- int length;
- while ((length = is.read(buffer)) > 0) {
- os.write(buffer, 0, length);
- }
- // 关闭文件流
- os.flush();
- os.close();
- is.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
- try {
- list = getData();
- getDistinctData();
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- this.textView = (TextView) super.findViewById(R.id.textView1);
- // this.textView.setText(list.get(0).get("VALUE").toString());
- this.textView.setText("节点个数:" + col);
- int[][] array;
- array = new int[col][col];
- for (int x = 0; x < col; x++) {
- for (int y = 0; y < col; y++) {
- for (int k = 0; k < list.size(); k++) {
- if ((x + 1 == (Integer.parseInt(list.get(k)
- .get("PRENODE_ID").toString())))
- && (y + 1 == (Integer.parseInt(list.get(k)
- .get("NEXTNODE_ID").toString())))) {
- array[x][y] = Integer.parseInt(list.get(k).get("VALUE")
- .toString());
- break;
- }
- }
- }
- }
- for (int i = 0; i < col; i++) {
- for (int j = 0; j < col; j++) {
- if (array[i][j] == 0) {
- array[i][j] = -1;
- }
- }
- }
- for (int i = 0; i < col; i++) {
- for (int j = 0; j < col; j++) {
- System.out.println(array[i][j]);
- }
- }
- int[] nodes = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23 };
- map = new ArrayList<Side>();
- for (int i = 0; i < list.size(); i++) {
- map.add(new Side((Integer.parseInt(list.get(i).get("PRENODE_ID")
- .toString())), (Integer.parseInt(list.get(i)
- .get("NEXTNODE_ID").toString())), (Integer.parseInt(list
- .get(i).get("VALUE").toString()))));
- }
- // 初始化已知最短路径的顶点集,即红点集,只加入顶点0
- redAgg = new ArrayList<Integer>();
- redAgg.add(nodes[0]);
- // 初始化未知最短路径的顶点集,即蓝点集
- blueAgg = new ArrayList<Integer>();
- for (int i = 1; i < nodes.length; i++) {
- blueAgg.add(nodes[i]);
- }
- // 初始化每个顶点在最短路径中的父节点,及它们之间的权重,权重-1表示不连通
- parents = new Side[nodes.length];
- parents[0] = new Side(-1, nodes[0], 0);
- for (int i = 0; i < blueAgg.size(); i++) {
- int n = blueAgg.get(i);
- parents[i + 1] = new Side(nodes[0], n, getWeight(nodes[0], n));
- }
- // 从蓝点集中找出权重最小的那个顶点,并把它加入到红点集中
- while (blueAgg.size() > 0) {
- MinShortPath msp = getMinSideNode();
- if (msp.getWeight() == -1) {
- msp.outputPath(nodes[0]);
- } else {
- msp.outputPath();
- }
- int node = msp.getLastNode();
- redAgg.add(node);
- // 如果因为加入了新的顶点,而导致蓝点集中的顶点的最短路径减小,则要重新设置
- setWeight(node);
- }
- }
- /*
- * 得到两点之间的权重
- */
- public int getWeight(int preNode, int nextNode) {
- if (map != null) {
- for (Side s : map) {
- if (s.getPreNode() == preNode && s.getNextNode() == nextNode)
- return s.getWeight();
- }
- }
- return -1;
- }
- /*
- * 从蓝点集合中找出路径最小的节点
- */
- public MinShortPath getMinSideNode() {
- MinShortPath minMsp = null;
- if (blueAgg.size() > 0) {
- int index = 0;
- for (int j = 0; j < blueAgg.size(); j++) {
- MinShortPath msp = getMinPath(blueAgg.get(j));
- if (minMsp == null || msp.getWeight() != -1
- && msp.getWeight() < minMsp.getWeight()) {
- minMsp = msp;
- index = j;
- }
- }
- blueAgg.remove(index);
- }
- return minMsp;
- }
- /*
- * 得到某一节点的最短路径(实际有多条,现在只考虑一条)
- */
- public MinShortPath getMinPath(int node) {
- MinShortPath msp = new MinShortPath(node);
- if (parents != null && redAgg != null) {
- for (int i = 0; i < redAgg.size(); i++) {
- MinShortPath tempMsp = new MinShortPath(node);
- int parent = redAgg.get(i);
- int curNode = node;
- while (parent > -1) {
- int weight = getWeight(parent, curNode);
- if (weight > -1) {
- tempMsp.addNode(parent);
- tempMsp.addWeight(weight);
- curNode = parent;
- parent = getParent(parents, parent);
- } else {
- break;
- }
- }
- if (msp.getWeight() == -1 || tempMsp.getWeight() != -1
- && msp.getWeight() > tempMsp.getWeight()) {
- msp = tempMsp;
- }
- }
- }
- return msp;
- }
- /*
- * 得到一个节点的父节点
- */
- public int getParent(Side[] parents, int node) {
- if (parents != null) {
- for (Side nd : parents) {
- if (nd.getNextNode() == node) {
- return nd.getPreNode();
- }
- }
- }
- return -1;
- }
- /*
- * 重新设置蓝点集中剩余节点的最短路径长度
- */
- public void setWeight(int preNode) {
- if (map != null && parents != null && blueAgg != null) {
- for (int node : blueAgg) {
- MinShortPath msp = getMinPath(node);
- int w1 = msp.getWeight();
- if (w1 == -1) {
- continue;
- }
- for (Side n : parents) {
- if (n.getNextNode() == node) {
- if (n.getWeight() == -1 || n.getWeight() > w1) {
- n.setWeight(w1);
- n.setPreNode(preNode);
- break;
- }
- }
- }
- }
- }
- }
- public List<Map<String, Object>> getData() throws IOException,
- SQLException, ClassNotFoundException {
- SQLiteDatabase databaseSpiPlace = SQLiteDatabase.openOrCreateDatabase(
- DB_PATH + DB_NAME, null);
- Cursor cursor = databaseSpiPlace.rawQuery("select * from ROUTE_PLAN",
- null);
- List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
- // ResultSetMetaData md = cursor.get.getMetaData();
- int columnCount = cursor.getColumnCount();
- while (cursor.moveToNext()) {
- Map<String, Object> rowData = new HashMap<String, Object>();
- for (int i = 0; i < columnCount; i++) {
- rowData.put(cursor.getColumnName(i), cursor.getInt(i));
- }
- list.add(rowData);
- }
- cursor.close();
- return list;
- }
- public void getDistinctData() {
- SQLiteDatabase databaseSpiPlace = SQLiteDatabase.openOrCreateDatabase(
- DB_PATH + DB_NAME, null);
- Cursor cursor = databaseSpiPlace.rawQuery(
- "select distinct PRENODE_ID from ROUTE_PLAN", null);
- List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
- int i = 0;
- while (cursor.moveToNext()) {
- i++;
- }
- cursor.close();
- col = i;
- }
- }
结果预览:
图一为通过百度地图搜索而显示的最短路径结果:
图一
图二为自定义最短路径搜索结果:
图二
在这里将代码分享出来,供大家参考学习~~~初次发帖,有不足之处望大家指正,相互学习~~