ThinkGeo.com    |     Documentation    |     Premium Support

GeoTff progress

Hello,


I recently got in my hands some code dealing with Geotiffs from the MapSuite project I work on. The code seemed to work by reading some geotiffs but it needed some "external maths" to perform certain calcuation of distances and bearing between lat/log points. I noticed that the geotiffs were read by using the GdiPlusRasterLayer and although the geotiffs were coming with a proper .prj file, that had been replaced by .tfw(?) for them to be properly (I guess this is an ESRI World File) opened. If I was feeding the original GeoTiff with its associated proj file the code was just crashing with a nullReference exception. So I just replaced the GdiPlusRasterLayer with a GeoTiffRasterLayer and all seems to work fine. I am prety sure though that there were a few good(?) reasons for the previous choices and I am kindly scared to move forward like this. So after reading the forum here are a few questions:



        
  1. Are there any more issues with Geotiffs as discussed here

  2.     
  3. Is it still recommended to use 

        
    tiffRasterLayer.LibraryType = GeoTiffLibraryType.UnmanagedLibTiff;

        

  4.     
  5. When first used the GeoTiffRasterLayer on MapSuite Dekstop edition 4.0 and .net 4.0 I got a:  Mixed mode assembly is built against version 'v2.0.50727' of  the runtime and cannot be loaded in the 4.0 runtime without additional  configuration information. That was resolved by applying useLegacyV2RuntimeActivationPolicy="true" Is this the recommended course of action?  

  6.     
  7. Finally, are there any good reason for using Gdi layer instead of GeoTIff? 


The problem mainly for me was that I had to canibalise a perfectly valid .prj file and create a .tfw that I was not even sure if it was the correct "projection" information as it was just "given". Essentially that approach was creating "MapSuite" only geotifs as most of the other commercial applications had unpredictable behaviour with those files. 


Thank you in advnace


Yiannis




 



Yiannis, 



I answered your questions one by one below: 



1, Please use the latest version to try again, this period of time we fixed many issues or bugs in the core code. If you encounter any new problems please let us know, 



2, Yes, I recommend you to use: 



tiffRasterLayer.LibraryType = GeoTiffLibraryType.UnmanagedLibTiff; 



The different between the unmanagedLibTiff and mannagedLibTiff is that the unMannagedLibTiff is used the third C++ library and managedLibTiff is used the conversion C# libarary based on the C++ libary. So obviously, th unManagedLibTiff has higher performance and faster speed than the ManagedLibTiff.  



3, Please add the following element to your config file: 



<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0"/>
  </startup>


So your problem what you mentioned can be resolved properly, 



4, As I told you, if you want to load and render the tif or tiff files, I suggest you to use the GeoTiff to instead of the GdiPlus layer, the reason is that the GeoTiff is the professional library to load and draw the tif(tiff) file, it is only for GeoTiff file. But the GdiPlus layer can be used on GeoTiff, jpg, ecw files and so on. It is a general class for loading and drawing image files. 



Hope these answers can help you, any more questions please let me know, 



Thanks, 



Scott,



Hi Scott, 
  
 Thank you for the quick answer. When you say latest version do you mean the latest daily build? or the latest release build? If you mean the latest daily build do you think that this is safe as we are talking about production code? 
  
 Kind Regards 
 Yiannis

Yiannis, 
  
 Thanks for your post and questions. 
  
 Which version are you using against? You can get version information by calling the following API: 
 string version = WinformsMap.GetVersion(); 
  
 I think what scott suggested is trying the latest devlopment branch(4.5.0.169), we are going to have a public release before the end of next month, so you also can choose to wait until then. 
  
 Any more questions please feel free to let me know. 
  
 Thanks. 
  
 Yale 


Hi guys, 



I downloaded the latest Development built (DesktopEditionFull4.5.169.0DllPackage) and it seems to handle the Geotiffs quite well. Will report if I have any issue. The original purchased was 4.0 thus the GeoTiffLibraryType set was not available back then. 



I have one more final question kinda related to this that I would like to discuss. You see up to know I was using this GDI class and the projection I was loading was kinda "unknown" or messy to put it nice. With the new implementation (Geotiff class) I can load a projection that has the following definition: 



PROJCS["AC2182C-0_W",
GEOGCS["Latitude/Longitude.OGC.WGS_1984",
DATUM["WGS_1984",SPHEROID["WGS84",6378137,298.257223562997]],
PRIMEM["Greenwich",0],
UNIT["degrees",0.0174532925199433]],
PROJECTION["Mercator_1SP"],
PARAMETER["Central_Meridian",0],
PARAMETER["False_Easting",0],
PARAMETER["False_Northing",0],
PARAMETER["Latitude_of_Origin",0],
PARAMETER["Scale_Factor",1],
UNIT["m",1]]



If I am not mistaken, this is WGS_1984 in lat/long GCS using Mercator for Projection.  If I open a file like this on MapSuite (in this case this file is my geotiff) and I start creating Layers, I guess that the layers are all going to be adhering to this system. If I save these layers to ShapeFile is the save procedure going to create ShapeFiles of this system OR do I have to explicitly set the Projection to the shape file? 



I hope I didn't took it very far. 

Kind Regards 

Yiannis



Yiannis, 
  
 When opening a shape file and want to display it in the Mercator projection, then it has close relationship with what type of data contained in the target shape file. 
  
 Ideally, the data (lat/long) can be any projection format. Let us say if it is in WGS84 decimal degrees, then we need to set a projection from WGS84 to Mercator for the ShapeFileFeaturelayer; While when we save data, we saved the Lat/Long in the Mercator projection format, then we do not need to set any projection for the layer when using it. 
  
 Any more questions please feel free to let me know. 
  
 Thanks. 
  
 Yale 


Hi Yale, 
  
 sorry for my late response but I got somehow busy and didn’t got the chance to respond in time. I hope this does not cause any issue with the forum rules. My questions were mainly generated from the code I try to rework for the past year or so and I cannot touch a lot at once without causing a knock on effect to other things. In this code I see a lot of projection transformations between wgs84 (lat/long) to Mercator in meters and visa versa. I believe that most of those transformations are pointless since, my input data are in lat/long, my exported results are in lat/long and my geotiff layer is in WGS84 (lat/long). However I see that all transformations I mentioned are happening because every click or action on “winformsMap control” is returning meters so conversions from “clicked” meters to lat/long must take place and of course the opposite when I want to present lat/long data on the winformsmap control. I have to admit that I am mostly a software engineer rather than a GIS person but I sense that there must be a way to make the winformsmap to be in a particular projection(?) and report back lat/long instead of meters thus saving me from repetitive: 
  
 Dim projWGS84ToMercator = New Proj4Projection(4326, 3395) 'WGS84 to Marcator 
 projWGS84ToMercator.ConvertToExternalProjection etc etc etc 
  
 This feature of the software I work has a profound effect on the accuracy as well since for a lat/log point that goes in and been transformed to meters it looses some accuracy on decimal digits due to rounding and when brought back to lat/log it also looses some accuracy due to rounding. As a result my 4326 data points in my database are not exactly those depicted on the control. Thus when I perform spatial queries trying to query my database on points I select on the map, I have to work either on tolerances or on distances and select the one with the smaller  distance from the selected one. 
  
 Any help as always will be much appreciated. 
 Kind Regards 
 Yiannis

Yiannis, 
  
 Thanks for your post and questions. 
  
 Please forget about the rules in the discussion forum, you can come here and talk about your ideas and thoughts at your any convenient time. 
  
 So it would great if you could give us a concrete example such the Lat/Lon in WGS84 and what value it is expected after projected to Marcator(SRID 3395), then we will see more clearly what is the reason for this issue. 
  
 Any more questions please feel free to let me know. 
  
 Thanks. 
  
 Yale 


Hi Yale,


Thank you for the quick reponces and the interest. So here is my example with data coming from a PostGres database. A table extract follows:



    
        
            pos_lon
            pos_lat
            pos_lon / 600000.0
            pos_lat / 600000.0
            geometry
        
    
    
        
            29874862
            18039427
            49.7914366666666667
            30.0657116666666667
            "POINT(49.791435 30.065712)"
        
        
            29874851
            18039409
            49.7914183333333333
            30.0656816666666667
            "POINT(49.79142 30.065681)"
        
        
            29874842
            18039430
            49.7914033333333333
            30.0657166666666667
            "POINT(49.791405 30.065716)"
        
        
            29874851
            18039438
            49.7914183333333333
            30.0657300000000000
            "POINT(49.79142 30.065729)"
        
        
            29874852
            18039470
            49.7914200000000000
            30.0657833333333333
            "POINT(49.79142 30.065783)"
        
        
            29874887
            18039447
            49.7914783333333333
            30.0657450000000000
            "POINT(49.791477 30.065744)"
        
        
            29874883
            18039450
            49.7914716666666667
            30.0657500000000000
            "POINT(49.791473 30.06575)"
        
        
            29874858
            18039436
            49.7914300000000000
            30.0657266666666667
            "POINT(49.791431 30.065727)"
        
        
            29874884
            18039482
            49.7914733333333333
            30.0658033333333333
            "POINT(49.791473 30.065804)"
        
        
            29874898
            18039514
            49.7914966666666667
            30.0658566666666667
            "POINT(49.791496 30.065857)"
        
    

My data arrive as integer (colums 1 and 2) which are then tranformed to decimal lat/long by dividing with 600000.0. This process produce the geometry that is listed in the last column. It is this geometry that is imported in the mapsuite via a postgres layer.


Now let's assume that I want to retrieve the point at row 6 i.e POINT(49.791477 30.065744) which is depicted on my control as a "dot" and send it back to my database to be used for some other query. So I click on my control I I get the following number in meters:


5542761.86548499,3490600.17921398,0


And if I tranform them back to wgs84 I get:


POINT(49.791477 30.0657439999995)


That means that the new point I created will never match my geometry at row 6 of my table unless if I had a way to know before hand the number of decimal digits that row 6 has and round my new point accordingly. But since my decimal places  are not constant (see row 5, 6 and 7) I cannot do this.


The code that produces these numbers follows:


1. Dim projWGS84ToMercator = New Proj4Projection(4326, 3395) 'WGS84 to Marcator
2. projWGS84ToMercator.Open()
3. Dim aPoint = projWGS84ToMercator.ConvertToExternalProjection(New PointShape("POINT(49.791477 30.065744)"))
4. Console.WriteLine(aPoint.ToString())
5. Dim originalPoint As PointShape = projWGS84ToMercator.ConvertToInternalProjection(aPoint)
6. Console.WriteLine(originalPoint.ToString())
7. Console.WriteLine(originalPoint.GetWellKnownText)
8. Console.WriteLine(FormatNumber(originalPoint.Y, 6))
9. projWGS84ToMercator.Close()


At line 8 you can see that I can get the correct lon but only if I know before hand that my database point has 6 decimal places at row 6 which is of course imposible. So for the time being the best way around this issue is that I store the point row number as a property of my feature and I do my queries based on this rather than the geometry itself i.e get the rowID, go to the db, find the row, find the geometry etc etc etc. However this is not portable between databases as the rowID will vary so I still prefer to search for geometries using ST_EQUALS(geomA, geomB).


As always I may have take a completly wrong way of doing this so any suggestion is more than welcome. 


Regards


Yiannis



Yiannis, 
  
 Thanks for your post and detailed explanations, I think I now understand the issue much better now. 
  
 Basically, I think the current issue rising is because we project one Lat/Lon from WGS84 to projection 3395 and when we project it back, It will cause some minor difference, is that right? If so, I am not sure why we want to project the lat back and forth, normally, we will save the data in one projection system (like WGS84) and project them on the fly.  
  
 Let us say in the database table, we just store the Lat/Lon data inWGS84 format, when we needed, we just extract it out and convert it to projection 3395 on the fly. How about your idea? 
  
 Any more questions please feel free to let me know. 
  
 Thanks. 
  
 Yale 


Yale,  
  
 as usual I got busy for a release and I will not be able to verify this suggestion soon. Not really soon though if we are talking about the same thing. What I mean is that, my “MapClicks” are always returning meters. So by definition I must convert those meters to lat/long by opening a projection i.e New Proj4Projection(3395, 4326 ). Isn’t this going to introduce a “decimal difference” anyway? Anyway I will talk a look in the code once I get some chance and I will come back to you. I hope you don’t mind 
  
 Regards 
 Yiannis

Yiannis,


Thanks for your post and response.
 
OK, I understand that the “MapClick” are always returning meters if the data is in the 3395 projection system and I believe it definitely correct to convert to WGS84 (4326) Lat/Lon when needed. My point is why we cannot do this conversion on the fly which means only do the projection conversion when we need the WGS Lat/Lon values? Instead, we try to save the projected values in the data table in advance which may cause some precision lost.
 
Any more questions please feel free to let me know.
 
Thanks.
 
Yale