当前位置: 首页 > 知识库问答 >
问题:

谷歌地图互动程序提供程序(地理服务器和WMS)

公良天逸
2023-03-14

WMS Web服务地理服务器WMS

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

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

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 Web服务

提前感谢...

http://192.168.1.102:1005/geoserver/estater/wms?SERVICE=WMS

共有1个答案

夏法
2023-03-14

我没有查看您的代码,但我的代码多年来一直在工作,因此这里是WMS tile provider类:

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

}

为了得到正确的代码,你必须使用"inMetersY坐标"转换纬度以米为单位,使用"inMetersX坐标"转换经度,然后使用"getTileBy坐标"计算磁贴x,y,z(i,j,为你缩放)

 类似资料:
  • 我对谷歌地图方向服务(api v3)有一个问题。我不知道如何指定起始和目标字符串。例如,对于请求: http://maps.googleapis.com/maps/api/js?sensor=false 或者 http://maps.googleapis.com/maps/api/directions/xml?sensor=false 服务器的响应为:未找到,即未找到路由, 但是,如果我将字符¨改

  • 正如标题所说,我已经在我的应用程序中使用谷歌地图,我也希望在Kindle设备中使用亚马逊地图。AM和GM v1在技术上使用相同的接口。我如何才能很好地解决这个问题,根据我使用的设备,我可以为每个类获得适当的类类型(例如com.google.android.maps.MapView或com.amazon.geo.maps.MapView)? 所以假设我需要适当版本的MapView类,具体取决于我的设

  • 我想知道是否有人在同一版本中实现了谷歌地图V2和百度地图;因为通用汽车在中国没有按预期工作? 或者我应该将项目分成两个分支?但是跳过维护两个分支会很好。

  • 02-14 13:09:38.184:e/databaseUtils(2348):向包写入异常02-14 13:09:38.184:e/databaseUtils(2348):java.lang.securityexception:权限拒绝:用户的get/set设置要求以用户-2的身份运行,但从用户0调用;这需要Android.permission.interact_across_users_fu

  • 我的测试方法涉及使用各种配置的许多模拟器(制造商/模型/维度/apis/目标)。 我最近升级到Android Studio 3.1。 我的应用程序现在已经运行了3年,使用谷歌地图v2,我想继续维护它(谷歌笑了)。 我现在拥有的每个模拟器(Nexus 5除外)都不起作用,因为它说Google Play服务需要更新,而且似乎没有办法解决它。Nexus 5模拟器没有错误,但显示空白地图背景。 当我试图消