ThinkGeo.com    |     Documentation    |     Premium Support

Shapefile Projection not correct

Hello,


I display shapefiles on GoogleMaps-Layer. We use EPSG 31467 to project the shapefile on GoogelMaps-Layer (EPSG 900913).


But as you can see on the attached picture the shape is not on the right position. It looks like the x-position of shape is right but the y-position has an offset.


Maybe I use wrong projection. Any ideas?


Thomas



1698-ALK.ZIP (235 KB)

 I used the shapefile you attached and projected it to Google Map with the EPSG 31467 projection. The result I have is similar to what you described (see attached screen shot). My suspicion is that the projection of origin (EPSG 31467 DHDN / 3-degree Gauss-Fruger zone 3) is not the correct one.  spatialreference.org/ref/epsg/31467/


 I tried to find some projection information in the attached files but I could not find anything related to projection. I recommendation is that you contact the providers of the shapefile and ask them what is the exact projection used for that shapefile. Thank you.



 



Hello Val, 
  
 I think the SRID is correct. Maybe the original SRID was EPSG 31463 but it is deprecated and we have to use EPSG 31467. 
  
 I wonder on your result. If you look on the picture I attached you can see that my offset is still higher although I use the same projection parameters. Your result is similar to the correct result. 
  
 Thomas 
  


Hello Val,


found an layer file with additional information on the shapefile. Maybe you can extract SRID from layer file.


Thanks


Thomas



1710-ALK.zip (15.4 KB)

 The attached file is a lyr file that is an ESRI standard only readable with ARCGIS and I don't have that installed on my machine.


I was still able to do some progress with your projection issue and apply some custom parameters to have the layer lying up more precisely over Google Map. I slightly modified the x and y offset of the original string for EPSG 31467  by playing around with those numbers. As you can see in the screen shot, it is an imperfect solution until you find out exactly from your data provider what the real projection is.



You can see the code I used below to get that result:


 



ShapeFileFeatureLayer myLayer = new ShapeFileFeatureLayer(@"..\..\Data\alk-flurstueck-objekt.shp");
            myLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            myLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(0,GeoColor.StandardColors.Red), GeoColor.StandardColors.Black,2);

            Proj4Projection proj4 = new Proj4Projection();
            proj4.InternalProjectionParametersString = "+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500075 +y_0=110 +ellps=bessel +datum=potsdam +units=m +no_defs"; 
            proj4.ExternalProjectionParametersString = Proj4Projection.GetGoogleMapParametersString();
            myLayer.FeatureSource.Projection = proj4;
           

            LayerOverlay staticOverlay = new LayerOverlay();
            staticOverlay.Layers.Add("MyLayer", myLayer);
            winformsMap1.Overlays.Add(staticOverlay);


Hello Val,


if you open the layerfile with an text editor you can see that the shapefile use ESRI-Projection string.


# Germany Zone 3

<31493> +proj=tmerc +lat_0=0 +lon_0=9 +k=1.000000 +x_0=3500000 +y_0=0 +ellps=bessel +units=m  no_defs <>


I changed my projection parameters to 31493 but the layers still don't fit to each other.



Any ideas?



As I explained in my previous posts, you need to find out on your side the exact projection parameters for your shapefiles in order to have them  line up correctly with Google Map. I demonstrated that Map Suite offers all the tools necessary for your projection needs. And for that, I used some custom X and Y offsets. There are literally thousands of fifferent projections used in the world and the ThinkGeo crew cannot be familiar with all of them. It is ultimately your responsability to know your data and what projection it is using.

Hello ThinkGeo-Team, 
  
 after some time I come back to this thread and reopen it because I did not fix it until now. 
  
 Over the last month you implemented many web based map types e.g. Google, Bing, Yahoo, Open Streetmap. Our customers are interested on using those map types as background layers but we stay in Germany and many of the data are projected in Gauss-Kruger zone 3. As you can see in my previous post in proj4 i have to use EPSG:31467 or ESRI:31463 as internal projection parameter. 
  
 If I project my Gauss-Kruger data on layers they are in WGS84 everything is allright. But if I project it to EPSG 900913 I get the position offset as mentioned in my previous posts. So I can’t use any of the web based map types at the moment. 
  
 It looks like the reprojection from Gauss-Kruger to EPSG 900913 did not work correct. Please help to fix my problem. 
  
 Thomas 
  


Thank you for giving us that additional information. I let you know that we will work on your issue first thing tomorrow morning.

With the code below, I have your shapefile matching pretty well with GoogleMap as you can see in the screen shot. The reason, I think, it is not matching perfectly is due to some inaccuracies within the shapefile itself, rather than in the projection operation. I hope this is going to help.



 



winformsMap1.MapUnit = GeographyUnit.Meter;

ShapeFileFeatureLayer myLayer = new ShapeFileFeatureLayer(@"..\..\Data\alk-flurstueck-objekt.shp");
myLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
myLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(0, GeoColor.StandardColors.Red), GeoColor.StandardColors.Black, 2);

ManagedProj4Projection proj4 = new ManagedProj4Projection();
proj4.InternalProjectionParameters = "+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500075 +y_0=110 +ellps=bessel +datum=potsdam +units=m +no_defs";
proj4.ExternalProjectionParameters = ManagedProj4Projection.GetGoogleMapParameters();
myLayer.FeatureSource.Projection = proj4;


Hello Val, 
  
 thanks for information. I remembered that you have manipulated the projection parameters for the Gauss-Krüger SRID. I understand that I can do that but I don’t think this is the right way. I think the data in the alk-flurstueck-shapefile are correct because we have many other files (.shp, MapInfo .mid, .tif …) in Gauss-Krüger projection and if we display them together they match perfectly without some inaccuracies. They also match with other files if we project them to WGS84. Only if we project them to EPSG 900913  they did have an offset. 
  
 I think the proj4 result is not correct. 
  
 Thanks Thomas

Can you show us some screen shots of the map where you go from Gauss-Kruger projection to EPSG 900913 (Google Map projection) using some other tools? And can you tell us what tool you are using to get the correct result to go from Gauss-Kruger to Google Map projection. With that information, we will look on how to fix Proj4  for that particular problem. Thank you.

Sorry Val, 
  
 maybe I was not clear enough. I think the shapefiles are correct because we can reproject them to other SRID e.g. WGS84  and display them over other shapefile layers they are native in WGS84 projection. If we do this we can see they match without some inaccuracies. 
  
 Thomas

I am not questioning the shapefiles. I am just asking if you managed to reproject your shapefiles to the Google Map projection. If yes, I would like to know using what tool so that we can compare it with proj4. That was all I was asking in my previous post.

 


I have one suggestion. The problem might be in the reprojection operation of going from Gauss-Kruger to Google Map projection directly in the Proj4 library. If, as you say, it projects directly to WSG84, you could save the shapefiles to that projection and then do the projection operation from WGS84 to Google Map. I know that this reprojection operation works, we do it all the time. There is a Code Community project, Save To Projection, that shows how to do that: code.thinkgeo.com/projects/show/savetoprojection.


 


 



Val,


at the moment we can not reproject our shapefiles to the Google map projection and we havent tried if any other tool can do that.


Your suggestion to save the shapefile to WGS84 is very hard to implement in our product. As I mentioned  above we have many customers with shapefiles in Gauss Krüger projection and we can not reproject all the files and store them in the file system. Gauss Krüger is the standard projection for the data our customers can edit and store in the database.


I would prefer if we could manage this in managedProj4Projection class.


Thomas



A possible solution would be to create a custom projection class where the reprojection from Grauss Kruger to Google map is done in two steps. The first step is to go from Grauss Kruger to WGS84 and the first step is to go from WGS84 to Google Map. To build such a custom projection class, you can look at the Code Community project Pacific Rim code.thinkgeo.com/projects/show/pacificrim


 You can replace the code in ProjectCore to call the Proj4 classes. If you have some doubts on how to exactely proceed, let us know and we will write the projection class for you.


 



Hello Val, 
  
 it would be great if you can send me the code for projection class. 
  
 Thanks Thomas

Ok, I will send you the code tomorrow.

You can try the projection code below. Using that custom projection, the result is slightly different than going directly from Gass Kruger to Google. In that custom projection, it is done in two steps using WGS84 as the pivot projection.


 



    class CustomProjection : Projection, IDisposable
    {
        private ManagedProj4Projection GaussKrugerToWGS84proj4 = new ManagedProj4Projection();
        private ManagedProj4Projection WGS84ToGoogleprog4 = new ManagedProj4Projection();

        public CustomProjection()
            : base()
        {
            GaussKrugerToWGS84proj4.InternalProjectionParameters = "+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500075 +y_0=110 +ellps=bessel +datum=potsdam +units=m +no_defs";
            GaussKrugerToWGS84proj4.ExternalProjectionParameters = ManagedProj4Projection.GetEpsgParameters(4326);

            WGS84ToGoogleprog4.InternalProjectionParameters = ManagedProj4Projection.GetEpsgParameters(4326);
            WGS84ToGoogleprog4.ExternalProjectionParameters = ManagedProj4Projection.GetGoogleMapParameters();
        }

        protected override Vertex[] ConvertToExternalProjectionCore(double[] x, double[] y)
        {
            Vertex[] vertices = new Vertex[x.Length];

            GaussKrugerToWGS84proj4.Open();
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = GaussKrugerToWGS84proj4.ConvertToExternalProjection(x[i], y[i]);
            }
            GaussKrugerToWGS84proj4.Close();

            WGS84ToGoogleprog4.Open();
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = WGS84ToGoogleprog4.ConvertToExternalProjection(vertices[i].X, vertices[i].Y);
            }
            WGS84ToGoogleprog4.Close();

            return vertices;
        }

        protected override Vertex[] ConvertToInternalProjectionCore(double[] x, double[] y)
        {
             Vertex[] vertices = new Vertex[x.Length];

            WGS84ToGoogleprog4.Open();
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = WGS84ToGoogleprog4.ConvertToInternalProjection(x[i], y[i]);
            }
            WGS84ToGoogleprog4.Close();

            GaussKrugerToWGS84proj4.Open();
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = GaussKrugerToWGS84proj4.ConvertToExternalProjection(x[i], y[i]);
            }
            GaussKrugerToWGS84proj4.Close();

            return vertices;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            Close();
        }
    }


Hello Val,


thanks for sample code. There was a little bug in the code, but after changig the line you can see in the attached code the projection class works fine. As you can see in the screenshot there are only some parts they show some inaccuracies.


As conclusion of our test I think the projection algorithm of Proj4Projection and ManagedProj4Projection class from GaussKruger (EPSG 31467) to Google works not correct. I don't know whats going on in Projection class and how you project data between different projections but I think if you compare the original projection code and the version we do it in our custom projection class you would be able to find the bug.


I would prefer a fixed version of ManagedProj4Projection class because our custom class has to do two projection steps. I think this is not the fastest solution.


Thomas



 



        protected override Vertex[] ConvertToInternalProjectionCore(double[] x, double[] y)
        {
             Vertex[] vertices = new Vertex[x.Length];

            WGS84ToGoogleprog4.Open();
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = WGS84ToGoogleprog4.ConvertToInternalProjection(x[i], y[i]);
            }
            WGS84ToGoogleprog4.Close();

            GaussKrugerToWGS84proj4.Open();
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = GaussKrugerToWGS84proj4.ConvertToInternalProjection(vertices[i].X, vertices[i].Y);
            }
            GaussKrugerToWGS84proj4.Close();

            return vertices;
        }