代码之家  ›  专栏  ›  技术社区  ›  AnanThDev

谷歌地图平铺提供商(GeoServer和WMS)

  •  2
  • AnanThDev  · 技术社区  · 9 年前

    WMS Web服务 GeoServer WMS

    我尝试在谷歌地图中通过缩放级别获取选定纬度和经度的平铺信息(I,J,BBOX)。

    我用这个公式得到了I,J,BBOX Formula Source

    private void getXYFromLatLon(double lat, double lon, final int zoom) {
        int tileSize = 256;
        // double initialResolution = 2 * Math.PI * 6378137 / tileSize;
        double initialResolution = 156543.03392804062;
        double originShift = 20037508.342789244;
        // LatLong to Meter
        double mx = lon * originShift / 180.0;
        double my = Math.log(Math.tan((90 + lat) * Math.PI / 360.0))
                / (Math.PI / 180.0);
        my = my * originShift / 180.0;
        // Meter to Pixels
        double res = initialResolution / (2 * zoom);
        double px = (mx + originShift) / res;
        double py = (my + originShift) / res;
    
        getBoundingBox(Double.valueOf(px).intValue(), Double.valueOf(py)
                .intValue(), zoom);
        // Pixel to tiles
        final int tx = (int) Math.ceil(px / ((tileSize)) - 1);
        final int ty = (int) Math.ceil(py / ((tileSize)) - 1);
    
        getTileBound(tx, ty, zoom, tileSize);
    
        Toast.makeText(getApplicationContext(), "X: " + tx + ",Y: " + ty,
                Toast.LENGTH_SHORT).show();
    
    }private void getTileBound(int tx, int ty, int zoom, int tileSize) {
        double[] min = pixelToMeter(tx * tileSize, ty * tileSize, zoom);
        double[] max = pixelToMeter((tx + 1) * tileSize, (ty + 1) * tileSize,
                zoom);
    
        builder.append("\nMIN-X:" + min[0]).append("\nMIN-Y:" + min[1])
                .append("\nMAX-X:" + max[0]).append("\nMAX-Y:" + max[1])
                .append("\nI:" + (tx)).append("\nJ:" + (ty));
        ((TextView) findViewById(R.id.textView1)).setText(builder.toString());
        /*
         * Toast.makeText(getApplicationContext(), "X: " + min.toString() +
         * ",Y: " + max.toString(), Toast.LENGTH_SHORT).show();
         */
    }public String getTileNumber(final double lat, final double lon,
            final int zoom) {
        int xtile = (int) Math.floor((lon + 180) / 360 * (1 << zoom));
        int ytile = (int) Math
                .floor((1 - Math.log(Math.tan(Math.toRadians(lat)) + 1
                        / Math.cos(Math.toRadians(lat)))
                        / Math.PI)
                        / 2 * (1 << zoom));
        if (xtile < 0)
            xtile = 0;
        if (xtile >= (1 << zoom))
            xtile = ((1 << zoom) - 1);
        if (ytile < 0)
            ytile = 0;
        if (ytile >= (1 << zoom))
            ytile = ((1 << zoom) - 1);
        System.out.println("xtile" + xtile);
    
        // Toast.makeText(getApplicationContext(),
        // xtile + "YY" + ytile + "Zoom" + (1 << zoom), Toast.LENGTH_LONG)
        // .show();
        return ("" + zoom + "/" + xtile + "/" + ytile);
    
    }private double[] pixelToMeter(int x, int y, int zoom) {
        int tileSize = 256;
        double initialResolution = 2 * Math.PI * 6378137 / tileSize;
        double originShift = 2 * Math.PI * 6378137 / 2;
        double res = initialResolution / (2 * zoom);
        double mx = x * res - originShift;
        double my = y * res - originShift;
    
        return new double[] { mx, my };
    
    }
    

    基于缩放级别的问题,我无法找到确切的值。。 基于正确的值i调用WMS Web服务

    提前感谢。。。

    http://192.168.1.102:1005/geoserver/estater/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetFeatureInfo&FORMAT=image%2Fpng&TRANSPARENT=true&QUERY_LAYERS=buildings&LAYERS=kwt_buildings&INFO_FORMAT=application%2Fjson&propertyName=grid_id%2Cbuild_id&I=90&J=161&WIDTH=256&HEIGHT=256&CRS=EPSG%3A3857&STYLES=&BBOX=5342031.032794397%2C3420709.8898182083%2C5343254.02524696%2C3421932.882270771

    1 回复  |  直到 9 年前
        1
  •  1
  •   N Dorigatti    9 年前

    我没有看你的代码,但我多年来一直在工作,所以这里是WMS瓷砖供应商类:

    public abstract class WMSTileProvider extends UrlTileProvider {
    
    // Web Mercator n/w corner of the map.
    private static final double[] TILE_ORIGIN = { -20037508.34789244, 20037508.34789244 };
    // array indexes for that data
    private static final int ORIG_X = 0;
    private static final int ORIG_Y = 1; // "
    
    // Size of square world map in meters, using WebMerc projection.
    private static final double MAP_SIZE = 20037508.34789244 * 2;
    
    // array indexes for array to hold bounding boxes.
    protected static final int MINX = 0;
    protected static final int MAXX = 1;
    protected static final int MINY = 2;
    protected static final int MAXY = 3;
    
    // cql filters
    private String cqlString = "";
    
    // Construct with tile size in pixels, normally 256, see parent class.
    public WMSTileProvider(int x, int y) {
        super(x, y);
    }
    
    @SuppressWarnings("deprecation")
    protected String getCql() {
        try {
            return URLEncoder.encode(cqlString, Charset.defaultCharset().name());
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return URLEncoder.encode(cqlString);
        }
    }
    
    public void setCql(String c) {
        cqlString = c;
    }
    
    // Return a web Mercator bounding box given tile x/y indexes and a zoom
    // level.
    protected double[] getBoundingBox(int x, int y, int zoom) {
        double tileSize = MAP_SIZE / Math.pow(2, zoom);
        double minx = TILE_ORIGIN[ORIG_X] + x * tileSize;
        double maxx = TILE_ORIGIN[ORIG_X] + (x + 1) * tileSize;
        double miny = TILE_ORIGIN[ORIG_Y] - (y + 1) * tileSize;
        double maxy = TILE_ORIGIN[ORIG_Y] - y * tileSize;
    
        double[] bbox = new double[4];
        bbox[MINX] = minx;
        bbox[MINY] = miny;
        bbox[MAXX] = maxx;
        bbox[MAXY] = maxy;
    
        return bbox;
    }
    }
    

    下面是我如何使用它的一些信息:

    public static WMSTileProvider getWMSTileProviderByName(String layerName) {
            final String OSGEO_WMS = "http://yourserver/geoserver/gwc/service/wms/?"
                    + "LAYERS=" + layerName
                    + "&FORMAT=image/png8&"
                    + "PROJECTION=EPSG:3857&"
                    + "TILEORIGIN=lon=-20037508.34,lat=-20037508.34&"
                    + "TILESIZE=w=256,h=256"
                    + "&MAXEXTENT=-20037508.34,-20037508.34,20037508.34,20037508.34&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&SRS=EPSG:3857"
                    + "&BBOX=%f,%f,%f,%f&WIDTH=256&HEIGHT=256";
    
            return new WMSTileProvider(256, 256) {
    
                @Override
                public synchronized URL getTileUrl(int x, int y, int zoom) {
                    final double[] bbox = getBoundingBox(x, y, zoom);
                    String s = String.format(Locale.US, OSGEO_WMS, bbox[MINX], bbox[MINY], bbox[MAXX], bbox[MAXY]);
                    try {
                        return new URL(s);
                    } catch (MalformedURLException e) {
                        throw new AssertionError(e);
                    }
                }
            };
        }
    

    不能给你更多的代码,但我希望能帮助你

    编辑:有了评论,现在我明白你需要什么了。 这里是一些代码(旧的,但正在工作),你必须对此进行一些工作,这是一种黑客:

        private static final double[] TILES_ORIGIN = {-20037508.34789244, 20037508.34789244};//TODO Duplicate from WMS PROVIDER, put as utils
        // Size of square world map in meters, using WebMerc projection.
        private static final double MAP_SIZE = 20037508.34789244 * 2;//TODO Duplicate from WMS PROVIDER, put as utils
        private static final double ORIGIN_SHIFT = Math.PI * 6378137d;
    
    /**
         * Transform the y map meter in y cordinate
         *
         * @param latitude the latitude of map
         * @return meters of y cordinate
         */
        private double inMetersYCoordinate(double latitude) {
            if (latitude < 0) {
                return -inMetersYCoordinate(-latitude);
            }
            return (Math.log(Math.tan((90d + latitude) * Math.PI / 360d)) / (Math.PI / 180d)) * ORIGIN_SHIFT / 180d;
        }
    
        /**
         * Transform the x map meter in x cordinate
         *
         * @param longitude the longitude of map
         * @return meters of x cordinate
         */
        private double inMetersXCoordinate(double longitude) {
            return longitude * ORIGIN_SHIFT / 180.0;
        }
    
    /**
         * Get the Tile from x and y cordinates
         *
         * @param pointX    x of the map
         * @param pointY    y of the map
         * @param zoomLevel zoom of Tile
         * @return the relative TileDataInfo
         */
    private TileDataInfo getTileByCoordinate(double pointX, double pointY, int zoomLevel) {
        final double tileDim = MAP_SIZE / Math.pow(2d, zoomLevel);
    
        final int tileX = (int) ((pointX - TILES_ORIGIN[0]) / tileDim);
        final int tileY = (int) ((TILES_ORIGIN[1] - pointY) / tileDim);
    
        return new TileDataInfo(tileX, tileY, zoomLevel);
    }
    
    private static class TileDataInfo {
        int tileX;
        int tileY;
        int tileZoom;
    
        public TileDataInfo(int tileX, int tileY, int tileZoom) {
            this.tileX = tileX;
            this.tileY = tileY;
            this.tileZoom = tileZoom;
        }
    
    }
    

    为了获得正确的代码,您必须使用“inMetersYCordinate”转换纬度(单位:米),使用“inmetersXCordinate)转换经度(单位:英寸),然后使用“getTileByCordinate(单位:厘米)”计算平铺x、y、z(i、j、缩放)