Hello,
Will anybody share some code to convert a line shapefile to KML for google Earth?
Thanks!
Hello,
Will anybody share some code to convert a line shapefile to KML for google Earth?
Thanks!
This is some code I use to create a kml files with a polygon (voting precinct) and a point (the polling place):
Private Sub CreateKML()
' open input file
Dim cdlOpen As New OpenFileDialog
Dim fileName As String = ""
'check to see if it is a shapefile
cdlOpen.Filter = "Shapefile (*.shp)|*.shp|Image Files (*.jpg)|*.jpg|Image Files (*.sid)|*.sid|All files (*.*)|*.*"
cdlOpen.ShowDialog()
fileName = Trim(cdlOpen.FileName)
If fileName = "" Then Exit Sub
Dim sf As New MapWinGIS.Shapefile
If Not sf.Open(fileName) Then
Console.WriteLine("Failed to open shapefile:" & fileName & sf.LastErrorCode.ToString)
Exit Sub
End If
' define the output file
Dim KMLFileNamePath As String = ""
'Dim cdlSaveAs As New SaveFileDialog
Dim cdlSaveAs As New FolderBrowserDialog
'cdlSaveAs.FileName = cdlOpen.FileName
'cdlSaveAs.Filter = "Shapefile (*.kml)|*.kml|All files (*.*)|*.*"
cdlSaveAs.ShowDialog()
If cdlSaveAs.SelectedPath.ToString > "" Then
KMLFileNamePath = cdlSaveAs.SelectedPath.ToString
Else
MsgBox("No output KML file designated.")
Exit Sub
End If
Dim preccol As Integer = 0 ' this needs to be a user choice at run time
Dim KMLFileName As String = ""
'Loop through the shape file, shape by shape
Dim KMLFile As System.IO.StreamWriter
Dim ShapeIndex As Integer, ConvertedShapeCount As Integer
For ShapeIndex = 0 To SF.NumShapes - 1
ToolStripStatusLabel6.Text = ShapeIndex.ToString & " of " & sf.NumShapes.ToString
'Process each shape depending on ShapeType
Select Case SF.Shape(ShapeIndex).ShapeType
Case ShpfileType.SHP_POLYGON, ShpfileType.SHP_POLYGONZ, ShpfileType.SHP_POLYGONM
Dim prec As String = sf.CellValue(preccol, ShapeIndex)
KMLFile = My.Computer.FileSystem.OpenTextFileWriter(KMLFileNamePath & "\p" & prec & ".kml", False)
KMLFile.WriteLine("<?xml version=""1.0"" encoding=""utf-8"" ?>")
KMLFile.WriteLine("<kml xmlns=""http://www.opengis.net/kml/2.2"">")
KMLFile.WriteLine("<Document id=""root_doc"">")
KMLFile.WriteLine("<Folder><name>Sarasota_Precincts_2016_region</name>")
Call AddPolygonKML(sf.Shape(ShapeIndex), KMLFile, CStr(ShapeIndex), prec)
ConvertedShapeCount = ConvertedShapeCount + 1
Dim locname As String = sf.CellValue(1, ShapeIndex)
Dim loclatlong As String = sf.CellValue(3, ShapeIndex)
If loclatlong > " " Then
KMLFile.WriteLine("<Placemark>")
KMLFile.WriteLine("<name>" & locname & "</name>")
KMLFile.WriteLine("<description>Polling place For precinct " & prec & "</description>")
KMLFile.WriteLine("<Point><coordinates>" & loclatlong & ",0</coordinates></Point>")
KMLFile.WriteLine("</Placemark>")
End If
KMLFile.WriteLine("</Folder></Document></kml>")
KMLFile.Close()
KMLCreateHTMLfile(prec, KMLFileNamePath)
Case Else
Debug.Print("Shape # " & ShapeIndex & " of type " & SF.Shape(ShapeIndex).ShapeType & " not supported yet.")
End Select
Next ShapeIndex
sf.Close()
'KMLFile.Close()
MsgBox("KML files created in '" & KMLFileNamePath)
End Sub
Private Sub KMLCreateHTMLfile(prec As String, pth As String)
Dim txt As String = "<!DOCTYPE html>"
txt &= vbCrLf & "<html>"
txt &= vbCrLf & "<head>"
txt &= vbCrLf & "<meta name=""viewport"" content=""initial-scale=1.0"">"
txt &= vbCrLf & "<meta charset=""utf-8"">"
txt &= vbCrLf & "<title>KML Layers</title>"
txt &= vbCrLf & "<style>"
txt &= vbCrLf & " /* Always set the map height explicitly to define the size of the div"
txt &= vbCrLf & " * element that contains the map. */"
txt &= vbCrLf & " #map {"
txt &= vbCrLf & " height: 100%;"
txt &= vbCrLf & " }"
txt &= vbCrLf & " /* Optional: Makes the sample page fill the window. */"
txt &= vbCrLf & " html, body {"
txt &= vbCrLf & " height: 100%;"
txt &= vbCrLf & " margin: 0;"
txt &= vbCrLf & " padding: 0;"
txt &= vbCrLf & " }"
txt &= vbCrLf & "</style>"
txt &= vbCrLf & "</head>"
txt &= vbCrLf & "<body>"
txt &= vbCrLf & " <div id=""map""></div>"
txt &= vbCrLf & "<script>"
txt &= vbCrLf & "function initMap() {"
txt &= vbCrLf & " var map = new google.maps.Map(document.getElementById('map'), {"
txt &= vbCrLf & " zoom: 11,"
txt &= vbCrLf & " center: {lat: 27.3678792, lng: -82.556743}"
txt &= vbCrLf & " });"
txt &= vbCrLf & " var ctaLayer = new google.maps.KmlLayer({"
txt &= vbCrLf & " url: 'http://www.myprecinct.com/maps/p*prec*.kml?op=10',"
txt &= vbCrLf & " map: map"
txt &= vbCrLf & " });"
txt &= vbCrLf & "}"
txt &= vbCrLf & "</script>"
txt &= vbCrLf & "<script async defer"
txt &= vbCrLf & "src=""https://maps.googleapis.com/maps/api/js?key=AIzaSyD0nHURrjFoRbw1FlwfNqqPlzQptaYje0k&callback=initMap"">"
txt &= vbCrLf & "</script>"
txt &= vbCrLf & "</body>"
txt &= vbCrLf & "</html>"
txt = txt.Replace("*prec*", prec)
Dim kmlFile As System.IO.StreamWriter
kmlFile = My.Computer.FileSystem.OpenTextFileWriter(pth & "\p" & prec & ".html", False)
kmlFile.WriteLine(txt)
kmlFile.Close()
End Sub
Private Sub AddPolygonKML(ByRef Shape As MapWinGIS.Shape,
ByRef oWrite As System.IO.StreamWriter,
ByVal ShapeID As String, prec As String)
'https://www.codeproject.com/Articles/452963/Using-MapWinGIS-to-Convert-ESRI-Shape-Files-to-Goo
' code for creating kml from shapefile
' call like this:
'Public Sub ConvertShapeFileToKML(ByVal ShapeFileName As String, _
' ByVal KMLFileName As String)
'The key parameters for defining the KML Polygon's points are:
Dim LatDeg As Double
Dim LonDeg As Double
Dim Height As Double 'Note: depending on whether this is AGL or ASL, change the KML setting below accordingly
'Create a Placemark with no label to wrap the Polygon in
oWrite.WriteLine("<Placemark>")
'Use the Shapes ID as a Name (optional)
oWrite.WriteLine("<name>Precinct " & prec & "</name>")
'Pick up the Style we wish to use (otional, but allows for nice colours etc)
oWrite.WriteLine("<styleUrl>Shape Style</styleUrl>")
'Start the Polygon KML object
oWrite.Write("<Polygon>")
'The <extrude> tag extends the line down to the ground
oWrite.Write("<extrude>1</extrude>")
'Note there are two common options for Altitude:
' "relativeToGround" for Above Ground Level
' "absolute" for Above Sea Level
' See https://developers.google.com/kml/documentation/altitudemode
oWrite.Write("<altitudeMode>relativeToGround</altitudeMode>")
'A Polygon is defined by a ring of coordinates
oWrite.Write("<outerBoundaryIs>")
oWrite.Write("<LinearRing>")
oWrite.Write("<coordinates>")
'Loop through the points one by one
Dim PointIndex As Integer
For PointIndex = 0 To Shape.numPoints - 1
'Extract the 3D coordinates for the Point
LonDeg = Shape.Point(PointIndex).x
LatDeg = Shape.Point(PointIndex).y
Height = Shape.Point(PointIndex).Z
'create KML coordinate string is <lon,lat,height> {space} <lon,lat,height>
'Note: Any space next to a ',' will create a new coordinate!
'oWrite.Write(" ")
oWrite.Write(FormatNumber(LonDeg, 6) & ",")
oWrite.Write(FormatNumber(LatDeg, 6) & ",")
oWrite.Write(FormatNumber(Height, 1) & " ")
'oWrite.WriteLine()
Next PointIndex
'Close the relevant folders in reverse order
oWrite.Write("</coordinates>")
oWrite.Write("</LinearRing>")
oWrite.Write("</outerBoundaryIs>")
oWrite.Write("</Polygon>")
oWrite.WriteLine("</Placemark>")
End Sub
An other option would be to use ogr2ogr -f KML output.kml input.shp
ogr2ogr
is implemented in MapWinGIS in the GdalUtils class as GdalVectorTranslate()
// Converting shapefile to kml:
var outputFilename = Path.Combine(Path.GetTempPath(), "translated.kml");
var options = new[]
{
"-f", "KML"
};
var gdalUtils = new GdalUtils();
if (!gdalUtils.GdalVectorTranslate(inputFilename, outputFilename, options))
{
Debug.WriteLine("GdalVectorTranslate failed: " + gdalUtils.ErrorMsg[gdalUtils.LastErrorCode] + " Detailed error: " + gdalUtils.DetailedErrorMsg);
}
Hi Jon and Paul,
Thank you two very much for the help. I figured to convert a polygon reading this link:
It is similar to Jon’s approach.
Paul’s method works very well. Question: how do we change the z? I want to use : say population, or area, income as z, where do we set it.