如何在特定边界框的 osmdroid 地图上加载 geoserver WMS 图层?

发布于 2025-01-09 14:01:32 字数 5734 浏览 3 评论 0原文

我正在使用 osmdroid 库在我的应用程序中显示地图视图。我必须在我的 osm 地图中加载 wms 图层以显示村庄边界。

我在谷歌和堆栈溢出上进行搜索,发现以下博客和帖子

  1. 如何将 OSMDroid 与私人提供商使用的网络地图服务 (WMS) 配合使用?
  2. 带有自定义 wms 图块提供程序的 Android Mapview
  3. 在带有 GeoServer 的 Android 应用程序中使用 getTileURL
  4. https://osmdroid.github.io/osmdroid/Map-Sources.html
  5. < a href="https://docs.geoserver.org/latest/en/user/services/wms/reference.html#getmap" rel="nofollow noreferrer">https://docs.geoserver.org/latest/en/user/services/wms/reference.html#getmap

我引用了这些并尝试实现相同的,我能够在 osm 上加载 wms 层映射成功。但它是在多个循环中加载的,您可以在下图中看到

在此处输入图像描述

我希望此 wms 图层仅加载到我在 wms Api url 中传递的提到的边界框中。

我调用 wms 层 api

public class TileProviderFactory {
private static final String TAG = "TileProviderFactory";

private String version = "1.1.0";
private String url = "http://49.206.244.230:8080/geoserver/cfr/wms";
private String layers = "cfr:bastar_villages";

public WMSTileProvider getWmsTileProvider() {

    String[] baseUrl = {url};
    
    final String WMS_FORMAT_STRING =
            url +
                    "?service=WMS" +
                    "&version=" + version +
                    "&request=GetMap" +
                    "&layers=" + layers +
                    "&bbox=81.3445510864258,18.6015472412109,82.2461547851562,19.5618953704834" +
                    "&width=721" +
                    "&height=768" +
                    "&srs=EPSG:4326" +  // NB This is important, other SRS's won't work.
                    "&format=image/png" +
                    "&transparent=true";


    WMSTileProvider tileProvider = new WMSTileProvider(baseUrl, 256) {
        @Override
        public String getTileURLString(long pMapTileIndex) {
            WebMercatorBoundingBox bb = new WebMercatorBoundingBox(MapTileIndex.getX(pMapTileIndex), MapTileIndex.getY(pMapTileIndex), MapTileIndex.getZoom(pMapTileIndex));
            String s = String.format(
                    Locale.ENGLISH,
                    WMS_FORMAT_STRING,
                    bb.getWest(),
                    bb.getSouth(),
                    bb.getEast(),
                    bb.getNorth());
            Log.d(TAG,"Fetching map tile: " + s);
            return s;
        }
    };
    return tileProvider;
}}

WebMercatorBoundingBox 类

public class WebMercatorBoundingBox {
double north;
double south;
double east;
double west;


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

protected WebMercatorBoundingBox(final int x, final int y, final int zoom) {
    north = tile2lat(y, zoom);
    south = tile2lat(y + 1, zoom);
    west = tile2lon(x, zoom);
    east = tile2lon(x + 1, zoom);
}
double tile2lon(int x, int z) {
    double tileSize = MAP_SIZE / Math.pow(2.0, z);
    return  TILE_ORIGIN[ORIG_X] + x * tileSize;
}

double tile2lat(int y, int z) {
    double tileSize = MAP_SIZE / Math.pow(2.0, z);
    return TILE_ORIGIN[ORIG_Y] - y * tileSize;
}

public double getNorth(){
    return this.north;
}
public double getSouth(){
    return this.south;
}
public double getEast(){
    return this.east;
}
public double getWest(){
    return this.west;
}}

WMSTileProvider 抽象类

public abstract class WMSTileProvider extends OnlineTileSourceBase {

// cql filters
private String cqlString = "";

// Construct with tile size in pixels, normally 256, see parent class.
public WMSTileProvider(String[] baseurl, int tileSizeInPixels) {
    super("WMS tile source", 1 ,19,tileSizeInPixels,"png",baseurl);

}

protected String getCql() {
    return URLEncoder.encode(cqlString);
}

public void setCql(String c) {
    cqlString = c;
}
}

WebMercatorBoundingBox 的代码返回以下边界框(s 的值):

D/TileProviderFactory: Fetching map tile: http://49.206.244.230:8080/geoserver/cfr/wms?service=WMS&version=1.1.0&request=GetMap&layers=cfr:bastar_villages&bbox=-626172.135872,-1878516.407615,0.000000,-1252344.271743&width=721&height=768&srs=EPSG:4326&format=image/png&transparent=true
D/TileProviderFactory: Fetching map tile: http://49.206.244.230:8080/geoserver/cfr/wms?service=WMS&version=1.1.0&request=GetMap&layers=cfr:bastar_villages&bbox=-626172.135872,626172.135872,0.000000,1252344.271743&width=721&height=768&srs=EPSG:4326&format=image/png&transparent=true
D/TileProviderFactory: Fetching map tile: http://49.206.244.230:8080/geoserver/cfr/wms?service=WMS&version=1.1.0&request=GetMap&layers=cfr:bastar_villages&bbox=-1252344.271743,0.000000,-626172.135872,626172.135872&width=721&height=768&srs=EPSG:4326&format=image/png&transparent=true

请帮助我找出我的错误或给我任何如何实现目标的建议。

I am using osmdroid library to show mapview in my application. I have to load wms layer in my osm map to show village boundaries.

I have search on google and stack overflow and I found following blogs and posts

  1. How to work OSMDroid with Web Map Service (WMS) used by the private provider?
  2. android mapview with custom wms tile provider
  3. Using getTileURL in Android Application with GeoServer
  4. https://osmdroid.github.io/osmdroid/Map-Sources.html
  5. https://docs.geoserver.org/latest/en/user/services/wms/reference.html#getmap

I referred these and tried to implement same and I am able to load wms layer on osm map successfully. But it is loaded in multiple loop you can see in below image

enter image description here

I want this wms layer only be loaded in mentioned bounding box which I am passing in wms Api url.

My code to calling wms layer api

public class TileProviderFactory {
private static final String TAG = "TileProviderFactory";

private String version = "1.1.0";
private String url = "http://49.206.244.230:8080/geoserver/cfr/wms";
private String layers = "cfr:bastar_villages";

public WMSTileProvider getWmsTileProvider() {

    String[] baseUrl = {url};
    
    final String WMS_FORMAT_STRING =
            url +
                    "?service=WMS" +
                    "&version=" + version +
                    "&request=GetMap" +
                    "&layers=" + layers +
                    "&bbox=81.3445510864258,18.6015472412109,82.2461547851562,19.5618953704834" +
                    "&width=721" +
                    "&height=768" +
                    "&srs=EPSG:4326" +  // NB This is important, other SRS's won't work.
                    "&format=image/png" +
                    "&transparent=true";


    WMSTileProvider tileProvider = new WMSTileProvider(baseUrl, 256) {
        @Override
        public String getTileURLString(long pMapTileIndex) {
            WebMercatorBoundingBox bb = new WebMercatorBoundingBox(MapTileIndex.getX(pMapTileIndex), MapTileIndex.getY(pMapTileIndex), MapTileIndex.getZoom(pMapTileIndex));
            String s = String.format(
                    Locale.ENGLISH,
                    WMS_FORMAT_STRING,
                    bb.getWest(),
                    bb.getSouth(),
                    bb.getEast(),
                    bb.getNorth());
            Log.d(TAG,"Fetching map tile: " + s);
            return s;
        }
    };
    return tileProvider;
}}

WebMercatorBoundingBox class

public class WebMercatorBoundingBox {
double north;
double south;
double east;
double west;


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

protected WebMercatorBoundingBox(final int x, final int y, final int zoom) {
    north = tile2lat(y, zoom);
    south = tile2lat(y + 1, zoom);
    west = tile2lon(x, zoom);
    east = tile2lon(x + 1, zoom);
}
double tile2lon(int x, int z) {
    double tileSize = MAP_SIZE / Math.pow(2.0, z);
    return  TILE_ORIGIN[ORIG_X] + x * tileSize;
}

double tile2lat(int y, int z) {
    double tileSize = MAP_SIZE / Math.pow(2.0, z);
    return TILE_ORIGIN[ORIG_Y] - y * tileSize;
}

public double getNorth(){
    return this.north;
}
public double getSouth(){
    return this.south;
}
public double getEast(){
    return this.east;
}
public double getWest(){
    return this.west;
}}

WMSTileProvider abstract class

public abstract class WMSTileProvider extends OnlineTileSourceBase {

// cql filters
private String cqlString = "";

// Construct with tile size in pixels, normally 256, see parent class.
public WMSTileProvider(String[] baseurl, int tileSizeInPixels) {
    super("WMS tile source", 1 ,19,tileSizeInPixels,"png",baseurl);

}

protected String getCql() {
    return URLEncoder.encode(cqlString);
}

public void setCql(String c) {
    cqlString = c;
}
}

WebMercatorBoundingBox return following bounding box(value of s):

D/TileProviderFactory: Fetching map tile: http://49.206.244.230:8080/geoserver/cfr/wms?service=WMS&version=1.1.0&request=GetMap&layers=cfr:bastar_villages&bbox=-626172.135872,-1878516.407615,0.000000,-1252344.271743&width=721&height=768&srs=EPSG:4326&format=image/png&transparent=true
D/TileProviderFactory: Fetching map tile: http://49.206.244.230:8080/geoserver/cfr/wms?service=WMS&version=1.1.0&request=GetMap&layers=cfr:bastar_villages&bbox=-626172.135872,626172.135872,0.000000,1252344.271743&width=721&height=768&srs=EPSG:4326&format=image/png&transparent=true
D/TileProviderFactory: Fetching map tile: http://49.206.244.230:8080/geoserver/cfr/wms?service=WMS&version=1.1.0&request=GetMap&layers=cfr:bastar_villages&bbox=-1252344.271743,0.000000,-626172.135872,626172.135872&width=721&height=768&srs=EPSG:4326&format=image/png&transparent=true

Please help me to figure out my mistake or give me any suggestions how I achieve my goal.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

玩心态 2025-01-16 14:01:32

您似乎正在使用整个地图边界框来发出平铺请求 - 正如您所看到的http://49.206.244.230:8080/geoserver/cfr/wms?service=WMS&version=1.1.0&request=GetMap&layers=cfr:bastar_villages&bbox=81.34455108 64258,18.6015472412109,82.2461547851562,19.5618953704834&宽度=721&高度=768&srs=EPSG:4326&格式=image/png&透明=true

输入图片description here

但是您在每个图块中都要求它,因此您需要计算每个图块的边界(这也会将大小更改为 256x256)。此时,您可能应该在 WebMercator 坐标 (EPSG:3857) 中工作(否则地球的曲率会使数学变得困难)。

这就是我认为 WebMercatorBoundingBox 应该为您提供的内容,因此将这些坐标(它们将在数千到数百万范围内)与 EPSG:3857 的 SRS 相结合应该会返回您所需的图块。使用这些边界后,您需要确保已在 widthheight 参数中将图块大小正确设置为 265x256,并且 SRS< /code> 也设置正确。

更新

通过查看服务器,您可以使用WGS 图块设置并从以下位置开始计算:

<TileMatrixSet>
  <ows:Identifier>EPSG:4326</ows:Identifier>
  <ows:SupportedCRS>urn:ogc:def:crs:EPSG::4326</ows:SupportedCRS>
  <TileMatrix>
    <ows:Identifier>EPSG:4326:0</ows:Identifier>
    <ScaleDenominator>2.795411320143589E8</ScaleDenominator>
    <TopLeftCorner>90.0 -180.0</TopLeftCorner>
    <TileWidth>256</TileWidth>
    <TileHeight>256</TileHeight>
    <MatrixWidth>2</MatrixWidth>
    <MatrixHeight>1</MatrixHeight>
  </TileMatrix>

然后您将得到纬度/经度并可以使用 EPSG:4326。

You seem to be using the whole maps bounding box to make your tile requests - as you can see with http://49.206.244.230:8080/geoserver/cfr/wms?service=WMS&version=1.1.0&request=GetMap&layers=cfr:bastar_villages&bbox=81.3445510864258,18.6015472412109,82.2461547851562,19.5618953704834&width=721&height=768&srs=EPSG:4326&format=image/png&transparent=true

enter image description here

But you are asking for it in each tile, so you need to calculate the bounds for each tile (which changes the size to 256x256 as well). At this point you should probably be working in WebMercator coordinates (EPSG:3857) (otherwise the curvature of the Earth makes the maths hard).

This is what I think WebMercatorBoundingBox should give you so combining those coordinates (they will be in the thousands to millions range) with an SRS of EPSG:3857 should return you the required tiles. Once you are using those bounds you will need to make sure that you have correctly set the tile size to 265x256 in the width and height parameters and that the SRS is correctly set too.

Update

From a look at the server you could get use the WGS tile set and start your calculations from:

<TileMatrixSet>
  <ows:Identifier>EPSG:4326</ows:Identifier>
  <ows:SupportedCRS>urn:ogc:def:crs:EPSG::4326</ows:SupportedCRS>
  <TileMatrix>
    <ows:Identifier>EPSG:4326:0</ows:Identifier>
    <ScaleDenominator>2.795411320143589E8</ScaleDenominator>
    <TopLeftCorner>90.0 -180.0</TopLeftCorner>
    <TileWidth>256</TileWidth>
    <TileHeight>256</TileHeight>
    <MatrixWidth>2</MatrixWidth>
    <MatrixHeight>1</MatrixHeight>
  </TileMatrix>

and then you would get lat/lon out and could use EPSG:4326.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文