首页 文章

Google Map 图块提供程序(GeoServer和WMS)

提问于
浏览
1

WMS Webservice GeoServer WMS

我尝试在Google Map中使用缩放级别在选定的纬度和经度上获取Tile Information(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 };

}

基于缩放级别的问题我无法找到确切的值 . 基于正确的值我可以调用WMS webservices

提前致谢...

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 回答

  • 1

    我没有查看你的代码,但是我的工作已经多年了,所以这里是WMS tile提供者类:

    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;
        }
    
    }
    

    为了使代码正确,你必须使用“inMetersYCoordinate”转换纬度(米),经度使用“inMetersXCoordinate”,然后使用“getTileByCoordinate”来计算瓦片x,y,z(i,j,缩放给你)

相关问题