package com.aerodynelabs.map;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* A class to represent, write, and read KML files.
*
* @author Ethan Harstad
*
*/
public class KML {
private Document doc;
private Element root;
/**
* Create a KML object.
*/
public KML() {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.newDocument();
Element kml = doc.createElementNS("http://www.opengis.net/kml/2.2", "kml");
doc.appendChild(kml);
root = doc.createElement("Document");
kml.appendChild(root);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Add a placemark to this KML object.
* @param mark
*/
public void addMark(MapPoint mark) {
Element placemark = doc.createElement("Placemark");
root.appendChild(placemark);
Element name = doc.createElement("name");
name.appendChild(doc.createTextNode(mark.getName()));
placemark.appendChild(name);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
Element desc = doc.createElement("description");
desc.appendChild(doc.createTextNode(mark.getLatitude() + ", " + mark.getLongitude() + "\n" +
"Altitude: " + mark.getAltitude() + " meters\n" +
"Time: " + sdf.format(new Date(mark.getTime()))));
placemark.appendChild(desc);
Element point = doc.createElement("Point");
placemark.appendChild(point);
if(mark.getAltitude() > 0) {
Element altitudeMode = doc.createElement("altitudeMode");
altitudeMode.appendChild(doc.createTextNode("absolute"));
point.appendChild(altitudeMode);
}
Element coords = doc.createElement("coordinates");
coords.appendChild(doc.createTextNode(mark.getLongitude() + ", " + mark.getLatitude() + ", " + mark.getAltitude()));
point.appendChild(coords);
}
/**
* Add a path to this KML object.
* @param path
* @param pathName
*/
public void addPath(List<MapPoint> path, String pathName) {
Element placemark = doc.createElement("Placemark");
root.appendChild(placemark);
if(pathName != null) {
Element name = doc.createElement("name");
name.appendChild(doc.createTextNode(pathName));
placemark.appendChild(name);
}
Element lineString = doc.createElement("LineString");
placemark.appendChild(lineString);
Element extrude = doc.createElement("extrude");
extrude.appendChild(doc.createTextNode("1"));
lineString.appendChild(extrude);
Element tesselate = doc.createElement("tesselate");
tesselate.appendChild(doc.createTextNode("1"));
lineString.appendChild(tesselate);
Element altitudeMode = doc.createElement("altitudeMode");
altitudeMode.appendChild(doc.createTextNode("absolute"));
lineString.appendChild(altitudeMode);
Element coords = doc.createElement("coordinates");
String points = "";
ListIterator<MapPoint> itr = path.listIterator();
while(itr.hasNext()) {
MapPoint p = itr.next();
points += p.getLongitude() + "," + p.getLatitude() + "," + p.getAltitude() + "\n";
}
coords.appendChild(doc.createTextNode(points));
lineString.appendChild(coords);
}
/**
* Write this KML object to a file.
* @param file
* @return
*/
public boolean writeFile(File file) {
try {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource src = new DOMSource(doc);
StreamResult out = new StreamResult(file);
transformer.transform(src, out);
} catch(Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* Read the KML file into this object.
* @param file
*/
public void readFile(File file) {
// TODO read KML file
}
}