geohash用一个字符串表示经度和纬度两个坐标。它的缺点是:位于格子边界两侧的两点,虽然十分接近,但编码会完全不同。
我想出了另一种方法,本方法是得到一个点邻近区域内的点集合:
思路:第一步(生成):将一个长方形区域分成许多正方形格子,区域内的点都属于某个格子,有点的格子新建一个list,将格子中的点放进去。
第二步(查找):进来一个坐标,先计算它属于哪个格子,将周围9个格子(包括所在格子)中的list合并起来,就是邻近点集合。
package custom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SuperMap
{
static Map<Double,ArrayList<Integer>> map=new HashMap<Double, ArrayList<Integer>>(); //格子中的list
static int cnt=0; //点编号
static final ArrayList<Integer> nullList = new ArrayList<Integer>();
static final double begin_lon=119;
static final double begin_lat=27;
static final double end_lon=122;
static final double end_lat=29; /*长方形区域*/
static final double dist=0.007; //邻近区域半径
static int lat_Num=(int)((end_lat-begin_lat)/dist+1);
//邻近区域周围格子
static int[][] offset={
{0,0},{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1}
};
/**
* 将所有点放到格子中
* @param lon 经度
* @param lat 纬度
*/
public static void addToMap(double lon,double lat)
{
double idx=getCellNo(lon,lat);
if(!map.containsKey(idx)) //有点的格子才新建list
{
map.put(idx, new ArrayList<Integer>());
}
map.get(idx).add(cnt);
cnt++;
}
/**
* 得到周围格子中的点编号
* @param lon 经度
* @param lat 纬度
* @return 邻近表
*/
public static List<Integer> NearTable(double lon,double lat)
{
ArrayList<Integer> res=new ArrayList<Integer>();
for(int i=0;i<9;i++)
{
res.addAll(getList(lon+offset[i][0]*dist,lat+offset[i][1]*dist));
}
return res;
}
/**
* 得到某个格子的点编号
* @param d 经度
* @param e
* @return
*/
private static ArrayList<Integer> getList(double lon, double lat)
{
double idx=getCellNo(lon, lat);
if(map.containsKey(idx)) //格子中有没有list
{
return map.get(idx);
}
return nullList;//格子没有点,返回空list
}
/**
* 得到隐式二维数组格子编号
* 将纬度变成小数
* @param lon
* @param lat
* @return
*/
private static double getCellNo(double lon, double lat)
{
int i=(int)((lon-begin_lon)/dist);
int j=(int)((lat-begin_lat)/dist);
return (double)j/lat_Num+i;
}
}