1

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

}

基于缩放级别的问题我无法找到确切的值..基于正确的值我有调用 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=925&JHEIG=116 256&CRS=EPSG%3A3857&STYLES=&BBOX=5342031.032794397%2C3420709.8898182083%2C5343254.02524696%2C3421932.882270771

4

1 回答 1

1

我没有查看您的代码,但多年来我一直在工作,所以这里是 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);
                }
            }
        };
    }

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

编辑:鉴于评论,现在我知道你需要什么了。这是一些代码(旧但可以工作),您必须对其进行一些工作,这是一种 hack:

    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,zoom for you )

于 2015-09-04T07:20:39.257 回答