地理坐标(WGS84),投影坐标下(Mercator)切片系统的计算Java类

Laila ·
更新时间:2024-09-20
· 681 次阅读

1、地理坐标下切片系统的计算 地理坐标下切片系统的计算,主要适用于google地球中切片系统,以及目标底图参考系统为EPSG:4326的情况。 public class GlobalGeodetic { private int tileSize; private double resFact; public GlobalGeodetic(String tmscompatible, int tileSize) { this.tileSize = tileSize; if (tmscompatible != null && tmscompatible.length() > 0) { // Defaults the resolution factor to 0.703125 (2 tiles @ level 0) this.resFact = 180.0D / (double)this.tileSize; } else { //Defaults the resolution factor to 1.40625 (1 tile @ level 0) this.resFact = 360.0D / (double)this.tileSize; } } public double[] lonlatToPixels(double lon, double lat, int zoom) { double res = this.resFact / Math.pow(2.0D, (double)zoom); return new double[]{(180.0D + lon) / res, (90.0D + lat) / res}; } public int[] pixelsToTile(double px, double py) { int tx = (int)(Math.ceil(px / (double)this.tileSize) - 1.0D); int ty = (int)(Math.ceil(py / (double)this.tileSize) - 1.0D); return new int[]{tx, ty}; } public int[] lonlatToTile(double lon, double lat, int zoom) { double[] pxpy = this.lonlatToPixels(lon, lat, zoom); return this.pixelsToTile(pxpy[0], pxpy[1]); } public double resolution(int zoom) { return this.resFact / Math.pow(2.0D, (double)zoom); } public int zoomForPixelSize(double pixelSize) { for(int i = 0; i this.resolution(i)) { if (i != 0) { return i - 1; } return 0; } } return 0; } public double[] tileBounds(int tx, int ty, int zoom) { double res = this.resFact / Math.pow(2.0D, (double)zoom); return new double[]{(double)(tx * this.tileSize) * res - 180.0D, (double)(ty * this.tileSize) * res - 90.0D, (double)((tx + 1) * this.tileSize) * res - 180.0D, (double)((ty + 1) * this.tileSize) * res - 90.0D}; } public double[] tileLatLonBounds(int tx, int ty, int zoom) { double[] b = this.tileBounds(tx, ty, zoom); return new double[]{b[1], b[0], b[3], b[2]}; } } 2、投影坐标系下计算类 目前绝大多数切片系统内部实现都是采用这种方式实现。 public class GlobalMercator { private int tileSize; private double initialResolution; private double originSh; //6378137 为地球半径 public GlobalMercator(int tileSize) { this.tileSize = tileSize; this.initialResolution = 2 * Math.PI * 6378137 / this.tileSize; this.originShift = 2 * Math.PI * 6378137 / 2.0; } public double[] latLonToMeters(double lat, double lon) { double mx = lon * this.originShift / 180.0; double my = Math.log(Math.tan((90 + lat) * Math.PI / 360.0)) / (Math.PI / 180.0); my = my * this.originShift / 180.0; return new double[]{mx, my}; } public double[] metersToLatLon(double mx, double my) { double lon = (mx / this.originShift) * 180.0; double lat = (my / this.originShift) * 180.0; lat = 180 / Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180.0)) - Math.PI / 2.0); return new double[]{lat, lon}; } public double[] pixelsToMeters(int px, int py, int zoom) { double res = this.resolution(zoom); double mx = px * res - this.originShift; double my = py * res - this.originShift; return new double[]{mx, my}; } public double[] metersToPixels(double mx, double my, int zoom) { double res = this.resolution(zoom); double px = (mx + this.originShift) / res; double py = (my + this.originShift) / res; return new double[]{px, py}; } public int[] pixelsToTile(double px, double py) { int tx = (int) (Math.ceil(px / (float) (this.tileSize)) - 1); int ty = (int) (Math.ceil(py / (float) (this.tileSize)) - 1); return new int[]{tx, ty}; } public double[] pixelsToRaster(double px, double py, int zoom) { double mapSize = this.tileSize << zoom; return new double[]{px, mapSize - py}; } public int[] metersToTile(double mx, double my, int zoom) { double[] coordinate = this.metersToPixels(mx, my, zoom); return this.pixelsToTile(coordinate[0], coordinate[1]); } public double[] tileBounds(int tx, int ty, int zoom) { double[] minxy = pixelsToMeters(tx * this.tileSize, ty * this.tileSize, zoom); double[] maxxy = pixelsToMeters((tx + 1) * this.tileSize, (ty + 1) * this.tileSize, zoom); return new double[]{minxy[0], minxy[1], maxxy[0], maxxy[1]}; } public double[] tileLatLonBounds(int tx, int ty, int zoom) { double[] bounds = this.tileBounds(tx, ty, zoom); double[] minLatLon = this.metersToLatLon(bounds[0], bounds[1]); double[] maxLatlon = this.metersToLatLon(bounds[2], bounds[3]); return new double[]{minLatLon[0], minLatLon[1], maxLatlon[0], maxLatlon[1]}; } public double resolution(int zoom) { return this.initialResolution / (Math.pow(2, zoom)); } public int zoomForPixelSize(double pixelSize) { for (int i = 0; i this.resolution(i)) { if (i != 0) { return i - 1; } else return 0; } } return 0; } //XYZ切片系统转googleTSM切片系统,其实就是坐标系的Y轴的变换,由原点左上角变换为原点左下角。 public int[] googleTile(int tx, int ty, int zoom) { return new int[]{tx, ((int) (Math.pow(2, zoom)) - 1) - ty}; } public String quadTree(int tx, int ty, int zoom) { String quadKey = ""; ty = (int) (Math.pow(2, zoom) - 1 - ty); for (int i = zoom; i > 0; i--) { int digit = 0; int mask = 1 < 0; i--) { char digit = '0'; int mask = 1 < 0; i--) { int mask = 1 << (i - 1); switch (quadKey.charAt(levelOfDetail - i)) { case '0': break; case '1': tileX |= mask; break; case '2': tileY |= mask; break; case '3': tileX |= mask; tileY |= mask; break; default: throw new Exception("Invalid QuadKey digit sequence."); } } return new int[]{tileX, tileY, levelOfDetail}; } } 3、使用例子 根据XYZ计算经纬度范围 //地理坐标(EPSG:4326)下计算方式 double[] bbox = new GlobalGeodetic("", 256).tileLatLonBounds(x, y, z); //投影坐标(EPSG:3857)下的计算方式 double[] bboxs = new GlobalMercator(256).tileLatLonBounds(x, y, z); 根据经纬度范围计算XYZ //地理坐标(EPSG:4326)下计算方式 ……待补充 //投影坐标(EPSG:3857)下的计算方式 Envelope envelope = new Envelope(xmin, xmax, ymin, ymax); GlobalMercator mercator = new GlobalMercator(256); double[] min = mercator.latLonToMeters(envelope.getMinY(), envelope.getMinX()); double[] max = mercator.latLonToMeters(envelope.getMaxY(), envelope.getMaxX()); //#region 计算 for (int tz = tmaxz; tz > tminz - 1; tz--) { int[] tminxy = mercator.metersToTile(min[0], min[1], tz); int[] tmaxxy = mercator.metersToTile(max[0], max[1], tz); tminxy = new int[]{Math.max(0, tminxy[0]), Math.max(0, tminxy[1])}; tmaxxy = new int[]{(int) Math.min(Math.pow(2, tz) - 1, tmaxxy[0]), (int) Math.min(Math.pow(2, tz) - 1, tmaxxy[1])}; for (int tx = tminxy[0]; tx tminxy[1] - 1; ty--) { //z,x,y坐标 } } } //endregion 作者:JerFer



wgs84 JAVA 地理坐标 系统 地理

需要 登录 后方可回复, 如果你还没有账号请 注册新账号