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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java实现Google的S2算法工具类

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

WGS84坐標(biāo)系 GCJ02坐標(biāo)系 BD09坐標(biāo)系的各種轉(zhuǎn)換

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

S2 Demo

Java實(shí)現(xiàn)Google的S2算法工具類GoogleS2GoogleS2GoogleS2-Java文檔類資源-CSDN下載

level (等級)min area(最小面積)max area(最大面積)average area(平均面積)units(單位)Random cell 1 (UK)() min edge length(隨機(jī)單元1 (UK)最小邊長度)Random cell 1 (UK) max edge length(隨機(jī)單元格1 (UK)最大邊長度)Random cell 2 (US) min edge length(隨機(jī)單元2 (US)最小邊長度)Random cell 2 (US) max edge length(隨機(jī)單元格2(美國)最大邊長度)Number of cells(單元格數(shù))
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位置信息接下來說下坐標(biāo)系。目前主要有三種地理坐標(biāo)系,如下:* 1、WGS84坐標(biāo)系:即地球坐標(biāo)系(World Geodetic System),國際上通用的坐標(biāo)系。* 設(shè)備包含的GPS芯片或者北斗芯片獲取的經(jīng)緯度一般都是為WGS84地理坐標(biāo)系,目前谷歌地圖采用的是WGS84坐標(biāo)系(中國范圍除外)。* 2、GCJ02坐標(biāo)系:即火星坐標(biāo)系,國測局坐標(biāo)系。是由中國國家測繪局制定。由WGS84坐標(biāo)系經(jīng)加密后的坐標(biāo)系。谷歌中國和搜搜中國采用的GCJ02地理坐標(biāo)系。* 3、BD09坐標(biāo)系:百度坐標(biāo)系,GCJ02坐標(biāo)系經(jīng)加密后的坐標(biāo)系。* 4、其他(搜狗坐標(biāo)系,圖吧坐標(biāo)系等)。大概率也是再GCJ02坐標(biāo)系基礎(chǔ)上加密生成的*/ 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;/*** 百度坐標(biāo)系 (BD-09) 與 火星坐標(biāo)系 (GCJ-02)的轉(zhuǎn)換* 即 百度 轉(zhuǎn) 谷歌、高德** @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;}/*** 火星坐標(biāo)系 (GCJ-02) 與百度坐標(biāo)系 (BD-09) 的轉(zhuǎn)換* 即谷歌、高德 轉(zhuǎn) 百度** @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轉(zhuǎn)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 ?星坐標(biāo)系 (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);}/*** ?星坐標(biāo)系 GCJ02 轉(zhuǎn)換為 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;}/*** ?星坐標(biāo)系 GCJ02 轉(zhuǎn)換為 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 坐標(biāo)轉(zhuǎn)換成 BD-09 坐標(biāo)* @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 坐標(biāo)轉(zhuǎn)換成GCJ-02 坐標(biāo)* 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坐標(biāo)* 如果你獲得的是WGS84坐標(biāo)-百度或者高德的地理坐標(biāo),請將其轉(zhuǎn)換為GPS-WGS84坐標(biāo)* 由于google s2默認(rèn)使用gps坐標(biāo)系,在國內(nèi)無法使用,需要轉(zhuǎn)換為國內(nèi)的gcj坐標(biāo)或者bd09坐標(biāo)* 主要包含3類方法:* getS2RegionByXXX* 獲取給定經(jīng)緯度坐標(biāo)對應(yīng)的S2Region,該region可用于獲取cellId,或用于判斷包含關(guān)系* getCellIdList* 獲取給定region的cellId,并通過childrenCellId方法控制其嚴(yán)格遵守minLevel* contains* 對于指定S2Region,判斷經(jīng)緯度或CellToken是否在其范圍內(nèi)*/ /* 包<dependency><groupId>io.sgr</groupId><artifactId>s2-geometry-library-java</artifactId><version>1.0.0</version></dependency>*/ public class GoogleS2 {/*** 經(jīng)緯度 轉(zhuǎn) S2CellId** @param lat 維度* @param lng 經(jīng)度* @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;}/*** 經(jīng)緯度 轉(zhuǎn) CellId** @param lat 維度* @param lng 經(jīng)度* @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();}/*** 經(jīng)緯度 轉(zhuǎn) cellToken** @param lat 維度* @param lng 經(jīng)度* @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 轉(zhuǎn) 經(jīng)緯度** @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 轉(zhuǎn) 經(jīng)緯度** @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是否包含指定經(jīng)緯度坐標(biāo)** @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;}}/*** 判斷當(dāng)前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;}/*** 獲取任意形狀內(nèi)所有S2塊* 可以用于區(qū)域內(nèi)目標(biāo)檢索,根據(jù)cellid建立索引,查詢區(qū)域內(nèi)cellid in (list)的區(qū)域** @param vertices 形成多邊形的點(diǎn)集合* @return*/private static List<Long> vertices(List<PointS2> vertices) {//因?yàn)閤一般表示經(jīng)度 y軸表示緯度所以這兒需要參數(shù)需要對應(yīng)一下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); //創(chuàng)建多邊形//S2Region cap 任意區(qū)域S2RegionCoverer coverer = new S2RegionCoverer();//最小格子和最大格子,總格子數(shù)量coverer.setMinLevel(7);//設(shè)置最小級別coverer.setMaxLevel(15);//設(shè)置最大級別coverer.setMaxCells(500);//設(shè)置最大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計(jì)算距離** @param s1 點(diǎn)1的經(jīng)度 緯度* @param s2 點(diǎn)2的經(jīng)度 緯度* @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;}/*** 計(jì)算地球上某個(gè)點(diǎn)是否在矩形區(qū)域內(nèi)* 矩形的左下角點(diǎn)和矩形的右上角點(diǎn)通過緯度來判斷,高低不然算不出來* @param s1 生成矩形的經(jīng)緯度s1* @param s2 生成矩形的經(jīng)緯度s2* @param s3 判斷s3點(diǎn)是否在上面s1和s2的矩形中* @return*/public static boolean pointRectangleArea(PointS2 s1, PointS2 s2, int desLevel, PointS2 s3) {S2LatLngRect rect = null;if (s1.getLat() > s2.getLat()) {//兩個(gè)點(diǎn)可以經(jīng)緯度-構(gòu)建S2矩形rect = new S2LatLngRect(S2LatLng.fromDegrees(s2.getLat(), s2.getLng()),S2LatLng.fromDegrees(s1.getLat(), s1.getLng()));} else {//兩個(gè)點(diǎn)可以經(jīng)緯度-構(gòu)建S2矩形rect = new S2LatLngRect(S2LatLng.fromDegrees(s1.getLat(), s1.getLng()),S2LatLng.fromDegrees(s2.getLat(), s2.getLng()));}//設(shè)置矩形的大小S2RegionCoverer coverer = new S2RegionCoverer();//設(shè)置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());}/*** 計(jì)算點(diǎn)s2是否在圓中心為s1半徑為capHeight的圓形區(qū)域內(nèi)** @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;}/*** 判斷點(diǎn)是否在任意形狀內(nèi)** @param vertices 形成多邊形的點(diǎn)集合* @param s 判斷的點(diǎn)* @return*/public static boolean pointPolygonArea(List<PointS2> vertices, PointS2 s) {//因?yàn)閤一般表示經(jīng)度 y軸表示緯度所以這兒需要參數(shù)需要對應(yīng)一下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); //創(chuàng)建多邊形S2Point s2Point = S2LatLng.fromDegrees(s.getLat(), s.getLng()).toPoint();boolean contains = polygon.contains(s2Point);return contains;}/*** 計(jì)算兩個(gè)區(qū)域是否有交集** @param vertices 形成多邊形的點(diǎn)集合1* @param vertices2 形成多邊形的點(diǎn)集合2* @return*/public static boolean pointUniteArea(List<PointS2> vertices, List<PointS2> vertices2) {//因?yàn)閤一般表示經(jīng)度 y軸表示緯度所以這兒需要參數(shù)需要對應(yīng)一下List<S2Point> collect = vertices.stream().map(e -> S2LatLng.fromDegrees(e.getLng(), e.getLat()).toPoint()).collect(Collectors.toList());//因?yàn)閤一般表示經(jīng)度 y軸表示緯度所以這兒需要參數(shù)需要對應(yīng)一下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();//設(shè)置cellcoverer.setMinLevel(7);//設(shè)置最小級別coverer.setMaxLevel(15);//設(shè)置最大級別coverer.setMaxCells(500);//設(shè)置最大CellS2CellUnion covering = coverer.getCovering(polygon2);for (S2CellId s2CellId : covering.cellIds()) {boolean b = polygon.mayIntersect(new S2Cell(s2CellId));if (b) {System.out.println("兩個(gè)區(qū)域之間含有交集.....");}return b;}return false;}/*** 不同等級S2塊包含的S2子塊** @param s 自己的點(diǎn)* @param level 自己的等級* @param desLevel 被計(jì)算的格子等級,注意:等級越大算的就越多* @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);}//遞歸調(diào)用,每個(gè)格子一分為四private static List<S2CellId> childrenCellId(S2CellId s2CellId, Integer curLevel, Integer desLevel) {if (curLevel < desLevel) {//計(jì)算當(dāng)前格子每個(gè)格子的差值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);}}/*** 任意形狀內(nèi)所有指定等級的S2塊** @param vertices 多邊形的點(diǎn)* @param desevel 需要計(jì)算的內(nèi)部的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();//設(shè)置cellcoverer.setMinLevel(6);//設(shè)置最小級別 108km~151kmcoverer.setMaxLevel(11);//設(shè)置最大級別 3km~5kmcoverer.setMaxCells(500);//設(shè)置最大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("點(diǎn)下的s2的token------"+s2CellId.toToken()); // }List<S2CellId> s2CellIds = childrenCellId(pointS2s, 10); // for (S2CellId s2CellId : s2CellIds) { // System.err.println("token------"+s2CellId.toToken()); // }}}

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。