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

3.7k views Asked by At

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.

1

There are 1 answers

0
Ahmed GIS On BEST ANSWER

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