日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java实现Google的S2算法工具类

發布時間:2024/3/13 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java实现Google的S2算法工具类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

WGS84坐標系 GCJ02坐標系 BD09坐標系的各種轉換

WGS84坐標系 GCJ02坐標系 BD09坐標系的各種轉換 Google S2 經緯度 轉 CellId 經緯度 轉 cellToken CellId 轉 經緯度 判斷當前cellId的level * 獲取任意形狀內所有S2塊 * 可以用于區域內目標檢索,根據cellid建立索引,查詢區域內cellid in (list)的區域 S2計算點距離 計算地球上某個點是否在矩形區域內 計算點s2是否在圓中心為s1半徑為capHeight的圓形區域內 判斷點是否在任意形狀內 計算兩個區域是否有交集 求不同等級S2塊包含的S2子塊

S2 Demo

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(單元格數)
085011012.1985011012.1985011012.19km27842 km7842 km7842 km7842 km6
121252753.0521252753.0521252753.05km23921 km5004 km3921 km5004 km24
24919708.236026521.165313188.26km21825 km2489 km1825 km2489 km96
31055377.481646455.51328297.07km2840 km1167 km1130 km1310 km384
4231564.06413918.15332074.27km2432 km609 km579 km636 km1536
553798.67104297.9183018.57km2210 km298 km287 km315 km6K
612948.8126113.320754.64km2108 km151 km143 km156 km24K
73175.446529.095188.66km254 km76 km72 km78 km98K
8786.21632.451297.17km227 km38 km36 km39 km393K
9195.59408.12324.29km214 km19 km18 km20 km1573K
1048.78102.0381.07km27 km9 km9 km10 km6M
1112.1825.5120.27km23 km5 km4 km5 km25M
123.046.385.07km21699 m2 km2 km2 km100M
130.761.591.27km2850 m1185 m1123 m1225 m402M
140.190.40.32km2425 m593 m562 m613 m1610M
1547520.399638.9379172.67m2212 m296 m281 m306 m6B
1611880.0824909.7319793.17m2106 m148 m140 m153 m25B
172970.026227.434948.29m253 m74 m70 m77 m103B
18742.51556.861237.07m227 m37 m35 m38 m412B
19185.63389.21309.27m213 m19 m18 m19 m1649B
2046.4197.377.32m27 m9 m9 m10 m7T
2111.624.3319.33m23 m5 m4 m5 m26T
222.96.084.83m2166 cm2 m2 m2 m105T
230.731.521.21m283 cm116 cm110 cm120 cm422T
240.180.380.3m241 cm58 cm55 cm60 cm1689T
25453.19950.23755.05cm221 cm29 cm27 cm30 cm7.00E+15
26113.3237.56188.76cm210 cm14 cm14 cm15 cm2.70E+16
2728.3259.3947.19cm25 cm7 cm7 cm7 cm1.08E+17
287.0814.8511.8cm22 cm4 cm3 cm4 cm4.32E+17
291.773.712.95cm212 mm18 mm17 mm18 mm1.73E+18
300.440.930.74cm26 mm9 mm8 mm9 mm7.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);//設置最大CellList<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();//設置cellcoverer.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();//設置cellcoverer.setMinLevel(7);//設置最小級別coverer.setMaxLevel(15);//設置最大級別coverer.setMaxCells(500);//設置最大CellS2CellUnion 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();//設置cellcoverer.setMinLevel(6);//設置最小級別 108km~151kmcoverer.setMaxLevel(11);//設置最大級別 3km~5kmcoverer.setMaxCells(500);//設置最大CellS2CellUnion 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()); // }}}

總結

以上是生活随笔為你收集整理的Java实现Google的S2算法工具类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。