Google S2常用操作
Google S2
包引用
<dependency>
<groupId>io.sgr</groupId>
<artifactId>s2-geometry-library-java</artifactId>
<version>1.0.0</version>
</dependency>
经纬度 转 CellId
val s2LatLng : S2LatLng = S2LatLng.fromDegrees(lat, lng)
val celId = S2CellId.fromLatLng(s2LatLng)
CellId 转 经纬度
val s2LatLng = new S2CellId(celId).toLatLng
val lat = s2LatLng.latDegrees()
val lng = s2LatLng.lngDegrees()
S2计算距离
val startS2: S2LatLng = S2LatLng.fromDegrees(55.8241, 137.8347)
val endS2: S2LatLng = S2LatLng.fromDegrees(55.8271, 137.8347)
val dis = startS2.getEarthDistance(endS2)
经纬度构建任意形状
经纬度构建S2矩形
val startS2: S2LatLng = S2LatLng.fromDegrees(0.8293, 72.004) //左下角
val endS2: S2LatLng = S2LatLng.fromDegrees(55.8271, 137.8347) //右上角
val rect: S2LatLngRect = new S2LatLngRect(startS2, endS2)
经纬度构建S2多边形
val vertices = new util.ArrayList[S2Point]
//注意,一般需要多边形内侧,此处需要按照逆时针顺序添加。
vertices.add(S2LatLng.fromDegrees(lat, lng).toPoint)
val s2Loop = new S2Loop(vertices)
val polygon = new S2Polygon(s2Loop)
经纬度构建圆形
double radius = 600.5; //半径
val capHeight = (2 * S2.M_PI) * (radius / 40075017)
S2LatLng s2LatLng= S2LatLng.fromDegrees(lat, lng);
S2Cap cap = S2Cap.fromAxisHeight(s2LatLng.toPoint(),capHeight × capHeight / 2);
任意形状内所有S2块
val rect //构建的形状
val coverer: S2RegionCoverer = new S2RegionCoverer
coverer.setMaxLevel(7)
coverer.setMinLevel(7)
val list: util.ArrayList[S2CellId] = coverer.getCovering(rect).cellIds()
判断点是否在任意形状内
val rect //构建的形状
S2LatLng s2LatLng = S2LatLng.fromDegrees(lat, lng);
boolean contains = rect.contains(s2LatLng.toPoint());
S2块包含的S2子块
求level=7的S2块下的level=8的4个子块的S2CellId,如下:
val s2CellId = S2CellId.fromLatLng(S2LatLng.fromDegrees(55.130666,88.700062)).parent(7)
val interval = (s2CellId.childEnd().id() - s2CellId.childBegin().id()) / 4
val childrenId = (0 until 4).flatMap(i => {
val id = s2CellId.childBegin().id() + interval * i
val cellId = new S2CellId(id).toLatLng
List(cellId.lngDegrees(), cellId.latDegrees()).mkString(",")
}).mkString(";")
求level=7的S2块下的level=9的16个子块的S2CellId,如下:
val s2CellId = S2CellId.fromLatLng(S2LatLng.fromDegrees(55.130666,88.700062)).parent(7)
val chilren = childrenCellId(s2CellId, 7, 9)
/**
* 求当前cellId下的所有 子cellId
* @param s2CellId 当前cellId
* @param curLevel 当前cellId的level 需与cellId保持一致
* @param desLevel 目标cellId的level 需大于当前cellId
* @return
*/
def childrenCellId(s2CellId: S2CellId, curLevel:Int, desLevel:Int): List[S2CellId] = {
if (curLevel < desLevel) {
val interval = (s2CellId.childEnd().id() - s2CellId.childBegin().id()) / 4
(0 until 4).flatMap(i => {
val id = s2CellId.childBegin().id() + interval * i
val cellId = new S2CellId(id)
childrenCellId(cellId, curLevel + 1, desLevel)
}).toList
} else List(s2CellId)
}
判断当前cellId的level
private static int getLevel(long input) {
int n = 0;
while (input % 2 == 0) {
input = input / 2;
n++;
}
return 30 - n / 2;
}