1引入依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.3</version>
</dependency>
<!-- 计算正方形坐标的开源库 -->
<dependency>
<groupId>org.locationtech.spatial4j</groupId>
<artifactId>spatial4j</artifactId>
<version>0.8</version>
</dependency>
2创建测试表
CREATE TABLE `t_address_axis` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`lng` double DEFAULT NULL,
`lat` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3添加测试数据
Db db = null;
{
if (db == null) {
db = Db.use("test");
}
}
/**
* 坐标轴
*/
@Data
public static class CoordinateAxis {
//经度
private double lng;
//纬度
private double lat;
}
//调用百度接口,根据地址获取经纬度
private CoordinateAxis getAxisByAddress(String address) {
String url = "http://api.map.baidu.com/geocoding/v3/?address=%s&ret_coordtype=wgs84ll&output=json&ak=百度开放平台申请的ak";
String requst = String.format(url, address);
JSONObject jsonObject = JSONUtil.parseObj(HttpUtil.get(requst));
if (jsonObject != null && jsonObject.getInt("status") == 0) {
JSONObject location = jsonObject.getJSONObject("result").getJSONObject("location");
CoordinateAxis axis = location.toBean(CoordinateAxis.class);
return axis;
}
return null;
}
/**
* 添加一些测试地址信息
*/
@Test
public void saveAddressTest() {
ArrayList<String> address = ListUtil.toList("传奇广场","虹桥国际机场", "南京市", "迪士尼乐园", "浦东国际机场", "上海市", "张江高科地铁站");
for (String name : address) {
if (name != null) {
CoordinateAxis axis = getAxisByAddress(name);
try {
Entity entity = Entity.create("t_address_axis")
.set("name", name)
.set("lng", axis.getLng())
.set("lat", axis.getLat());
db.insert(entity);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
4查找
CoordinateAxis axisByAddress = getAxisByAddress("外滩");
List<AddressAxis> addressAxes = nearBySearch(500, axisByAddress.getLng(), axisByAddress.getLat());
Console.log(addressAxes);
for (AddressAxis addressAx : addressAxes) {
double distance = getDistance(axisByAddress.getLng(), axisByAddress.getLat(), addressAx.getLng(), addressAx.getLat());
Console.log("目标地址距离{}{}千米", addressAx.getName(), new BigDecimal(distance).setScale(2, RoundingMode.HALF_UP));
}
/**
* 利用开源库计算外接正方形坐标
*
* @param distance
* @param userLng 当前经度
* @param userLat 当前纬度
* @return
*/
private Rectangle getRectangle(double distance, double userLng, double userLat) {
return spatialContext.getDistCalc()
.calcBoxByDistFromPt(spatialContext.getShapeFactory().pointXY(userLng, userLat),
distance * DistanceUtils.KM_TO_DEG, spatialContext, null);
}
/***
* 球面中,两点间的距离(第三方库方法)
*
* @param longitude 经度1
* @param latitude 纬度1
* @param userLng 经度2
* @param userLat 纬度2
* @return 返回距离,单位km
*/
public double getDistance(Double longitude, Double latitude, double userLng, double userLat) {
return spatialContext.calcDistance(spatialContext.getShapeFactory().pointXY(userLng, userLat),
spatialContext.getShapeFactory().pointXY(longitude, latitude)) * DistanceUtils.DEG_TO_KM;
}
输出的结果:
[AddressTest.AddressAxis(name=传奇广场, lng=121.59243727416298, lat=31.20622095028226), AddressTest.AddressAxis(name=联想大厦, lng=121.5919890197135, lat=31.20893782709614), AddressTest.AddressAxis(name=迪士尼乐园, lng=121.6670271738785, lat=31.148817187073096), AddressTest.AddressAxis(name=浦东国际机场, lng=121.8150900202384, lat=31.15747782869679), AddressTest.AddressAxis(name=上海市, lng=121.48053886017651, lat=31.235929042252014), AddressTest.AddressAxis(name=张江高科地铁站, lng=121.58898490642703, lat=31.212075889269606)]
目标地址距离传奇广场10.85千米
目标地址距离联想大厦10.69千米
目标地址距离迪士尼乐园20.14千米
目标地址距离浦东国际机场32.62千米
目标地址距离上海市1.26千米
目标地址距离张江高科地铁站10.30千米
本文参考附近的人功能实现及原理