I am trying to write a script to convert Google Earth KML files to CSV files for use in Agisoft's Photoscan Pro. This script will enable users to quickly create a CSV file of GCPs (Ground Control Points) for the optimization of models so they can be more accurately overlaid in Google Earth.
How do I write this to a CSV?
<?php
$inputfile = simplexml_load_file('Points.kml');
$placemarks = $inputfile->Document->Folder->Placemark;
print "<pre>";
print_r($inputfile->Document->Folder->Placemark[0]);
foreach ($placemarks as $placemark){
$name = $placemark->name;
$longitude = $placemark->LookAt->longitude;
$latitude = $placemark->LookAt->latitude;
$altitude = $placemark->LookAt->altitude;
//print $name.",".$longitude.",".$latitude.",".$altitude;
//print "</br>";
$array = array("$name", "$longitude", "$latitude", "$altitude");
//var_dump($array);
}
?>
Example KML:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
<name>Points.kml</name>
<Style id="sn_open-diamond">
<IconStyle>
<color>ff0e12b7</color>
<scale>0.7</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/shapes/open-diamond.png</href>
</Icon>
</IconStyle>
<LabelStyle>
<color>b30e12b7</color>
</LabelStyle>
</Style>
<StyleMap id="msn_open-diamond">
<Pair>
<key>normal</key>
<styleUrl>#sn_open-diamond</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#sh_open-diamond</styleUrl>
</Pair>
</StyleMap>
<Style id="sh_open-diamond">
<IconStyle>
<color>ff0e12b7</color>
<scale>0.827273</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/shapes/open-diamond.png</href>
</Icon>
</IconStyle>
<LabelStyle>
<color>b30e12b7</color>
</LabelStyle>
</Style>
<Folder>
<name>Points</name>
<open>1</open>
<Placemark>
<name>1</name>
<LookAt>
<longitude>-81.11867631881405</longitude>
<latitude>28.58871312454101</latitude>
<altitude>0</altitude>
<heading>1.04958304488296e-13</heading>
<tilt>0</tilt>
<range>16</range>
<gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
</LookAt>
<styleUrl>#msn_open-diamond</styleUrl>
<Point>
<gx:drawOrder>1</gx:drawOrder>
<coordinates>-81.11867631881405,28.58871312454101,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>2</name>
<LookAt>
<longitude>-81.11878160604603</longitude>
<latitude>28.58868018607449</latitude>
<altitude>0</altitude>
<heading>-5.038190918931147e-05</heading>
<tilt>0</tilt>
<range>16.00000207857145</range>
<gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
</LookAt>
<styleUrl>#msn_open-diamond</styleUrl>
<Point>
<gx:drawOrder>1</gx:drawOrder>
<coordinates>-81.11878160604603,28.58868018607449,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>3</name>
<LookAt>
<longitude>-81.11889392441689</longitude>
<latitude>28.58897376333365</latitude>
<altitude>0</altitude>
<heading>-5.676793149912727e-05</heading>
<tilt>0</tilt>
<range>16</range>
<gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
</LookAt>
<styleUrl>#msn_open-diamond</styleUrl>
<Point>
<gx:drawOrder>1</gx:drawOrder>
<coordinates>-81.11889392441689,28.58897376333365,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>4</name>
<LookAt>
<longitude>-81.11879074625233</longitude>
<latitude>28.58900436190265</latitude>
<altitude>0</altitude>
<heading>-7.3948102396262e-06</heading>
<tilt>0</tilt>
<range>16.00000167331963</range>
<gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
</LookAt>
<styleUrl>#msn_open-diamond</styleUrl>
<Point>
<gx:drawOrder>1</gx:drawOrder>
<coordinates>-81.11879074625233,28.58900436190265,0</coordinates>
</Point>
</Placemark>
</Folder>
</Document>
</kml>
Example CSV:
# Label,X,Y,Z
1,-81.11867632,28.58871312,0
2,-81.11878161,28.58868019,0
3,-81.11889392,28.58897376,0
simplexml_load_file will return SimpleXMLElement class, so you should use method from this class to access to xml elements.
For example children method - http://www.php.net/manual/en/simplexmlelement.children.php
In case you do need only coordinate of the points and their labels do not matter, I suggest that you can write a simple Python script for PhotoScan that will get the path to the kml file and then line by line search for <coordinates> text, if it is in the given line then you can just extract coordinates from the string and even create new marker with applied coordinates.
Here is a sample code (should be save as .py file and started through Run Script dialog in PhotoScan Pro) that asks for a kml file and writes into Console pane x,y,z coordinates of the points extracted:
import PhotoScan
path = PhotoScan.app.getOpenFileName("Specify KML file:")
file = open(path, "rt")
feof = False
counter = 0
while not feof:
str = file.readline()
if not len(str):
feof = True
break
if "<coordinates>" in str:
counter += 1
str = str.split("<coordinates>", 1)[1]
str = str.rsplit("</coordinates>", 1)[0]
(x, y, z) = str.split(",")
print(x, y, z)
file.close()
You can modify this code if you wish to save the coordinates into .txt file (using counter variable as GCP label, for example). But I think it should not be hard to import these values dirrectly to the Ground Control pane.