0

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.

Shivam Jamaiwar
  • 524
  • 1
  • 4
  • 14
  • you need to subsitute your bounding box into the URL and change the SRS to EPSG:3857 to match those coordinates. – Ian Turton Feb 24 '22 at 10:21
  • I have already substitute bounding box into ulr `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:3857&format=image/png&transparent=true`. And yes I tried with **EPSG:3857** SRS but same output – Shivam Jamaiwar Feb 24 '22 at 11:04
  • You need to calculate your bounding box in 3857 (`WebMercatorBoundingBox`) to match the SRS you are sending – Ian Turton Feb 24 '22 at 11:11
  • How I will calculate bounding box in 3857? you have any sample snippet or reference so please share it. – Shivam Jamaiwar Feb 24 '22 at 11:20

1 Answers1

1

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.

Ian Turton
  • 10,018
  • 1
  • 28
  • 47
  • Hi @lan Turton, Not getting you exactly how to calculate the bounds for each tile. And combining those coordinates with an SRS of EPSG:3857. If you have any sample snippet or reference so please share it. This Wms layer and geoserver new for me. – Shivam Jamaiwar Feb 25 '22 at 10:06
  • Your method `WebMercatorBoundingBox` looks to calculate the bounds of a tile in ESPG:3857 - can you print out some values of `s` and add them to your question – Ian Turton Feb 25 '22 at 10:39
  • Hi @lan Turton, I have added some values of s to question. – Shivam Jamaiwar Feb 25 '22 at 11:41
  • 1
    Change the width and height to 256 and the srs to 3857 and those should be good tiles. – Ian Turton Feb 25 '22 at 16:57
  • Issue solved :), Actually I am passing wrong hardcoded bounding box and wrong srs value. Now I am passing srs = ESPG:3857 and correct bounding box which is calculated from `WebMercatorBoundingBox`. Thankyou @lan Turton – Shivam Jamaiwar Feb 26 '22 at 07:33
  • please accept the answer if it solved your problem – Ian Turton Feb 26 '22 at 08:55
  • Hi, Can you edit your answer as per the above comments so I can accept your answer – Shivam Jamaiwar Mar 01 '22 at 11:54