Search code examples
c#rendershapesesrigmap.net

How to draw ESRI shapes on top of GMap.NET output or using my Graphics object


I've got the C# app, which uses GMap.NET to render the world maps and my other data on top of that. I've got the Graphics object to render to. I also have a need to display ESRI shape files as translucent shapes on my map. How do I render that? Libraries available look like they would draw into their own Windows control. Also, when I am able to render that, how do I sync the map and shape coordinates exactly?

Thanks, D.


Solution

  • GMap.Net does not support reading ESRI shape files directly but you can use a 3rd party library like MapTools it is a .Net wrapper to the (ShapeLib) Library.

    You have to read the shape file first with the (MapTools) library and loop for each geometry (Point, Line, Polygon) and convert the geometry projection using the Proj4Net Libarary and add each geometry to its appropriate overlay on the GMapControl.

    You can download the latest version of (MapTools) from this link

    Here's a sample function to read a shape file filled with routes, it will return a list of GMapRoutes, then you have to draw them on your map.

    Public  Function ReadRoutesFromShapefile(ByVal filename As String) As List(Of GMapRoute)
    
            Dim basePath As String = Path.GetDirectoryName(filename) & AscW(Path.DirectorySeparatorChar) & Path.GetFileNameWithoutExtension(filename)
    
            If Not File.Exists(basePath & ".prj") Then
                Throw New Exception("Could not find the projection file!")
            End If
    
            'Get info from WKT-File:
            Dim wkt As String = File.ReadAllText(basePath & ".prj")
    
            Dim gcs As ICoordinateSystem = TryCast(CoordinateSystemWktReader.Parse(wkt), ICoordinateSystem)
            Dim doTransformation = Not gcs.AuthorityCode = 4326
    
            Dim wgs84 As GeographicCoordinateSystem = GeographicCoordinateSystem.WGS84
            Dim ctfac As New CoordinateTransformationFactory()
            Dim trans As ICoordinateTransformation = ctfac.CreateFromCoordinateSystems(gcs, wgs84)
    
            'Open shape-file
            Dim shapeFile As IntPtr = ShapeLib.SHPOpen(basePath, "rb")
    
            Dim numOfRecords As Integer = 0
    
            'Check type and get number of entries
            Dim shapeType As ShapeLib.ShapeType = 0
            ShapeLib.SHPGetInfo(shapeFile, numOfRecords, shapeType, Nothing, Nothing)
    
            If Not shapeType.Equals(ShapeLib.ShapeType.PolyLine) Then
                Throw New Exception("The shape type is not polyline but " & shapeType)
            End If
    
            Dim lstRoutes As New List(Of GMapRoute)(numOfRecords)
    
            'Get info from shapefile and save data:
            For i As Integer = 0 To numOfRecords - 1
                'Add all GPS-Points:
                'Get pointer to object
                Dim ptrPolyline As IntPtr = ShapeLib.SHPReadObject(shapeFile, i)
    
                'Create actual object:
                Dim polyline As New ShapeLib.SHPObject()
                Marshal.PtrToStructure(ptrPolyline, polyline)
    
                If polyline.nParts = 1 Then
                    'Get number of points and arrays of X and Y values:
                    Dim numPoints As Integer = polyline.nVertices
    
                    Dim lstpoints As New List(Of PointLatLng)(numPoints)
    
                    Dim xCoord(numPoints - 1) As Double
                    Dim yCoord(numPoints - 1) As Double
    
                    'Fill the arrays:
                    Marshal.Copy(polyline.padfX, xCoord, 0, numPoints)
                    Marshal.Copy(polyline.padfY, yCoord, 0, numPoints)
    
                    'Add all Points
                    For j As Integer = 0 To numPoints - 1
                        Dim latitude As Double = 0.0R
                        Dim longitude As Double = 0.0R
    
                        If doTransformation Then
                            'Convert from original coordinate system to wgs84
                            Dim fromPoint() As Double = {xCoord(j), yCoord(j)}
                            Dim toPoint() As Double = trans.MathTransform.Transform(fromPoint)
                            'Get point from polyline
                            longitude = toPoint(0)
                            latitude = toPoint(1)
                        Else
                            longitude = xCoord(j)
                            latitude = yCoord(j)
                        End If
    
                        lstpoints.Add(New PointLatLng(latitude, longitude))
                    Next j
    
                    lstRoutes.Add(New GMapRoute(lstpoints, "Route" & (i + 1).ToString()))
                End If
    
                polyline = Nothing
                ShapeLib.SHPDestroyObject(ptrPolyline)
            Next i
    
            ShapeLib.SHPClose(shapeFile)
    
            Return lstRoutes
        End Function