赞
踩
WGS84坐标系 GCJ02坐标系 BD09坐标系的各种转换
WGS84坐标系 GCJ02坐标系 BD09坐标系的各种转换 Google S2 经纬度 转 CellId 经纬度 转 cellToken CellId 转 经纬度 判断当前cellId的level * 获取任意形状内所有S2块 * 可以用于区域内目标检索,根据cellid建立索引,查询区域内cellid in (list)的区域 S2计算点距离 计算地球上某个点是否在矩形区域内 计算点s2是否在圆中心为s1半径为capHeight的圆形区域内 判断点是否在任意形状内 计算两个区域是否有交集 求不同等级S2块包含的S2子块
Java实现Google的S2算法工具类GoogleS2GoogleS2GoogleS2-Java文档类资源-CSDN下载
level (等级) | min area(最小面积) | max area(最大面积) | average area(平均面积) | units(单位) | Random cell 1 (UK)() min edge length(随机单元1 (UK)最小边长度) | Random cell 1 (UK) max edge length(随机单元格1 (UK)最大边长度) | Random cell 2 (US) min edge length(随机单元2 (US)最小边长度) | Random cell 2 (US) max edge length(随机单元格2(美国)最大边长度) | Number of cells(单元格数) |
0 | 85011012.19 | 85011012.19 | 85011012.19 | km2 | 7842 km | 7842 km | 7842 km | 7842 km | 6 |
1 | 21252753.05 | 21252753.05 | 21252753.05 | km2 | 3921 km | 5004 km | 3921 km | 5004 km | 24 |
2 | 4919708.23 | 6026521.16 | 5313188.26 | km2 | 1825 km | 2489 km | 1825 km | 2489 km | 96 |
3 | 1055377.48 | 1646455.5 | 1328297.07 | km2 | 840 km | 1167 km | 1130 km | 1310 km | 384 |
4 | 231564.06 | 413918.15 | 332074.27 | km2 | 432 km | 609 km | 579 km | 636 km | 1536 |
5 | 53798.67 | 104297.91 | 83018.57 | km2 | 210 km | 298 km | 287 km | 315 km | 6K |
6 | 12948.81 | 26113.3 | 20754.64 | km2 | 108 km | 151 km | 143 km | 156 km | 24K |
7 | 3175.44 | 6529.09 | 5188.66 | km2 | 54 km | 76 km | 72 km | 78 km | 98K |
8 | 786.2 | 1632.45 | 1297.17 | km2 | 27 km | 38 km | 36 km | 39 km | 393K |
9 | 195.59 | 408.12 | 324.29 | km2 | 14 km | 19 km | 18 km | 20 km | 1573K |
10 | 48.78 | 102.03 | 81.07 | km2 | 7 km | 9 km | 9 km | 10 km | 6M |
11 | 12.18 | 25.51 | 20.27 | km2 | 3 km | 5 km | 4 km | 5 km | 25M |
12 | 3.04 | 6.38 | 5.07 | km2 | 1699 m | 2 km | 2 km | 2 km | 100M |
13 | 0.76 | 1.59 | 1.27 | km2 | 850 m | 1185 m | 1123 m | 1225 m | 402M |
14 | 0.19 | 0.4 | 0.32 | km2 | 425 m | 593 m | 562 m | 613 m | 1610M |
15 | 47520.3 | 99638.93 | 79172.67 | m2 | 212 m | 296 m | 281 m | 306 m | 6B |
16 | 11880.08 | 24909.73 | 19793.17 | m2 | 106 m | 148 m | 140 m | 153 m | 25B |
17 | 2970.02 | 6227.43 | 4948.29 | m2 | 53 m | 74 m | 70 m | 77 m | 103B |
18 | 742.5 | 1556.86 | 1237.07 | m2 | 27 m | 37 m | 35 m | 38 m | 412B |
19 | 185.63 | 389.21 | 309.27 | m2 | 13 m | 19 m | 18 m | 19 m | 1649B |
20 | 46.41 | 97.3 | 77.32 | m2 | 7 m | 9 m | 9 m | 10 m | 7T |
21 | 11.6 | 24.33 | 19.33 | m2 | 3 m | 5 m | 4 m | 5 m | 26T |
22 | 2.9 | 6.08 | 4.83 | m2 | 166 cm | 2 m | 2 m | 2 m | 105T |
23 | 0.73 | 1.52 | 1.21 | m2 | 83 cm | 116 cm | 110 cm | 120 cm | 422T |
24 | 0.18 | 0.38 | 0.3 | m2 | 41 cm | 58 cm | 55 cm | 60 cm | 1689T |
25 | 453.19 | 950.23 | 755.05 | cm2 | 21 cm | 29 cm | 27 cm | 30 cm | 7.00E+15 |
26 | 113.3 | 237.56 | 188.76 | cm2 | 10 cm | 14 cm | 14 cm | 15 cm | 2.70E+16 |
27 | 28.32 | 59.39 | 47.19 | cm2 | 5 cm | 7 cm | 7 cm | 7 cm | 1.08E+17 |
28 | 7.08 | 14.85 | 11.8 | cm2 | 2 cm | 4 cm | 3 cm | 4 cm | 4.32E+17 |
29 | 1.77 | 3.71 | 2.95 | cm2 | 12 mm | 18 mm | 17 mm | 18 mm | 1.73E+18 |
30 | 0.44 | 0.93 | 0.74 | cm2 | 6 mm | 9 mm | 8 mm | 9 mm | 7.00E+18 |
- package com.zz.meridian.utils.googleS2;
-
- /**
- * @author tiger
- * GPS位置信息接下来说下坐标系。目前主要有三种地理坐标系,如下:
- * 1、WGS84坐标系:即地球坐标系(World Geodetic System),国际上通用的坐标系。
- * 设备包含的GPS芯片或者北斗芯片获取的经纬度一般都是为WGS84地理坐标系,目前谷歌地图采用的是WGS84坐标系(中国范围除外)。
- * 2、GCJ02坐标系:即火星坐标系,国测局坐标系。是由中国国家测绘局制定。由WGS84坐标系经加密后的坐标系。谷歌中国和搜搜中国采用的GCJ02地理坐标系。
- * 3、BD09坐标系:百度坐标系,GCJ02坐标系经加密后的坐标系。
- * 4、其他(搜狗坐标系,图吧坐标系等)。大概率也是再GCJ02坐标系基础上加密生成的
- */
- public class PointS2Transform {
-
- public static double x_PI = 3.14159265358979324 * 3000.0 / 180.0;
- public static double PI = 3.1415926535897932384626;
- public static double a = 6378245.0;
- public static double ee = 0.00669342162296594323;
-
- /**
- * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
- * 即 百度 转 谷歌、高德
- *
- * @param bd_lon
- * @param bd_lat
- * @returns {*[]}
- */
- public static PointS2 bd09togcj02(double bd_lon, double bd_lat) {
- double x = bd_lon - 0.0065;
- double y = bd_lat - 0.006;
- double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_PI);
- double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_PI);
- double gg_lng = z * Math.cos(theta);
- double gg_lat = z * Math.sin(theta);
- PointS2 point = new PointS2(gg_lat, gg_lng);
- return point;
- }
-
- /**
- * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
- * 即谷歌、高德 转 百度
- *
- * @param lng
- * @param lat
- * @returns {*[]}
- */
- public static PointS2 gcj02tobd09(double lng, double lat) {
- double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
- double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
- double bd_lng = z * Math.cos(theta) + 0.0065;
- double bd_lat = z * Math.sin(theta) + 0.006;
- PointS2 point = new PointS2(bd_lat, bd_lng);
- return point;
- }
-
- ;
-
- /**
- * WGS84转GCj02
- *
- * @param lng
- * @param lat
- * @returns {*[]}
- */
- public static PointS2 wgs84togcj02(double lng, double lat) {
- double dlat = transformlat(lng - 105.0, lat - 35.0);
- double dlng = transformlng(lng - 105.0, lat - 35.0);
- double radlat = lat / 180.0 * PI;
- double magic = Math.sin(radlat);
- magic = 1 - ee * magic * magic;
- double sqrtmagic = Math.sqrt(magic);
- dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
- dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
- double mglat = lat + dlat;
- double mglng = lng + dlng;
- PointS2 point = new PointS2(mglat, mglng);
- return point;
- }
- /**
- * 84 to ⽕星坐标系 (GCJ-02) 是否离开了中国版
- *
- * @param lat
- * @param lon
- */
- public static PointS2 gps84_To_Gcj02(double lat, double lon) {
- if (outOfChina(lat, lon)) {
- return null;
- }
- double dLat = transformLat(lon - 105.0, lat - 35.0);
- double dLon = transformLon(lon - 105.0, lat - 35.0);
- double radLat = lat / 180.0 * PI;
- double magic = Math.sin(radLat);
- magic = 1 - ee * magic * magic;
- double sqrtMagic = Math.sqrt(magic);
- dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
- dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
- double mgLat = lat + dLat;
- double mgLon = lon + dLon;
- return new PointS2(mgLat, mgLon);
- }
-
- /**
- * ⽕星坐标系 GCJ02 转换为 WGS84
- *
- * @param lng
- * @param lat
- * @returns {*[]}
- */
- public static PointS2 gcj02towgs84(double lng, double lat) {
- double dlat = transformlat(lng - 105.0, lat - 35.0);
- double dlng = transformlng(lng - 105.0, lat - 35.0);
- double radlat = lat / 180.0 * PI;
- double magic = Math.sin(radlat);
- magic = 1 - ee * magic * magic;
- double sqrtmagic = Math.sqrt(magic);
- dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
- dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
- double mglat = lat + dlat;
- double mglng = lng + dlng;
- PointS2 point = new PointS2(mglat, mglng);
- return point;
- }
-
-
- /**
- * ⽕星坐标系 GCJ02 转换为 WGS84 是否离开了中国版
- * @param lon * @param lat * @return
- */
- public static PointS2 gcj_To_Gps84(double lat, double lon) {
- PointS2 gps = transform(lat, lon);
- double lontitude = lon * 2 - gps.getLng();
- double latitude = lat * 2 - gps.getLat();
- return new PointS2(latitude, lontitude);
- }
-
- /**
- * 将 GCJ-02 坐标转换成 BD-09 坐标
- * @param gg_lat
- * @param gg_lon
- */
- public static PointS2 gcj02_To_Bd09(double gg_lat, double gg_lon) {
- double x = gg_lon, y = gg_lat;
- double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * PI);
- double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * PI);
- double bd_lon = z * Math.cos(theta) + 0.0065;
- double bd_lat = z * Math.sin(theta) + 0.006;
- return new PointS2(bd_lat, bd_lon);
- }
-
- /**
- * 将 BD-09 坐标转换成GCJ-02 坐标
- * bd_lat * @param bd_lon * @return
- */
- public static PointS2 bd09_To_Gcj02(double bd_lat, double bd_lon) {
- double x = bd_lon - 0.0065;
- double y = bd_lat - 0.006;
- double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * PI);
- double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * PI);
- double gg_lon = z * Math.cos(theta);
- double gg_lat = z * Math.sin(theta);
- return new PointS2(gg_lat, gg_lon);
- }
-
- /**
- * (BD-09)-->84
- *
- * @param bd_lat
- * @param bd_lon
- * @return
- */
- public static PointS2 bd09_To_Gps84(double bd_lat, double bd_lon) {
- PointS2 gcj02 = bd09_To_Gcj02(bd_lat, bd_lon);
- PointS2 map84 = gcj_To_Gps84(gcj02.getLat(),
- gcj02.getLng());
- return map84;
- }
-
- /**
- * is or not outOfChina
- * 是否离开了中国
- * @param lat
- * @param lon
- * @return
- */
- public static boolean outOfChina(double lat, double lon) {
- if (lon < 72.004 || lon > 137.8347)
- return true;
- if (lat < 0.8293 || lat > 55.8271)
- return true;
- return false;
- }
-
- private static double transformlat(double lng, double lat) {
- double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
- ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
- ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
- ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
- return ret;
- }
-
- private static double transformlng(double lng, double lat) {
- double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
- ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
- ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
- ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
- return ret;
- }
-
- public static PointS2 transform(double lat, double lon) {
- if (outOfChina(lat, lon)) {
- return new PointS2(lat, lon);
- }
- double dLat = transformLat(lon - 105.0, lat - 35.0);
- double dLon = transformLon(lon - 105.0, lat - 35.0);
- double radLat = lat / 180.0 * PI;
- double magic = Math.sin(radLat);
- magic = 1 - ee * magic * magic;
- double sqrtMagic = Math.sqrt(magic);
- dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
- dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
- double mgLat = lat + dLat;
- double mgLon = lon + dLon;
- return new PointS2(mgLat, mgLon);
- }
-
- public static double transformLat(double x, double y) {
- double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
- + 0.2 * Math.sqrt(Math.abs(x));
- ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
- ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
- ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
- return ret;
- }
-
- public static double transformLon(double x, double y) {
- double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
- * Math.sqrt(Math.abs(x));
- ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
- ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
- ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0
- * PI)) * 2.0 / 3.0;
- return ret;
- }
- }
- package com.zz.meridian.utils.googleS2;
-
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
-
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- public class PointS2 {
- double lat;
- double lng;
- }
- package com.zz.meridian.utils.googleS2;
-
- import com.google.common.collect.Lists;
- import com.google.common.geometry.*;
-
- import java.util.ArrayList;
- import java.util.List;
- import java.util.stream.Collectors;
-
- /**
- * @author tiger
- * 必须使用-S2使用的是WGS84坐标
- * 如果你获得的是WGS84坐标-百度或者高德的地理坐标,请将其转换为GPS-WGS84坐标
- * 由于google s2默认使用gps坐标系,在国内无法使用,需要转换为国内的gcj坐标或者bd09坐标
- * 主要包含3类方法:
- * getS2RegionByXXX
- * 获取给定经纬度坐标对应的S2Region,该region可用于获取cellId,或用于判断包含关系
- * getCellIdList
- * 获取给定region的cellId,并通过childrenCellId方法控制其严格遵守minLevel
- * contains
- * 对于指定S2Region,判断经纬度或CellToken是否在其范围内
- */
- /*
- 包
- <dependency>
- <groupId>io.sgr</groupId>
- <artifactId>s2-geometry-library-java</artifactId>
- <version>1.0.0</version>
- </dependency>
-
- */
- public class GoogleS2 {
-
- /**
- * 经纬度 转 S2CellId
- *
- * @param lat 维度
- * @param lng 经度
- * @param currentLevel level选择级别
- */
- public static S2CellId latLonToS2LatLng(double lat, double lng, int currentLevel) {
- S2LatLng s2LatLng = S2LatLng.fromDegrees(lat, lng);
- S2CellId cellId = S2CellId.fromLatLng(s2LatLng).parent(currentLevel);
- return cellId;
- }
-
- /**
- * 经纬度 转 CellId
- *
- * @param lat 维度
- * @param lng 经度
- * @param currentLevel level选择级别
- */
- public static Long latLonToCellId(double lat, double lng, int currentLevel) {
- S2LatLng s2LatLng = S2LatLng.fromDegrees(lat, lng);
- S2CellId cellId = S2CellId.fromLatLng(s2LatLng).parent(currentLevel);
- return cellId.id();
- }
-
- /**
- * 经纬度 转 cellToken
- *
- * @param lat 维度
- * @param lng 经度
- * @param currentLevel level选择级别
- */
- public static String latLonToCellToken(double lat, double lng, int currentLevel) {
- try {
- S2LatLng s2LatLng = S2LatLng.fromDegrees(lat, lng);
- S2CellId cellId = S2CellId.fromLatLng(s2LatLng).parent(currentLevel);
- return cellId.toToken();
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
-
- /**
- * CellId 转 经纬度
- *
- * @param cellId 是 S2CellId.id();
- * @return
- */
- public static PointS2 cellIdToLatLon(Long cellId) {
- S2LatLng s2LatLng = new S2CellId(cellId).toLatLng();
- double lat = s2LatLng.latDegrees();
- double lng = s2LatLng.lngDegrees();
- return new PointS2(lat, lng);
- }
-
- /**
- * cellToken 转 经纬度
- *
- * @param cellToken
- * @return
- */
- public static PointS2 cellTokenToLatLon(String cellToken) {
- S2LatLng latLng = new S2LatLng(S2CellId.fromToken(cellToken).toPoint());
- return new PointS2(latLng.latDegrees(), latLng.lngDegrees());
- }
-
- /**
- * 判断region是否包含指定经纬度坐标
- *
- * @param region
- * @param lat
- * @param lon
- * @return
- */
- public static boolean contains(S2Region region, double lat, double lon) {
- S2LatLng s2LatLng = S2LatLng.fromDegrees(lat, lon);
- try {
- boolean contains = region.contains(new S2Cell(s2LatLng));
- return contains;
- } catch (NullPointerException e) {
- e.printStackTrace();
- return false;
- }
- }
-
- /**
- * 判断当前cellId的level
- *
- * @param cellId
- * @return
- */
- public static int getLevel(long cellId) {
- int n = 0;
- while (cellId % 2 == 0) {
- cellId = cellId / 2;
- n++;
- }
- return 30 - n / 2;
- }
-
- /**
- * 获取任意形状内所有S2块
- * 可以用于区域内目标检索,根据cellid建立索引,查询区域内cellid in (list)的区域
- *
- * @param vertices 形成多边形的点集合
- * @return
- */
- private static List<Long> vertices(List<PointS2> vertices) {
- //因为x一般表示经度 y轴表示纬度所以这儿需要参数需要对应一下
- List<S2Point> collect = vertices.stream().map(e -> S2LatLng.fromDegrees(e.getLng(), e.getLat()).toPoint()).collect(Collectors.toList());
- S2Loop s2Loop = new S2Loop(collect);
- S2Polygon cap = new S2Polygon(s2Loop); //创建多边形
- //S2Region cap 任意区域
- S2RegionCoverer coverer = new S2RegionCoverer();
- //最小格子和最大格子,总格子数量
- coverer.setMinLevel(7);//设置最小级别
- coverer.setMaxLevel(15);//设置最大级别
- coverer.setMaxCells(500);//设置最大Cell
- List<S2CellId> list = coverer.getCovering(cap).cellIds();
- // for (S2CellId s : list) {
- // System.out.println(s.id());
- // }
- return list.stream().map(S2CellId::id).collect(Collectors.toList());
- }
-
- /**
- * S2计算距离
- *
- * @param s1 点1的经度 纬度
- * @param s2 点2的经度 纬度
- * @return
- */
- public static double distance(PointS2 s1, PointS2 s2) {
- S2LatLng startS2 = S2LatLng.fromDegrees(s1.getLat(), s1.getLng());
- S2LatLng endS2 = S2LatLng.fromDegrees(s2.getLat(), s2.getLng());
- double distance = startS2.getEarthDistance(endS2);
- return distance;
- }
-
- /**
- * 计算地球上某个点是否在矩形区域内
- * 矩形的左下角点和矩形的右上角点通过纬度来判断,高低不然算不出来
- * @param s1 生成矩形的经纬度s1
- * @param s2 生成矩形的经纬度s2
- * @param s3 判断s3点是否在上面s1和s2的矩形中
- * @return
- */
- public static boolean pointRectangleArea(PointS2 s1, PointS2 s2, int desLevel, PointS2 s3) {
- S2LatLngRect rect = null;
- if (s1.getLat() > s2.getLat()) {
- //两个点可以经纬度-构建S2矩形
- rect = new S2LatLngRect(
- S2LatLng.fromDegrees(s2.getLat(), s2.getLng()),
- S2LatLng.fromDegrees(s1.getLat(), s1.getLng()));
- } else {
- //两个点可以经纬度-构建S2矩形
- rect = new S2LatLngRect(
- S2LatLng.fromDegrees(s1.getLat(), s1.getLng()),
- S2LatLng.fromDegrees(s2.getLat(), s2.getLng()));
- }
- //设置矩形的大小
- S2RegionCoverer coverer = new S2RegionCoverer();
- //设置cell
- coverer.setMinLevel(7);
- coverer.setMaxLevel(15);
- coverer.setMaxCells(500);
- S2CellUnion covering = coverer.getCovering(rect);
- S2LatLng s2LatLng = S2LatLng.fromDegrees(s3.getLat(), s3.getLng());
- return covering.contains(s2LatLng.toPoint());
- }
-
- /**
- * 计算点s2是否在圆中心为s1半径为capHeight的圆形区域内
- *
- * @param s1
- * @param capHeight
- * @param s2
- * @return
- */
- public static boolean pointGardenArea(PointS2 s1, double capHeight, PointS2 s2) {
- S2LatLng s2LatLng = S2LatLng.fromDegrees(s1.getLat(), s1.getLng());
- S2Cap cap = S2Cap.fromAxisHeight(s2LatLng.toPoint(), capHeight);
- S2LatLng s2LatLng2 = S2LatLng.fromDegrees(s2.getLat(), s2.getLng());
- boolean contains = cap.contains(s2LatLng2.toPoint());
- return contains;
- }
-
- /**
- * 判断点是否在任意形状内
- *
- * @param vertices 形成多边形的点集合
- * @param s 判断的点
- * @return
- */
- public static boolean pointPolygonArea(List<PointS2> vertices, PointS2 s) {
- //因为x一般表示经度 y轴表示纬度所以这儿需要参数需要对应一下
- List<S2Point> collect = vertices.stream().map(e -> S2LatLng.fromDegrees(e.getLng(), e.getLat()).toPoint()).collect(Collectors.toList());
- S2Loop s2Loop = new S2Loop(collect);
- S2Polygon polygon = new S2Polygon(s2Loop); //创建多边形
- S2Point s2Point = S2LatLng.fromDegrees(s.getLat(), s.getLng()).toPoint();
- boolean contains = polygon.contains(s2Point);
- return contains;
- }
-
- /**
- * 计算两个区域是否有交集
- *
- * @param vertices 形成多边形的点集合1
- * @param vertices2 形成多边形的点集合2
- * @return
- */
- public static boolean pointUniteArea(List<PointS2> vertices, List<PointS2> vertices2) {
- //因为x一般表示经度 y轴表示纬度所以这儿需要参数需要对应一下
- List<S2Point> collect = vertices.stream().map(e -> S2LatLng.fromDegrees(e.getLng(), e.getLat()).toPoint()).collect(Collectors.toList());
- //因为x一般表示经度 y轴表示纬度所以这儿需要参数需要对应一下
- List<S2Point> collect2 = vertices2.stream().map(e -> S2LatLng.fromDegrees(e.getLng(), e.getLat()).toPoint()).collect(Collectors.toList());
- S2Loop s2Loop = new S2Loop(collect);
- S2Polygon polygon = new S2Polygon(s2Loop);
- S2Loop s2Loop2 = new S2Loop(collect2);
- S2Polygon polygon2 = new S2Polygon(s2Loop2);
- S2RegionCoverer coverer = new S2RegionCoverer();
- //设置cell
- coverer.setMinLevel(7);//设置最小级别
- coverer.setMaxLevel(15);//设置最大级别
- coverer.setMaxCells(500);//设置最大Cell
- S2CellUnion covering = coverer.getCovering(polygon2);
- for (S2CellId s2CellId : covering.cellIds()) {
- boolean b = polygon.mayIntersect(new S2Cell(s2CellId));
- if (b) {
- System.out.println("两个区域之间含有交集.....");
- }
- return b;
- }
- return false;
- }
-
- /**
- * 不同等级S2块包含的S2子块
- *
- * @param s 自己的点
- * @param level 自己的等级
- * @param desLevel 被计算的格子等级,注意:等级越大算的就越多
- * @return
- */
- public static List<S2CellId> childrenCellId(PointS2 s, Integer level, Integer desLevel) {
- S2LatLng s2LatLng = S2LatLng.fromDegrees(s.getLat(), s.getLng());
- S2CellId cellId = S2CellId.fromLatLng(s2LatLng).parent(level);
- return childrenCellId(cellId, cellId.level(), desLevel);
- }
-
- //递归调用,每个格子一分为四
- private static List<S2CellId> childrenCellId(S2CellId s2CellId, Integer curLevel, Integer desLevel) {
- if (curLevel < desLevel) {
- //计算当前格子每个格子的差值
- long interval = (s2CellId.childEnd().id() - s2CellId.childBegin().id()) / 4;
- List<S2CellId> s2CellIds = Lists.newArrayList();
- for (int i = 0; i < 4; i++) {
- long id = s2CellId.childBegin().id() + interval * i;
- s2CellIds.addAll(childrenCellId(new S2CellId(id), curLevel + 1, desLevel));
- }
- return s2CellIds;
- } else {
- return Lists.newArrayList(s2CellId);
- }
- }
- /**
- * 任意形状内所有指定等级的S2块
- *
- * @param vertices 多边形的点
- * @param desevel 需要计算的内部的s2块的等级
- * @return
- */
- public static List<S2CellId> childrenCellId(List<PointS2> vertices, int desevel) {
- List<S2Point> collect = vertices.stream().map(e -> S2LatLng.fromDegrees(e.getLng(), e.getLat()).toPoint()).collect(Collectors.toList());
- S2Loop s2Loop = new S2Loop(collect);
- S2Polygon polygon = new S2Polygon(s2Loop);
-
- S2RegionCoverer coverer = new S2RegionCoverer();
- //设置cell
- coverer.setMinLevel(6);//设置最小级别 108km~151km
- coverer.setMaxLevel(11);//设置最大级别 3km~5km
- coverer.setMaxCells(500);//设置最大Cell
- S2CellUnion covering = coverer.getCovering(polygon);
- List<S2CellId> s2CellIds = covering.cellIds();
- int i=0;
- List<S2CellId> list=new ArrayList<>();
- for (S2CellId s2CellId : s2CellIds) {
- List<S2CellId> s2CellIds1 = childrenCellId(s2CellId, s2CellId.level(), desevel);
- list.addAll(s2CellIds1);
- }
- return list;
- }
-
- public static void main(String[] args) {
- double lat = 30.2;
- double lng = 116.3;
- int currentLevel = 13;
- S2LatLng s2LatLng = S2LatLng.fromDegrees(lat, lng);
- S2CellId cellId = S2CellId.fromLatLng(s2LatLng).parent(currentLevel);
- System.err.println(cellId);
- String s = cellId.toToken();
- System.err.println(s);
-
- /* System.err.println("------------------------------");
- System.err.println(latLonToCellToken(lat,lng,1));
- System.err.println(latLonToCellToken(lat,lng,2));
- System.err.println(latLonToCellToken(lat,lng,3));
- System.err.println(latLonToCellToken(lat,lng,4));
- System.err.println(latLonToCellToken(lat,lng,5));
- System.err.println(latLonToCellToken(lat,lng,6));
- System.err.println(latLonToCellToken(lat,lng,7));
- System.err.println(latLonToCellToken(lat,lng,8));
- System.err.println(latLonToCellToken(lat,lng,9));
- System.err.println(latLonToCellToken(lat,lng,10));
- System.err.println(latLonToCellToken(lat,lng,11));
- System.err.println(latLonToCellToken(lat,lng,12));
- System.err.println(latLonToCellToken(lat,lng,13));
- System.err.println(latLonToCellToken(lat,lng,14));
- System.err.println(latLonToCellToken(lat,lng,15));
- System.err.println(latLonToCellToken(lat,lng,16));
- System.err.println(latLonToCellToken(lat,lng,17));
- System.err.println(latLonToCellToken(lat,lng,18));
- System.err.println(latLonToCellToken(lat,lng,19));
- System.err.println(latLonToCellToken(lat,lng,20));
- System.err.println(latLonToCellToken(lat,lng,21));
- System.err.println(latLonToCellToken(lat,lng,30));
- System.err.println("------------------------------");*/
-
- PointS2 pointS2 = cellIdToLatLon(cellId.id());
- System.err.println(pointS2);
-
- double distance = distance(new PointS2(55.8241, 137.8347), new PointS2(55.8271, 137.8347));
- System.err.println("距离为:" + distance + " m");
-
- boolean b = pointRectangleArea(new PointS2(41.808006669390046, 111.495546258779), new PointS2(47.55467105799515, 117.6168335999181),
- 30, new PointS2(45.47161041105891, 114.84087253252726));
- System.err.println("矩形-----------------" + b);
-
- boolean b2 = pointGardenArea(new PointS2(112.030500, 27.970271), 600.5, new PointS2(22.629164, 114.025514));
- System.err.println(b2);
-
- ArrayList<PointS2> pointS2s = new ArrayList<>();
- pointS2s.add(new PointS2(41.200195, 97.760681));
- pointS2s.add(new PointS2(41.827161, 103.119335));
- pointS2s.add(new PointS2(36.507585, 103.688463));
- pointS2s.add(new PointS2(35.895869, 98.743842));
- pointS2s.add(new PointS2(41.253179, 97.700277));
- boolean b1 = pointPolygonArea(pointS2s, new PointS2(39.470948, 100.302180));
- System.err.println("多边形-----------" + b1);
- System.err.println("多边形2-----------" + Ryamethod.ray2(39.470948f, 100.302180f, pointS2s));
-
- // boolean b3 = pointUniteArea(pointS2s, pointS2s);
- ArrayList<PointS2> pointS2s1 = Lists.newArrayList(new PointS2(1, 2), new PointS2(3, 4));
-
- boolean b3 = pointUniteArea(pointS2s, pointS2s1);
- System.err.println(b3);
-
- // List<S2CellId> s2CellIds1 = childrenCellId(new PointS2(39.470948, 100.302180), 10, 12);
- // for (S2CellId s2CellId : s2CellIds1) {
- // System.err.println("点下的s2的token------"+s2CellId.toToken());
- // }
-
- List<S2CellId> s2CellIds = childrenCellId(pointS2s, 10);
- // for (S2CellId s2CellId : s2CellIds) {
- // System.err.println("token------"+s2CellId.toToken());
- // }
- }
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。