声明:
1.该工具类是基本胚子,没有所谓设计模式.但可以完美使用
2.该工具类附带有web监听器,供持久化存储
3.速度超快
代码:
public class LatData implements Serializable,Comparable<LatData>{
/**
*
*/
private static final long serialVersionUID = -2841897755569229115L;
private double lat;
private List<Object> list = new ArrayList<>();
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public List<Object> getList() {
return list;
}
public void setList(List<Object> list) {
this.list = list;
}
public LatData(double lat) {
super();
this.lat = lat;
}
public LatData(double lat,Object obj) {
super();
this.lat = lat;
list.add(obj);
}
public LatData() {
super();
// TODO Auto-generated constructor stub
}
@Override
public int compareTo(LatData o) {
if (this.getLat() < o.getLat()){
return -1;
}
if (this.getLat() > o.getLat()){
return 1;
}
return 0;
}
@Override
public String toString() {
return "LatData [lat=" + lat + ", list=" + list + "]";
}
}
/**
* 经度数据
* @author
*
* 2018年12月28日
*/
public class LonData implements Serializable,Comparable<LonData>{
/**
*
*/
private static final long serialVersionUID = 1361788488326400849L;
private double lon;
private TreeSet<LatData> lats = new TreeSet<>();
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
public TreeSet<LatData> getLats() {
return lats;
}
public void setLats(TreeSet<LatData> lats) {
this.lats = lats;
}
public static LonData create(double lon){
LonData lonObject = new LonData();
lonObject.setLon(lon);
return lonObject;
}
@Override
public String toString() {
return "LonData [lon=" + lon + ", lats=" + lats + "]";
}
@Override
public int compareTo(LonData o) {
if (this.getLon() < o.getLon()){
return -1;
}
if (this.getLon() > o.getLon()){
return 1;
}
return 0;
}
}
/**
* 查询返回数据
* @author
*
* 2018年12月28日
*/
public class Res implements Serializable{
/**
*
*/
private static final long serialVersionUID = -8340410745934084391L;
private double lon;
private double lat;
private double distance;
private Object object;
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public Res(double lon, double lat, Object object) {
super();
this.lon = lon;
this.lat = lat;
this.object = object;
}
public Res() {
super();
}
public double distance(double otherLon, double otherlat){
distance = DistanceUtil.getGreatCircleDistance(lon, lat, otherLon, otherlat);
return distance;
}
@Override
public String toString() {
return "Res [lon=" + lon + ", lat=" + lat + ", distance=" + distance + ", object=" + object + "]";
}
}
/**
* 计算经纬度和距离的工具类
* @author
*
* 2018年12月28日
*/
public class DistanceUtil implements Serializable{
/**
*
*/
private static final long serialVersionUID = 8747777023173566233L;
// 地球半径
public static final double EARTH_RADIUS = 6378137.0; // 单位M
private static double getRad(double d) {
return d * Math.PI / 180.0;
}
/**
* 两坐标(经纬度)之间距离计算 GD/BD地图采用此算法
*
* @param startLng
* 起点坐标经度
* @param startLat
* 起点坐标纬度
* @param endLng
* 终点坐标经度
* @param endLat
* 终点坐标纬度
* @return 起点坐标与终点坐标的距离 单位:m
*/
public static double getGreatCircleDistance(double startLng, double startLat, double endLng, double endLat) {
double radLat1 = getRad(startLat);
double radLat2 = getRad(endLat);
double dy = radLat1 - radLat2; // a
double dx = getRad(startLng) - getRad(endLng); // b
double s = 2 * Math.asin(Math.sqrt(
Math.pow(Math.sin(dy / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(dx / 2), 2)));
s = s * EARTH_RADIUS;
s = Math.round(s * 10000) / 10000.0;
return s;
}
public static void main(String[] args) {
// 东经106.486654度 北纬23.490295度 向东移动4000米 向北移动3000米
double lng = getMoveLng(23.490295, 4000) + 106.486654;
double lat = getMoveLat(3000) + 23.490295;
System.out.println(lat);
System.out.println(lng);
System.out.println("移动后两点距离(米):" + getGreatCircleDistance(106.486654, 23.490295, lng, lat));
}
/**
* 获取纬度移动latMovement米,纬度移动的度数
*
* @param latMovement
* 单位:米
* @return 纬度移动的度数
*/
public static double getMoveLat(double latMovement) {
return (180 / (Math.PI * EARTH_RADIUS)) * latMovement;
}
/**
* 获取经度移动lngMovement米,经度移动的度数
*
* @param lat
* 纬度
* @param lngMovement
* 单位:米
* @return 经度移动的度数
*/
public static double getMoveLng(double lat, double lngMovement) {
return (180 / (Math.PI * EARTH_RADIUS * Math.cos(Math.toRadians(lat)))) * lngMovement;
}
}
/**
* 供GEO数据持久化的监听器
*
* @author
*
* 2018年12月28日
*/
public class GeoLisener implements ServletContextListener {
private static String fileName = "";
@Override
public void contextInitialized(ServletContextEvent sce) {
try (FileInputStream fis = new FileInputStream(fileName);
ObjectInputStream ois = new ObjectInputStream(fis);) {
Object object = ois.readObject();
if (object != null) {
GeoUtil.lonSet = (TreeSet<LonData>) object;
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
try(FileOutputStream fos = new FileOutputStream(fileName);
ObjectOutputStream oos = new ObjectOutputStream(fos);){
oos.writeObject(GeoUtil.lonSet);
}catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 对外开放的使用类
* @author
*
* 2018年12月28日
*/
public class GeoUtil{
public static void main(String[] args) {
double lon = 113.7704658508;
double lat = 34.7189693687;
for (double i = 0; i < 0.001; i = i + 0.000001) {
put(lon+i, lat+i,"呵呵");
}
put(lon, lat,"呵呵111");
long currentTimeMillis = System.currentTimeMillis();
System.out.println(search(lon, lat,10));
System.out.println(System.currentTimeMillis()-currentTimeMillis);
}
public static TreeSet<LonData> lonSet = new TreeSet<LonData>();
/**
* 查找某点多少米范围的所有点,是正方形范围
* @param lon 当前精度
* @param lat 当前纬度
* @param distance 单位米,范围
* @return
*/
public static TreeSet<Res> search(double lon,double lat,double distance){
TreeSet<Res> resset = new TreeSet<Res>(new Comparator<Res>() {
@Override
public int compare(Res o1, Res o2) {
if (o1.distance(lon, lat) < o2.distance(lon, lat)){
return -1;
}
return 1;
}
});
NavigableSet<LonData> set = lonSet.subSet(LonData.create(lon-DistanceUtil.getMoveLng(lat, distance)), true, LonData.create(lon+DistanceUtil.getMoveLng(lat, distance)), true);
for (LonData lonObject : set) {
NavigableSet<LatData> subSet = lonObject.getLats().subSet(new LatData(lat-DistanceUtil.getMoveLat(distance)), true, new LatData(lat+DistanceUtil.getMoveLat(distance)), true);
for (LatData latData : subSet) {
resset.add(new Res(lonObject.getLon(), latData.getLat(), latData.getList()));
}
}
return resset;
}
public static void put(double lon,double lat,Object data){
LonData create = LonData.create(lon);
if (lonSet.contains(create)){
//如果存在
LonData ceiling = lonSet.ceiling(create);
TreeSet<LatData> lats = ceiling.getLats();
if (lats.contains(new LatData(lat))){
LatData latData = lats.ceiling(new LatData(lat));
latData.getList().add(data);
}else {
lats.add(new LatData(lat,data));
}
}else{
//如果不存在
create.getLats().add(new LatData(lat,data));
lonSet.add(create);
}
}
public static void remove(double lon,double lat){
LonData create = LonData.create(lon);
if (lonSet.contains(create)){
//如果存在
lonSet.ceiling(create).getLats().remove(new LatData(lat));
}
}
}