API 的投影东西并不是那么有用,我遇到了同样的问题并推出了自己的问题。
public class SphericalMercatorProjection {
public static PointD latLngToWorldXY(LatLng latLng, double zoomLevel) {
final double worldWidthPixels = toWorldWidthPixels(zoomLevel);
final double x = latLng.longitude / 360 + .5;
final double siny = Math.sin(Math.toRadians(latLng.latitude));
final double y = 0.5 * Math.log((1 + siny) / (1 - siny)) / -(2 * Math.PI) + .5;
return new PointD(x * worldWidthPixels, y * worldWidthPixels);
}
public static LatLng worldXYToLatLng(PointD point, double zoomLevel) {
final double worldWidthPixels = toWorldWidthPixels(zoomLevel);
final double x = point.x / worldWidthPixels - 0.5;
final double lng = x * 360;
double y = .5 - (point.y / worldWidthPixels);
final double lat = 90 - Math.toDegrees(Math.atan(Math.exp(-y * 2 * Math.PI)) * 2);
return new LatLng(lat, lng);
}
private static double toWorldWidthPixels(double zoomLevel) {
return 256 * Math.pow(2, zoomLevel);
}
}
使用此代码,您可以围绕新目标(即不是中心)转换地图。我选择使用锚点系统,其中 (0.5, 0.5) 是默认值,代表屏幕的中间。(0,0) 位于左上角,(1, 1) 位于左下角。
private LatLng getOffsetLocation(LatLng location, double zoom) {
Point size = getSize();
PointD anchorOffset = new PointD(size.x * (0.5 - anchor.x), size.y * (0.5 - anchor.y));
PointD screenCenterWorldXY = SphericalMercatorProjection.latLngToWorldXY(location, zoom);
PointD newScreenCenterWorldXY = new PointD(screenCenterWorldXY.x + anchorOffset.x, screenCenterWorldXY.y + anchorOffset.y);
newScreenCenterWorldXY.rotate(screenCenterWorldXY, cameraPosition.bearing);
return SphericalMercatorProjection.worldXYToLatLng(newScreenCenterWorldXY, zoom);
}
基本上,您使用投影来获取世界 XY 坐标,然后偏移该点并将其转回 LatLng。然后,您可以将其传递给您的地图。PointD 是简单类型,其中包含 x,y 作为双精度值,并且还进行旋转。
public class PointD {
public double x;
public double y;
public PointD(double x, double y) {
this.x = x;
this.y = y;
}
public void rotate(PointD origin, float angleDeg) {
double rotationRadians = Math.toRadians(angleDeg);
this.x -= origin.x;
this.y -= origin.y;
double rotatedX = this.x * Math.cos(rotationRadians) - this.y * Math.sin(rotationRadians);
double rotatedY = this.x * Math.sin(rotationRadians) + this.y * Math.cos(rotationRadians);
this.x = rotatedX;
this.y = rotatedY;
this.x += origin.x;
this.y += origin.y;
}
}
请注意,如果您同时更新地图方位和位置,请务必在 getOffsetLocation 中使用新方位。