A8站源码交易平台 地理坐标(WGS84)/投影坐标下(Mercator)切片体系的核算Java类

摘要://投影坐标(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 < tmaxxy[0] + 1; tx++) {

A8站源码交易平台

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 < 32; ++i) {
            if (pixelSize > 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]};
    }
}


A8站源码交易平台

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 < 32; i++) {
            if (pixelSize > 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 << (i - 1);
            if ((tx & mask) != 0) {
                digit += 1;
            }
            if ((ty & mask) != 0) {
                digit += 2;
                quadKey += digit;
            }
        }
        return quadKey;
    }
//XYZ转换为geohash编码
    public String tileXYToQuadKey(int tileX, int tileY, int levelOfDetail) {
        StringBuilder quadKey = new StringBuilder();
        for (int i = levelOfDetail; i > 0; i--) {
            char digit = '0';
            int mask = 1 << (i - 1);
            if ((tileX & mask) != 0) {
                digit++;
            }
            if ((tileY & mask) != 0) {
                digit++;
                digit++;
            }
            quadKey.append(digit);
        }
        return quadKey.toString();
    }
//geohash编码转换为XYZ
    public int[] quadKeyToTileXY(String quadKey) throws Exception {
        int tileX = 0, tileY = 0;
        int levelOfDetail = quadKey.length();
        for (int i = levelOfDetail; i > 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};
    }
}



A8站源码交易平台

3、运用比如
依据XYZ核算经纬度规模
//地理坐标(EPSG:4326)下核算方法
double[] bbox = new GlobalGeodetic("", 256).tileLatLonBounds(x, y, z);
 //投影坐标(EPSG:3857)下的核算方法
double[] bboxs = new GlobalMercator(256).tileLatLonBounds(x, y, z);

A8站源码交易平台



依据经纬度规模核算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 < tmaxxy[0] + 1; tx++) {
         for (int ty = tmaxxy[1]; ty > tminxy[1] - 1; ty--) {
    //z,x,y坐标
    }
    }
}
//endregion
A8站源码交易平台


  • 全部评论(0)
最新发布的资讯信息
【A8站-免费源码分享|直播源码】直播系统源码开发:关于安卓开发工具和obs直播推流(2020-10-30 09:41)
【计算机/互联网|】【独家修复】用户定制版短视频点赞系统,支持抖音+快手+刷宝+微视等所有主流短视频评论系统源码(2020-10-26 16:34)
【技术宅-为技术而疯|网站架设教程】【独家首发】最新更新已对接短信2020全新抖音快手点赞任务系统霸屏天下小红书头条威客兼职完整搭建架设视频教程(2020-10-25 13:56)
【技术宅-为技术而疯|网站架设教程】最新可用个人发卡网系统源码完整搭建架设视频教程(2020-10-25 10:53)
【技术宅-为技术而疯|网站架设教程】独家更新全新V10抢单系统唯品会京东淘宝自动抢单区块系统源码全开源抢单收单接单返利+搭建架设完整视频教程(2020-10-25 10:52)
【计算机/互联网|】柔丫纸尿裤云仓系统源码部署(2020-10-15 18:13)
【计算机/互联网|】侏罗纪软件模式定制开发(2020-10-14 15:33)
【计算机/互联网|】S2b2C供应商系统 营销闭环(2020-10-10 17:46)
【计算机/互联网|程序设计开发】盛都汇系统奖励机制(2020-10-10 17:20)
【A8站-免费源码分享|网站源码】积分商城系统APP开发(2020-09-23 14:56)
联系我们
Q Q:3101359898 点击直接对话
电话:18580901894
邮箱:admin#a8zhan.com
时间:09:00 - 24:00
手机二维码 访问手机版
返回顶部