查指定范围内的街道(基于经纬度)
来源:互联网 发布:淘宝电脑版 编辑:程序博客网 时间:2024/05/01 12:07
一、表结构:
CREATE TABLE `district` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `p_id` bigint(20) NOT NULL COMMENT '父ID', `zipcode` varchar(4) DEFAULT NULL COMMENT '城市编码', `adcode` varchar(6) NOT NULL DEFAULT '' COMMENT '区域编码', `name` varchar(64) NOT NULL DEFAULT '' COMMENT '行政区名称', `center` varchar(30) NOT NULL DEFAULT '' COMMENT '城市中心点', `lon` double(9,6) NOT NULL COMMENT '经度', `lat` double(8,6) NOT NULL COMMENT '维度', `geo_code` varchar(12) DEFAULT NULL COMMENT 'geohash编码', `level` varchar(10) NOT NULL DEFAULT '' COMMENT '取值:province省份,city市,district区县,street街道', `area` text COMMENT '街道覆盖域', PRIMARY KEY (`id`), KEY `p_id` (`p_id`) USING BTREE, KEY `zipcode` (`zipcode`) USING BTREE, KEY `adcode` (`adcode`) USING BTREE, KEY `name` (`name`) USING BTREE, KEY `level` (`level`) USING BTREE, KEY `lon` (`lon`) USING BTREE, KEY `lat` (`lat`) USING BTREE, KEY `geo_code` (`geo_code`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=51264 DEFAULT CHARSET=utf8mb4 COMMENT='行政区域';
二、引入jar包
<dependency><groupId>com.spatial4j</groupId><artifactId>spatial4j</artifactId><version>0.5</version></dependency><dependency><groupId>ch.hsr</groupId><artifactId>geohash</artifactId><version>1.3.0</version></dependency>三、Java代码
/** * 方法一,查询指定范围内的所有街道(区间查找) * @return */ public List<District> findNearbyDistrictByRadius(Double lon, Double lat, int radius){ SpatialContext geo = SpatialContext.GEO; Rectangle rectangle = geo.getDistCalc().calcBoxByDistFromPt(geo.makePoint(lon, lat), radius * DistanceUtils.KM_TO_DEG, geo, null); double minX = rectangle.getMinX(); double maxX = rectangle.getMaxX(); double minY = rectangle.getMinY(); double maxY = rectangle.getMaxY(); LOGGER.info(minX + " - " + maxX); // 经度范围 LOGGER.info(minY + " - " + maxY); // 纬度范围 String sql = "select * from district where (lon BETWEEN ? AND ?) AND (lat BETWEEN ? AND ?) and level = 'street' "; List<District> districtList = dao.find(sql, minX, maxX, minY, maxY); LOGGER.info("districtList1={}", JSON.toJSONString(districtList)); //按照距离排序 Collections.sort(districtList, new DistrictComparator(lon, lat)); return districtList; } /** * 方法二,查询指定范围内的所有街道(geohash查找) * @param lon * @param lat * @return */ public List<District> findNearbyDistrictByRadius2(Double lon, Double lat, int geohashLength){ String geoCode = GeohashUtils.encodeLatLon(lat, lon, geohashLength); //1公里 LOGGER.info("geoCode={}", geoCode); StringBuilder sql = new StringBuilder("select * from district where "); GeoHash geoHash = GeoHash.withCharacterPrecision(lat, lon, geohashLength); // 当前 sql.append(" geo_code LIKE CONCAT('" + geoHash.toBase32() + "', '%') "); // N, NE, E, SE, S, SW, W, NW GeoHash[] adjacent = geoHash.getAdjacent(); for (GeoHash hash : adjacent) { sql.append("or geo_code LIKE CONCAT('" + hash.toBase32() +"', '%') "); } LOGGER.info("sql={}", sql.toString()); List<District> districtList = dao.find(sql.toString()); LOGGER.info("districtList2={}", JSON.toJSONString(districtList)); //按照距离排序 Collections.sort(districtList, new DistrictComparator(lon, lat)); return districtList; }
/** * 按照距离远近排序 */ class DistrictComparator implements Comparator<District>{ private SpatialContext geo = SpatialContext.GEO; private Double centerLon; //中心点经度 private Double centerLat; //中心点纬度 public DistrictComparator(Double centerLon, Double centerLat) { this.centerLon = centerLon; this.centerLat = centerLat; } @Override public int compare(District o1, District o2) { double o1Distance = geo.calcDistance(geo.makePoint(o1.getDouble("lon"), o1.getDouble("lat")), geo.makePoint(centerLon, centerLat)) * DistanceUtils.DEG_TO_KM; o1.put("distance", o1Distance); double o2Distance = geo.calcDistance(geo.makePoint(o2.getDouble("lon"), o2.getDouble("lat")), geo.makePoint(centerLon, centerLat)) * DistanceUtils.DEG_TO_KM; o2.put("distance", o2Distance); if(o1Distance < o2Distance){ return -1; }else if(o1Distance > o2Distance){ return 1; }else{ return 0; } } }
阅读全文
0 0
- 查指定范围内的街道(基于经纬度)
- 遥感影像处理之自动筛选指定经纬度范围内的影像
- 取指定范围内的字符串
- 产生指定范围内的随机数
- 输出指定范围内的素数
- 输出指定范围内的阿姆斯特朗数
- 生成指定范围内的随机数
- 产生指定范围内的随机数
- ios 指定范围内的随机数
- 生成指定范围内的随机数
- iOS 获得指定范围内的屏幕图像(截屏)
- js找出指定范围内(m,n)的水仙花数
- 根据当前经纬度 获取一定距离范围内的两个经纬度的点值 经纬度最大最小值
- java实现经纬度坐标是否在范围内的算法
- 获得指定范围内的随机值
- 获得指定范围内的随机值
- 求指定范围内的所有素数
- 输出指定范围内的所有质数
- UGUI之新手引导事件上下分离
- 第一章 java入门
- 微信小程序 Node.js (基础六) Buffer(缓冲区)
- linux IO memory分配及map信息相关命令
- OkHttp深入学习
- 查指定范围内的街道(基于经纬度)
- #if defined和#if !defined(c语言的宏定义)
- 真机有一天突然打印不出log
- MVC分层模式
- jQuery EasyUI基础(一)
- 欢迎使用CSDN-markdown编辑器
- Docker镜像与容器命令
- javascript理解之变量作用域与闭包
- PHP解决网站从http转https后引用的外部资源警告的问题