ThinkGeo.com    |     Documentation    |     Premium Support

Projections

Hi everybody and excuse me for my ignorance but I have developed a mapping application using the WorldMap kit and Desktop edition V3.0  I have all maps in decimal degrees but now I need to load some shapefiles that are projected in UTM, I believe Zone 14.


What do I need to do to be able to render these shapefiles?  I believe I need to use the Proj4JProjection class but what do I supply it for projections?  And, I am also guessing that I need to convert all my maps to meters as well?  If I change my maps to meters does that also mean that when I create a new Vertex it needs to be in something other than decimal degrees?


This GIS stuff is all still fairly new to me although I have learned alot but it is pretty obvious that I have alot to learn yet.


Thanks.


Curtis



 


Hi Curtis,
 
The map unit of our Desktop edition map takes effect to all overlays and layers. So you must unify your WorldMap kit and the UTM shapefiles.
Here are two ways to do that:


        
  • Keep world map kit the same as before, and assign an instance proj4 projection to your shape file layer, set internal projection number or string according to your UTM, set external projection number to 4326, because world map kit is epsg4326. Set map unit to decimal degree

  •     
  • Attach projection to all layers of world map kit, switch internal and external number, and let it from 4236 to specific UTM projection number. This time set map unit to meter.


 
First of all, you must know which projection of your data, such as EPSG number, our world map kit is 4326, Google map is 900913. And then you can use proj4 projection to display what you want.
 
If you have any questions, please let me know.
 
Thanks.
 
James

1 Like

I'm a customer, so this will be far short of a true ThinkGeo reponse, but teaching is the best way of learning, so here goes. 



We use lots of projection stuff. The easiest that I have found is to use the EPSG Code integers as the SRID parameters on the Proj4Projection. SRID = Spatial Reference ID. 



I'm assuming when you say UTM Zone 14, that you really mean UTM Zone 14 North, based upon the NAD 83 datum (North American datum of 1983). This is the most common format for projected data in North America. Note that you may bump into NAD27 data (North Amerian Datum of 1927), which has a different set of EPSG codes. 



So, the EPSG code for a NAD83 UTM projection is 26900 + the UTM Zone Number. There are 60 zones, 6 degrees wide covering the world. I think NAD83 is defined for zones 7 through 18 or something like that... 



The way to find your zone from a longitude is: zone = (int)((lon + 180.0) / 6.0) + 1; 



So, UTM Zone 14 North is data from 96 to 102 degrees West, North of the equator, and is EPSGCode = 26914. 



The constructor on the ProjNet takes two SRID parameters (as one of the options). The internal projection, and the external projection. Internal means "what is the native projection of my data". External means "what do I want to convert to". Normal Lon/Lat data is expressed in WGS84 Geodetic datum, and the EPSGCode for it is 4326. So, your constructor is: 



Proj4Projection p = new Proj4Projection(4326, 26914) 



If you want to convert native Lon/Lat to projected. Of course, it is the reverse if you want to to "unproject" your projected data to the lon/lat of the WorldMapKit. 



I think you are right. You will typically want to project your WorkMapKit data to zone 14. And, yes, when you get "world" tracking coordinates, etc, they will be projected. If you want to convert those projected coordinates back to lon/lat, you just call: 



BaseShape projectedShape = projection.ConvertToInternal(trackedShape). 



We provided a modified copy of the world map kit to the support team for inclusion on the code project page. It was a single layer that encapsulated the entire world map kit as a multi layer derivation. It had a projection property on it, and would iterate through hundreds of world map kit layers setting the projection. I had support for other things, too. I don't think it ever got posted, but you might ask support for it. 



Hope this helps, rather than muddles. 



 



Thanks Ted, I appreciate you give us an excellent speech. 
  
 James 


Hi Ted,


That definitely helps clear the water quite a bit.  I did a bunch of reading last night as well after posting and it is starting to make sense now.  I should be on my way hopefully now.


Thanks.


Curtis



Curtis, 
  
 It’s awesome you are on your way!  
 Thank Ted’s help and hope you contribute your knowledge of projection more in the future. 
  
 James 


Thanks Ted for your detailed explanation. 
  
 Curtis Thanks for letting us know your status. Any more questions just feel free to let me know, we definitely will try our best to help you. 
  
 Thanks. 
  
 Yale 


Hello again,


I finally got back to this and started to throw a sample together and I have a feeling I am missing something.  I tried searching but there is not much information on here in regards to projections.  Anyway, I have attached the sample code below but what I am doing is loading a simple map which loads ok but when I try and zoom in I get an exception:  {"The input double value is out of range.\r\nParameter name: maxX"}


Here is the code from the form load and this is all that is in the form at this point.  What am I missing or doing wrong here?


Thanks.


Curtis


 




private void GraderTest_Load(object sender, EventArgs e) {
RenderMap renderMaps = new RenderMap("C:\\WorldMapKit");
renderMaps.LoadLayers(mapControl.StaticOverlay.Layers, mapControl.DynamicOverlay.Layers);
mapControl.MapUnit = GeographyUnit.DecimalDegree;

// Render the Mahnomen layer.
LayerOverlay overlay = new LayerOverlay();
mapControl.Overlays.Add("graderOverlay", overlay);

Proj4Projection projection = new Proj4Projection(26915, 4326);
ShapeFileFeatureLayer layer = new ShapeFileFeatureLayer(Application.StartupPath + "\\Mahnomen_Roads.shp", Application.StartupPath + "\\Mahnomen_Roads.shx", ShapeFileReadWriteMode.ReadOnly);
projection.Open();
layer.FeatureSource.Projection = projection;

GeoPen innerPen = new GeoPen(GeoColor.StandardColors.Red, 4);
innerPen.SetLineCap(DrawingLineCap.Round, DrawingLineCap.Round, GeoDashCap.Round);
GeoPen outerPen = new GeoPen(GeoColor.StandardColors.Black, 6);
outerPen.SetLineCap(DrawingLineCap.Round, DrawingLineCap.Round, GeoDashCap.Round);

layer.Name = "ProjLayer";
layer.ZoomLevelSet.ZoomLevel01.IsActive = true;
layer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = new LineStyle(outerPen, innerPen);
overlay.Layers.Add("projLayer", layer);

mapControl.CurrentExtent = RenderMap.DefaultExtent;
mapControl.Refresh();
}


 


Curtis,
 
Could you try a small sample application without worldMapKit included to see if this problem still exists? If it exits, could you send us your data for test?

   mapControl.MapUnit = GeographyUnit.DecimalDegree;
 
            // Render the Mahnomen layer.
            LayerOverlay overlay = new LayerOverlay();
            mapControl.Overlays.Add("graderOverlay", overlay);
 
            Proj4Projection projection = new Proj4Projection(26915, 4326);
            ShapeFileFeatureLayer layer = new ShapeFileFeatureLayer(Application.StartupPath + "\\Mahnomen_Roads.shp", Application.StartupPath + "\\Mahnomen_Roads.shx", ShapeFileReadWriteMode.ReadOnly);
            projection.Open();
            layer.FeatureSource.Projection = projection;
 
            GeoPen innerPen = new GeoPen(GeoColor.StandardColors.Red, 4);
            innerPen.SetLineCap(DrawingLineCap.Round, DrawingLineCap.Round, GeoDashCap.Round);
            GeoPen outerPen = new GeoPen(GeoColor.StandardColors.Black, 6);
            outerPen.SetLineCap(DrawingLineCap.Round, DrawingLineCap.Round, GeoDashCap.Round);
 
            layer.Name = "ProjLayer";
            layer.ZoomLevelSet.ZoomLevel01.IsActive = true;
            layer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = new LineStyle(outerPen, innerPen);
            overlay.Layers.Add("projLayer", layer);
 
            mapControl.CurrentExtent = new RectangleShape(-139.2, 92.4, 120.9, -93.2);
            mapControl.Refresh();
 

 
Let me know if any more questions.
 
Thanks.
 
Yale

Hi Yale,


With this test application I don't get any exceptions but I get absolutely nothing drawing on the map either.  It is like the rendering is just not happening.  Where should I send the code to?


Thanks.


Curtis



Curtis,


Could you send the code attached with data to our support(support@thinkgeo.com) and ask him to forword it to Yale?
 
Also, could you paste out the version information by following code:

string version = WinformsMap.GetVersion();

 
Any more questions just feel free to let me know.
 
Thanks.
 
Yale

Curtis,


I am sorry that I made a very obvious mistake in my previous post, did not setting the current extent right.
 
Please try following code with correct extent set, it should works.

  winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
 
            // Render the Mahnomen layer.
            LayerOverlay overlay = new LayerOverlay();
            winformsMap1.Overlays.Add("graderOverlay", overlay);
 
            Proj4Projection projection = new Proj4Projection(26915, 4326);
            ShapeFileFeatureLayer layer = new ShapeFileFeatureLayer(@"C:\Mahnomen_Roads.shp", ShapeFileReadWriteMode.ReadOnly);
            projection.Open();
            layer.FeatureSource.Projection = projection;
 
            GeoPen innerPen = new GeoPen(GeoColor.StandardColors.Red, 4);
            innerPen.SetLineCap(DrawingLineCap.Round, DrawingLineCap.Round, GeoDashCap.Round);
            GeoPen outerPen = new GeoPen(GeoColor.StandardColors.Black, 6);
            outerPen.SetLineCap(DrawingLineCap.Round, DrawingLineCap.Round, GeoDashCap.Round);
 
            layer.Name = "ProjLayer";
            layer.ZoomLevelSet.ZoomLevel01.IsActive = true;
            layer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.Canal1;//new LineStyle(outerPen, innerPen);
            overlay.Layers.Add("projLayer", layer);
 
            //winformsMap1.CurrentExtent = new RectangleShape(-139.2, 92.4, 120.9, -93.2);
            layer.Open();
            winformsMap1.CurrentExtent = layer.GetBoundingBox();
            layer.Close();
 
            winformsMap1.Refresh();

 
Any more questions just feel free to let me know.
 
Thanks.
 
Yale
 

Hi Yale,


Thanks and that worked perfectly.


Now, another question for somebody.  I am trying to render shapefiles projected in NAD_1983_StatePlane_North_Dakota_South_FIPS_3302_Feet, I found the SRID as 102721 and I believe that to be the correct SRID.  However, I am unable to get this to render.  Is it possible that Proj4Projection does not support this projection?


Thanks.


Curtis



Curtis,


Try following, find it Esri instead of Epsg:

string str = Proj4Projection.GetEsriParametersString(102721);

 
Any more qeustions just feel free to let me know.
 
Thanks.
 
Yale