FObermaier / DotSpatial.Plugins

Set of plugins/application-extensions for DotSpatial
16 stars 10 forks source link

Accuracy of projection for MapNik OSM TMS #4

Closed Adriaanse closed 10 years ago

Adriaanse commented 10 years ago

After replacing the WebMap plugin with the BrutileLayer implementation, The OSM (Mapnik) TMS provider is shifted by about 100m south-west if we overlay our application features..

We moved on to the BrutileLayer implementation so we can use the dutch PDOK services and solve issues with our feature overlays using DutchRD projection. Now on PDOK background everything is just perfect for our Dutch applications but for those outside the Netherlands our overlay is shifted when using OSM Mapnik TMS ;-)

I will investigate further next week, at first sight it looks as if the Projection reported by the TMS service for Mapnik is inaccurate (I did set the projection of the MapControl to the one reported by the BrutileLayer to make sure no reprojection of the tiles is needed, but now something is wrong with the reprojection of our feature layers)

pauldendulk commented 10 years ago

So with PDOK there is no projection but with OSM you are projecting your features from RD to SphericalMercator? Or are the tiles also projected?

Perhaps the RD projection string is not correct: http://oegeo.wordpress.com/2008/05/20/note-to-self-the-one-and-only-rd-projection-string/

Adriaanse commented 10 years ago

Exactly, our setup is that we always set DotSpatial to use the projection that Brutile layers reports back for a TMS, then we reproject our feature overlays to match.

I will debug the code to see if I can find the problem, after finishing a few other things today, i'll keep you posted...

BTW I have fixed the DutchRD projection string etc, that fix is included in the 1.6 DotSpatial release and it worked well with OSM in the WebMap Plugin before...

FObermaier commented 10 years ago

A possible explanation could be that WebMap plugin assignes the predefined WebMercator projection whereas BruTileLayer uses AuthorityCodeHandler. Are there any differences in the resulting Proj4Strings?

FObermaier commented 10 years ago

There is a difference WebMercator: +x_0=0 +y_0=0 +lon_0=0 +lat_1=0 +proj=merc +datum=WGS84 +no_defs AuthorityCodeHandler: +x_0=0 +y_0=0 +lon_0=0 +lat_1=0 +proj=merc +ellps=WGS84 +no_defs

FObermaier commented 10 years ago

To make it more obscure, a fairly decent postgis installation reports this: +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs

Adriaanse commented 10 years ago

Thanks for pointing me in that direction ! I'll do some testing tomorrow for the proj4 strings i can find for WebMercator and let you know which works best for us

Adriaanse commented 10 years ago

Looking at your post again, ellps=WGS84 is an invalid parameter, WGS is not an ellipse, this should indeed be +datum=WGS84, and if set the OSM Brutile layer to use: ProjectionInfo.FromProj4String("+x_0=0 +y_0=0 +lon_0=0 +lat_1=0 +proj=merc +datum=WGS84 +no_defs"); our feature overlays now are spot on ;-)

Thanks a LOT for solving my problem even before i found the time to dig into this myself !

Now we should also fix the wrong AuthorityCodeHandler definition in DotSpatial to make it work for everyone, right ?

pauldendulk commented 10 years ago

ah, a thread with lots of scary projection strings and a happy ending, well done!

Adriaanse commented 10 years ago

Oops, my conclusion was a bit premature, sorry, but i do love messing around with proj4 strings, let me see if i can get it right....

FObermaier commented 10 years ago

As I initially added the AuthorityCodeHandler and all the related files I'd say yes. You have to do it though, as I don't have commit rights anymore. IIRC there is a csv/tsv file that has some srid;proj4string key value pair, which should be compressed during compile and added as resource. I don't know if that chain is still enabled or not.

Adriaanse commented 10 years ago

OK, i will do as soon as I am sure i have found the right definition, the csv.tsv chains for the authoritycodes is still there, i did the same for the DutchRD fix.

Adriaanse commented 10 years ago

The happy ending was premature, sorry, even if I add a "hack" in the BrutileLayer constructor to replace "EPSG:3857" with the same Known...WebMercator projection as used by the WebMap plugin it doesn't solve the problem, yet...

Adriaanse commented 10 years ago

Bingo !

I noticed in the WebMap plugin code, the projection is being transferred toEsriString and back in many places, wich seemed odd but it was also my solution to the problem.

If I take the standard WebMercator projection and convert this back and forth via ESRI projection string the problem disappears

Obviously this is the kind of workaround that should not be required, i think its because the proj4 string, esri wkt, epsg code or whatever you start from is not stored as such in projectionInfo in its original form, each of them are reconstructed whenever you ask for it and appearantly the esri bits fix something in an unexpected way.

Happy ending: client happy, and now i have the rest of the weekend to dig down into DotSpatial.Projections and find an explanation for all this.

FObermaier commented 10 years ago

Have you tried the postgis init string?

Adriaanse commented 10 years ago

Yes, but none of the proj4 strings i tried give an accurate projection.

After conversion to esri string and back, it is accurate and it reports back a proj4 string of:

+x_0=0 +y_0=0 +lon_0=0 +lat_1=0 +proj=merc +datum=WGS84 +no_defs

And creating a projection from that is totally off by miles, something is seriously wrong here with DotSpatial.Projections.

Adriaanse commented 10 years ago

I just added a test for this to DotSpatial.Projections,Tests.Tester and now 2646 tests fail, wonder what happens if I check that in, hehehe...

it's a very valid test:

        // something is very wrong with the translation to/from proj4string
        var pCheck = ProjectionInfo.FromProj4String(pStart.ToProj4String());
        Assert.IsTrue(pCheck.ToEsriString() == pStart.ToEsriString());
Adriaanse commented 10 years ago

After ignoring a few Name fields that can get lost in the translation, I am finding some real issues here in this huge can of worms I just opened,

Somehow the ESRI and PROJ4 string parsers have a different understanding of both datums and ellipsoids, going back and forth most projections fail the test, even Geographic.World.WGS1972 fails the conversion, this time in the opposite direction, amazing !

To be continued, I guess I should take this to the DotSpatial forum, BrutileLayer is not to blame for any of this...

Adriaanse commented 10 years ago

I think I have found an explanation here (second post)

http://forums.esri.com/Thread.asp?c=93&f=984&t=288073

Now to achieve the same thing as the roundtrip to esri string does, one can fix the (old, inaccurate) definition that is in DotSpatial like this:

layer.Projection = KnownCoordinateSystems.Projected.World.WebMercator; layer.Projection.GeographicInfo.Datum = KnownCoordinateSystems.Geographic.World.WGS1984.GeographicInfo.Datum;

I am not sure if everyone will agree if I change the definition (also for the authority codes) maybe i should first check what is the current EPSG database for EPSG:3857 ?

FObermaier commented 10 years ago

I think this is truely a DotSpatial.Projections issue. I recall two (roughly) related issues, http://dotspatial.codeplex.com/workitem/24852 and http://dotspatial.codeplex.com/workitem/24006.

But it is definately worth another one.

Adriaanse commented 10 years ago

https://dotspatial.codeplex.com/workitem/25176