WMS layers rendered at wrong position

Topics: Data Access, SharpMap v2.0, Web Controls
Oct 5, 2007 at 8:57 AM
(continued from a accidently wrong positioned issue, my bad, sorry all)

I am sorry, if you guys are getting offended, but I am really trying to help to make SharpMap usable for me.

In response to:
"As designed. User should use a coordinate system for the map that matches the WMSLayer SRID" (SharpGIS)

and

"The BBOX in the request will match whatever the Map's extent is, so if it requests the wrong BBOX, make sure all your data in the Map match 28992. The SRID parameter is whatever you set the WMSLayer property to. It is just appended to the request string, with no interpretation.
If you look at the Render method in the code, the url is generated by calling "GetRequestUrl(map.Envelope,map.Size)", with NO projection of the map envelope, so if that extent is wrong, your map's extent is wrong for that spatial reference."

All the layers that are added to the map is in SRID 28992
In the mapserver WMS mapfile; all coordinate systems are set to 28992

When my program starts running:
1- The Map is constructed with the envelope -0.5 -0.5 0.5 0.5
2- All the layers are in SRID 28892
3- When the layers are Added, the maps bounding box shifts to the lat/lon coordinate envelope for the Netherlands.
3- When the WMS client is constructed in WMSLayer.cs, it ONLY creates a LATLONG boundingbox...; by doing this, my map also gets confused because one of the layers is in another srid, hereby changing the envelope to lat/lon
4- This bounding box is then called when the requeststring is constructed....
5- For a correct requeststring, the boundingbox has to match the SRID.

I discovered that in the SharpMap.Web.Wms.Client; the Boundingbox is not parsed, only the latlonboundingbox.

So the following information from the GetCapabilities request:

<BoundingBox SRS="EPSG:28992"
minx="160000" miny="427000" maxx="210000" maxy="478000" />

Gets skipped completely.

I just want to know if it is ok for me to do work on this topic that can later be merged with the general SharpMap branch.

Things I want to do are:

- Let the WMS Client parse the boundingbox(es) if it/they exist
- When rendering a WMS layer: Check to see if a boundingbox exists that matches the SRID that is set and then use that to construct the query string. If no boundingbox for the SRID exists; it will fall back to setting EPSG:4326 (lat/lon) and get the latlonboundingbox

Might this be an acceptable sollution? If it is I will start the work.
Oct 6, 2007 at 1:53 AM
1. Are you sure this is an extent that matches your projection??? EPSG:28992 is using meters as units, so you are specifying a 1x1 meter area and further more those coordinates are also outside the valid domain of the projection. See http://www.spatialreference.org/ref/epsg/28992/

2: Adding layers doesn't change the maps' boundingbox.

3a. Even though a layer has a different spatial reference, it won't apply any kind of transformation to it unless you specifically ask it to. WmsLayer doesn't even support transformations - it's all up to the WmsServer to interpret the SRID.

3b. This boundingbox is just used for getting the geographic extent of the wms service - it's not applied to the map. I agree that parsing the other SRID's might be a good thing to do.
Why do you say that one of your layers is in a different SRID? The whole point is that ALL layers should have the same spatial reference. SharpMap doesn't apply ANY reprojection logic what-so-ever on its own. It doesn't even know how to transform a SRID to a spatial reference - that is up to the developer to take care of. To add to that, transforming to/from Oblique Stereographic projection is not supported by SharpMap.

5. It requests whatever extent that the current map has, and that is an extent that you set on it.
Oct 8, 2007 at 9:11 AM
Odegaard, thank you for looking into my problem!

> 1. Are you sure this is an extent that matches your projection??? EPSG:28992 is using meters as units, so you are specifying a 1x1 meter area and further more those coordinates are also outside the valid domain of the projection. See http://www.spatialreference.org/ref/epsg/28992/

On the initiation of the map, the limits are set to -0.5 -0.5 0.5 0.5, when the WMS layers are added to the map, these limits stay the same.
When I issue a map.ZoomToExtents() the limits change to Envelope = {5.878782003288051,51.97122413433925 5.94602399671196,51.97122413433925}
This Envelope matches the latlonbounding box that is in the GetCapabilities result file for the WMS server. So, when staying in EPSG:4326, this is correct.

> 2: Adding layers doesn't change the maps' boundingbox.
This I noticed.

> 3a. Even though a layer has a different spatial reference, it won't apply any kind of transformation to it unless you specifically ask it to. WmsLayer doesn't even support transformations - it's all up to the WmsServer to interpret the SRID.

This is not correct, the SharpMap.Web.WMS.Client simply parses the "sm:LatLonBoundingBox" exclusively. The BoundingBox for the SRS I use (EPSG:28992) is simply not parsed at all.

> 3b. This boundingbox is just used for getting the geographic extent of the wms service - it's not applied to the map. I agree that parsing the other SRID's might be a good thing to do.
I will implement this, it is needed for my problem.
> Why do you say that one of your layers is in a different SRID? The whole point is that ALL layers should have the same spatial reference. SharpMap doesn't apply ANY reprojection logic what-so-ever on its own.

Because the latlongbox for the WMS layer is created, it looks as if SharpMap simply concludes that this particular layer is in EPSG:4326. I will look in to this and solve that.

> It doesn't even know how to transform a SRID to a spatial reference - that is up to the developer to take care of. To add to that, transforming to/from Oblique Stereographic projection is not supported by SharpMap.

Mmmm, ok. Then at first, I will make sure that everything is in Oblique Stereographic and see if I can put some effort in the proj.net component to get support for the transformation.

> 5. It requests whatever extent that the current map has, and that is an extent that you set on it.

Is it possible to set extent and SRID on the Map? I cannot find any properties or methods to set them
Oct 9, 2007 at 2:58 AM
> Is it possible to set extent and SRID on the Map? I cannot find any properties or methods to set them
Have you considered : myMap.Extent = myEnvelope; ?

So WmsLayer returns the wrong extent (because it to start with doesn't know which spatial reference you want to use), which in turn causes ZoomToFullExtent to zoom to the wrong extent. Set the extent manually to get around this.

Perhaps WmsLayer needs a collection of SRID's returned from the servers GetCapabilities that the developer can access and choose from, and depending on which its will be set to use, it returns the corresponding extent from that collection. You should consult the WMS specification - I'm not sure whether these extent values are required, thus it's not guaranteed that they will be available.
Oct 9, 2007 at 1:30 PM

Odegaard wrote:
> Is it possible to set extent and SRID on the Map? I cannot find any properties or methods to set them
Have you considered : myMap.Extent = myEnvelope; ?

Yes, but this is no solution, because the WMSLayer having the wrong projection causes all else to fail.


So WmsLayer returns the wrong extent (because it to start with doesn't know which spatial reference you want to use), which in turn causes ZoomToFullExtent to zoom to the wrong extent. Set the extent manually to get around this.

That assumption is wrong, the wms client simply has no implementation for getting the coordinate system for the remote wms server. It just takes the latlonbounding box and assumed that it is in wgs84. The Boundingbox for a set coordinatesystem is simply overlooked.

Perhaps WmsLayer needs a collection of SRID's returned from the servers GetCapabilities that the developer can access and choose from, and depending on which its will be set to use, it returns the corresponding extent from that collection. You should consult the WMS specification - I'm not sure whether these extent values are required, thus it's not guaranteed that they will be available.

That sounds more like my idea of getting to the solution. I will extend the wms client to get the available srids and read the boundingbox for the layer AND the SRID that is set for that bounding box, I think things will start to look more like it then.

I am an expert on mapserver WMS and think that I should be able to fix this matter on behalf of the Sharpmap community.


Oct 11, 2007 at 9:57 AM
I found out some more:

- Support for WMS in SharpMap is only reliable for WMS version 1.3.0
- The support for boundingboxes is not complete, from the 1.1.1 version description I took the following quote:

7.1.4.5.7 BoundingBox
Layers may have zero or more <BoundingBox> elements that are either stated explicitly or inherited from a parent Layer. Each BoundingBox states the bounding rectangle of the
map data in a particular spatial reference system; the attribute SRS indicates which SRS applies. If the data area is shaped irregularly then the BoundingBox gives the minimum
enclosing rectangle. The attributes minx, miny, maxx, maxy indicate the edges of the bounding box in units of the specified SRS as in Figure 5. Optional resx and resy
attributes indicate the spatial resolution of the data in those same units.

NOTE: _<LatLonBoundingBox> (Section 7.1.4.5.6) is effectively a BoundingBox in which the attribute
SRS="EPSG:4326" is implicit, but LatLonBoundingBox does not include resx and resy attributes. A separate BoundingBox element explicitly naming EPSG:4326 may be provided by the server in order, for example, to provide resolution information._

A Layer may have multiple BoundingBox element, but each one shall state a different SRS. A Layer inherits any BoundingBox values defined by its parents. A BoundingBox inherited from the parent Layer for a particular SRS is replaced by any declaration for the same SRS in the child Layer. A BoundingBox in the child for a new SRS not already declared by the parent is added to the list of bounding boxes for the child Layer. A single Layer element shall not contain more than one BoundingBox for the same SRS.

NOTE: _There is no provision for describing disjoint bounding boxes. For example, consider a dataset which covers two areas separated by some distance. The server cannot provide two separate bounding boxes in the same Layer using the same SRS to separately describe those areas. To handle this type of situation, the server may either define a single larger bounding box which encloses both areas, or may define two separate Layers that each have distinct Name and BoundingBox values.
A server which has the ability to transform data to different SRSes may choose not to provide an explicit BoundingBox for every possible SRS available for each Layer. The
server should provide BoundingBox information for at least the native SRS of the Layer. _

Im a considering implementing the following:

A WMSBoundingBox that inherits Boundingbox and extends it with resX,, resY and SRID

Can I do this without any trouble? And where should the WMSBoundingBox be placed; under SharpMap.Web.WMS or under SharpMap.Geometries?
Oct 11, 2007 at 3:24 PM
I have compiled and tested a connection to mapserver WMS with support for the dutch national coordinate system (EPSG:28992). This now works perfect for me.

I would like to know if there is a possibility to test my work and check to see if it is usable and generic enough for the 2.0 branche to be used. What steps do I have to take to get this done?

Coordinator
Oct 14, 2007 at 2:58 AM
Thanks, milovanderlinden, for looking into this. WMS 1.3 is the only version which was implemented in SharpMap, though there is an outstanding issue to add 1.1: WMS 1.0.0 and 1.1.1 support.

Feel free to checkout SharpMap v2 from http://sharpmapv2.googlecode.com/svn/trunk/ and see if you can come up with a general solution which will work well as a patch. In v2.0 (currently), the BoundingBox is implemented as a System.ValueType to get good perf with spatial indexes. The inheritance approach will thus not work. You might consider some class that implements IEnumerable<BoundingBox> to cover multiple bounding boxes.