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 } }