/* * Copyright (C) 2014 Alec Dhuse * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package co.foldingmap.mapImportExport; import co.foldingmap.map.vector.LatLonBox; import co.foldingmap.map.vector.NodeMap; import co.foldingmap.map.vector.VectorObject; import co.foldingmap.map.vector.Coordinate; import co.foldingmap.map.vector.MapPoint; import co.foldingmap.map.vector.LineString; import co.foldingmap.map.vector.Polygon; import co.foldingmap.Logger; import co.foldingmap.dataStructures.PropertyValuePair; import co.foldingmap.map.DigitalMap; import co.foldingmap.map.MapObject; import co.foldingmap.xml.XMLTag; import co.foldingmap.xml.XmlOutput; import co.foldingmap.xml.XmlWriter; import java.io.File; import java.util.ArrayList; /** * * @author Alec */ public class OsmExporter { private DigitalMap mapData; public OsmExporter(DigitalMap mapData) { this.mapData = mapData; } public void export(File osmFile) { ArrayList<MapPoint> points; ArrayList<VectorObject> objects; XmlWriter xmlOut; objects = new ArrayList<VectorObject>(); points = new ArrayList<MapPoint>(); xmlOut = new XmlWriter(osmFile); //Get a list of all the MapPoints and other objects for (MapObject object: mapData.getAllMapObjects()) { if (object instanceof MapPoint) { points.add((MapPoint) object); } else if (object instanceof VectorObject) { objects.add((VectorObject) object); } } //write header info xmlOut.writeText("<?xml version='1.0' encoding='UTF-8'?>\n"); xmlOut.writeText("<osm version='0.6' generator='FoldingMap'>\n"); xmlOut.increaseIndent(); //write bounds xmlOut.writeText(getOsmBoundsString(mapData.getBoundary())); //Export Nodes exportNodes(xmlOut, points); //Export Ways exportWays(xmlOut, objects); //Export Relations xmlOut.decreaseIndent(); xmlOut.writeText("</osm>\n"); xmlOut.closeFile(); } private void exportNodes(XmlOutput xmlOut, ArrayList<MapPoint> points) { Coordinate coordinate; MapPoint point; NodeMap nodeMap; nodeMap = mapData.getCoordinateSet(); for (int i = 0; i < nodeMap.size(); i++) { coordinate = nodeMap.getFromIndex(i); point = pointUsingCoordinate(points, coordinate); if (coordinate.getID() > 0) { xmlOut.writeText(getNodeOpenTag(coordinate)); xmlOut.increaseIndent(); xmlOut.writeText(xmlOut.getIndent()); xmlOut.writeText(getTagString("ele", coordinate.getAltitude())); if (point != null) { xmlOut.writeText(getTagString("name", XMLTag.getSafeText(point.getName()) )); //Style xmlOut.writeText(xmlOut.getIndent()); xmlOut.writeText(getStyleTags(point)); for (PropertyValuePair pvp: point.getAllCustomData()) { xmlOut.writeText(xmlOut.getIndent()); xmlOut.writeText(getTagString(pvp.getProperty(), pvp.getValue())); } } xmlOut.decreaseIndent(); xmlOut.writeText("</node>\n"); } } } private void exportWays(XmlOutput xmlOut, ArrayList<VectorObject> objects) { long wayID, wayCounter; String value; wayCounter = 1; for (VectorObject object: objects) { //If the object has an OSM field use that for the way ID, if not increment from 1. value = object.getCustomDataFieldValue("OsmID"); if (value != null) { wayID = Long.parseLong(value); } else { wayID = wayCounter; wayCounter++; } xmlOut.writeText(getWayTagOpen(wayID, object.getTimestamp())); xmlOut.increaseIndent(); //output node IDs used in this way for (Coordinate c: object.getCoordinateList()) { xmlOut.writeText(xmlOut.getIndent()); xmlOut.writeText("<nd ref='-" + c.getID() + "' />\n"); } //If polygon close way if (object instanceof Polygon) { xmlOut.writeText(xmlOut.getIndent()); xmlOut.writeText("<nd ref='-" + object.getCoordinateList().get(0).getID() + "' />\n"); } //name xmlOut.writeText(getTagString("name", XMLTag.getSafeText(object.getName()))); //Style xmlOut.writeText(xmlOut.getIndent()); xmlOut.writeText(getStyleTags(object)); //output properties for (PropertyValuePair pvp: object.getAllCustomData()) { xmlOut.writeText(xmlOut.getIndent()); xmlOut.writeText(getTagString(pvp.getProperty(), pvp.getValue())); } xmlOut.decreaseIndent(); xmlOut.writeText("</way>\n"); } } /** * Returns a string representing the open of the Node tag. * * @param c * @return */ private String getNodeOpenTag(Coordinate c) { StringBuilder sb; sb = new StringBuilder(); try { sb.append("<node id='-"); sb.append(c.getID()); sb.append("' timestamp='"); sb.append(c.getTimestamp()); sb.append("' visible='true' "); sb.append("lat='"); sb.append(c.getLatitude()); sb.append("' lon='"); sb.append(c.getLongitude()); sb.append("' version='1'"); sb.append(">\n"); } catch (Exception e) { Logger.log(Logger.ERR, "Error in OsmExporter.getNodeOpenTag(Coordinate) - " + e); } return sb.toString(); } private String getOsmBoundsString(LatLonBox bounds) { StringBuilder sb = new StringBuilder(); sb.append("<bounds minlat='"); sb.append(bounds.getSouth()); sb.append("' minlon='"); sb.append(bounds.getWest()); sb.append("' maxlat='"); sb.append(bounds.getNorth()); sb.append("' maxlon='"); sb.append(bounds.getEast()); sb.append("' />\n"); return sb.toString(); } private String getStyleTags(VectorObject object) { String objectClass; StringBuilder sb; objectClass = object.getObjectClass(); sb = new StringBuilder(); if (object instanceof MapPoint) { if (objectClass.equalsIgnoreCase("Airport")) { sb.append(getTagString("aeroway", "aerodrome")); } else if (objectClass.equalsIgnoreCase("Amenity")) { sb.append(getTagString("amenity", "yes")); } else if (objectClass.equalsIgnoreCase("Antenna")) { sb.append(getTagString("man_made", "antenna")); } else if (objectClass.equalsIgnoreCase("Art Gallery")) { sb.append(getTagString("amenity", "arts_centre")); } else if (objectClass.equalsIgnoreCase("Bank")) { sb.append(getTagString("amenity", "bank")); } else if (objectClass.equalsIgnoreCase("Bar")) { sb.append(getTagString("amenity", "bar")); } else if (objectClass.equalsIgnoreCase("Bridge")) { sb.append(getTagString("bridge", "yes")); } else if (objectClass.equalsIgnoreCase("Building")) { sb.append(getTagString("building", "yes")); } else if (objectClass.equalsIgnoreCase("Bus Station")) { sb.append(getTagString("amenity", "bus_station")); } else if (objectClass.equalsIgnoreCase("Cafe")) { sb.append(getTagString("amenity", "cafe")); } else if (objectClass.equalsIgnoreCase("Camp Site")) { sb.append(getTagString("tourism", "camp_site")); } else if (objectClass.equalsIgnoreCase("Cemetery")) { sb.append(getTagString("amenity", "grave_yard")); } else if (objectClass.equalsIgnoreCase("Clinic")) { sb.append(getTagString("amenity", "Clinic")); } else if (objectClass.equalsIgnoreCase("Cinema")) { sb.append(getTagString("amenity", "cinema")); } else if (objectClass.equalsIgnoreCase("City")) { sb.append(getTagString("place", "city")); } else if (objectClass.equalsIgnoreCase("Place - Town")) { sb.append(getTagString("place", "town")); } else if (objectClass.equalsIgnoreCase("Place - Suburb")) { sb.append(getTagString("place", "suburb")); } else if (objectClass.equalsIgnoreCase("Place - Village")) { sb.append(getTagString("place", "village")); } else if (objectClass.equalsIgnoreCase("Courthouse")) { sb.append(getTagString("amenity", "courthouse")); } else if (objectClass.equalsIgnoreCase("Cyber Café")) { sb.append(getTagString("internet_access", "terminal")); } else if (objectClass.equalsIgnoreCase("Dangerous Area")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Embassy")) { sb.append(getTagString("amenity", "embassy")); } else if (objectClass.equalsIgnoreCase("Ferry")) { sb.append(getTagString("amenity", "ferry_terminal")); } else if (objectClass.equalsIgnoreCase("Fire Station")) { sb.append(getTagString("amenity", "fire_station")); } else if (objectClass.equalsIgnoreCase("Forest")) { sb.append(getTagString("landuse", "forest")); } else if (objectClass.equalsIgnoreCase("Football")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Garden")) { sb.append(getTagString("leisure", "garden")); } else if (objectClass.equalsIgnoreCase("Gas Station")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Golf")) { sb.append(getTagString("leisure", "golf_course")); } else if (objectClass.equalsIgnoreCase("Grocery")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Harbor")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Heliport")) { sb.append(getTagString("aeroway", "helipad")); } else if (objectClass.equalsIgnoreCase("Hill")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Hospital")) { sb.append(getTagString("amenity", "hospital")); } else if (objectClass.equalsIgnoreCase("Hotel")) { sb.append(getTagString("tourism", "hotel")); } else if (objectClass.equalsIgnoreCase("Industrial")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Library")) { sb.append(getTagString("amenity", "library")); } else if (objectClass.equalsIgnoreCase("Lookout")) { sb.append(getTagString("tourism", "viewpoint")); } else if (objectClass.equalsIgnoreCase("Marker")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Memorial")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Mine")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Minefield")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Moto Taxi")) { sb.append(getTagString("amenity", "taxi")); sb.append(getTagString("motorcycle", "yes")); } else if (objectClass.equalsIgnoreCase("Mountain Peak")) { sb.append(getTagString("natural", "peak")); } else if (objectClass.equalsIgnoreCase("NGO Office")) { sb.append(getTagString("office", "ngo")); } else if (objectClass.equalsIgnoreCase("Park")) { sb.append(getTagString("leisure", "park")); } else if (objectClass.equalsIgnoreCase("Parking")) { sb.append(getTagString("amenity", "parking")); } else if (objectClass.equalsIgnoreCase("Parking Garage")) { sb.append(getTagString("amenity", "parking")); } else if (objectClass.equalsIgnoreCase("Pharmacy")) { sb.append(getTagString("amenity", "pharmacy")); } else if (objectClass.equalsIgnoreCase("Phone")) { sb.append(getTagString("amenity", "telephone")); } else if (objectClass.equalsIgnoreCase("Place Of Worship")) { sb.append(getTagString("amenity", "place_of_worship")); } else if (objectClass.equalsIgnoreCase("Place Of Worship - Christian")) { sb.append(getTagString("amenity", "place_of_worship")); sb.append(getTagString("religion", "christian")); } else if (objectClass.equalsIgnoreCase("Place Of Worship - Hindu")) { sb.append(getTagString("amenity", "place_of_worship")); sb.append(getTagString("religion", "hindu")); } else if (objectClass.equalsIgnoreCase("Place Of Worship - Islam")) { sb.append(getTagString("amenity", "place_of_worship")); sb.append(getTagString("religion", "muslim")); } else if (objectClass.equalsIgnoreCase("Place Of Worship - Jewish")) { sb.append(getTagString("amenity", "place_of_worship")); sb.append(getTagString("religion", "jewish")); } else if (objectClass.equalsIgnoreCase("Police Station")) { sb.append(getTagString("amenity", "police")); } else if (objectClass.equalsIgnoreCase("Prison")) { sb.append(getTagString("amenity", "prison")); } else if (objectClass.equalsIgnoreCase("Post Office")) { sb.append(getTagString("amenity", "post_office")); } else if (objectClass.equalsIgnoreCase("Public Toilets")) { sb.append(getTagString("amenity", "toilets")); } else if (objectClass.equalsIgnoreCase("Railway Stop")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Restaurant")) { sb.append(getTagString("amenity", "restaurant")); } else if (objectClass.equalsIgnoreCase("Restaurant - Fast Food")) { sb.append(getTagString("amenity", "fast_food")); } else if (objectClass.equalsIgnoreCase("Roadblock")) { sb.append(getTagString("barrier", "highway")); } else if (objectClass.equalsIgnoreCase("School")) { sb.append(getTagString("amenity", "school")); } else if (objectClass.equalsIgnoreCase("Shop")) { sb.append(getTagString("shop", "yes")); } else if (objectClass.equalsIgnoreCase("Super Market")) { sb.append(getTagString("shop", "supermarket")); } else if (objectClass.equalsIgnoreCase("Swimming")) { sb.append(getTagString("", "")); } else if (objectClass.equalsIgnoreCase("Tree")) { sb.append(getTagString("natural", "tree")); } else if (objectClass.equalsIgnoreCase("Tourist Attraction")) { sb.append(getTagString("tourism", "attraction")); } else if (objectClass.equalsIgnoreCase("University")) { sb.append(getTagString("amenity", "university")); } else if (objectClass.equalsIgnoreCase("Warehouse")) { sb.append(getTagString("building", "warehouse")); } else if (objectClass.equalsIgnoreCase("Zoo")) { sb.append(getTagString("tourism", "zoo")); } } //end MapPoint Check if (object instanceof LineString) { if (objectClass.equalsIgnoreCase("Lake") || objectClass.equalsIgnoreCase("Ocean") || objectClass.equalsIgnoreCase("River")) { sb.append(getTagString("natural", "water")); } else if (objectClass.equalsIgnoreCase("Agricultural Plot")) { sb.append(getTagString("landuse", "farm")); } else if (objectClass.equalsIgnoreCase("Beach")) { sb.append(getTagString("natural", "beach")); } else if (objectClass.equalsIgnoreCase("Building")) { sb.append(getTagString("building", "yes")); } else if (objectClass.equalsIgnoreCase("Commercial Area")) { sb.append(getTagString("landuse", "commercial")); } else if (objectClass.equalsIgnoreCase("Country - Filled")) { sb.append(getTagString("boundary", "administrative")); } else if (objectClass.equalsIgnoreCase("Forest")) { sb.append(getTagString("landuse", "forest")); } else if (objectClass.equalsIgnoreCase("Grass Field")) { sb.append(getTagString("landuse", "grass")); } else if (objectClass.equalsIgnoreCase("Industrial Area")) { sb.append(getTagString("landuse", "industrial")); } else if (objectClass.equalsIgnoreCase("Island")) { sb.append(getTagString("place", "island")); } else if (objectClass.equalsIgnoreCase("Market")) { sb.append(getTagString("amenity", "marketplace")); } else if (objectClass.equalsIgnoreCase("Park")) { sb.append(getTagString("leisure", "park")); } else if (objectClass.equalsIgnoreCase("Parking Lot")) { sb.append(getTagString("amenity", "parking")); } else if (objectClass.equalsIgnoreCase("Protected Area")) { sb.append(getTagString("boundary", "protected_area")); } else if (objectClass.equalsIgnoreCase("Reef")) { sb.append(getTagString("natural", "reef")); } else if (objectClass.equalsIgnoreCase("Residential Area")) { sb.append(getTagString("landuse", "residential")); } else if (objectClass.equalsIgnoreCase("School")) { sb.append(getTagString("amenity", "school")); } else if (objectClass.equalsIgnoreCase("Small Island")) { sb.append(getTagString("place", "island")); } else if (objectClass.equalsIgnoreCase("Sports Field")) { sb.append(getTagString("leisure", "pitch")); } else if (objectClass.equalsIgnoreCase("Stadium")) { sb.append(getTagString("leisure", "stadium")); } else if (objectClass.equalsIgnoreCase("University")) { sb.append(getTagString("amenity", "university")); } else if (objectClass.equalsIgnoreCase("Wetland")) { sb.append(getTagString("natural", "wetland")); } } //end LineString check if (object instanceof Polygon) { if (objectClass.equalsIgnoreCase("Border - Country Border")) { } else if (objectClass.equalsIgnoreCase("Border - Inter-Country")) { } else if (objectClass.equalsIgnoreCase("Coastline")) { sb.append(getTagString("natural", "coastline")); } else if (objectClass.equalsIgnoreCase("Ferry Line")) { sb.append(getTagString("route", "ferry")); } else if (objectClass.equalsIgnoreCase("Rail Line")) { } else if (objectClass.equalsIgnoreCase("Rail - Platform")) { } else if (objectClass.equalsIgnoreCase("Rail - Tram")) { } else if (objectClass.equalsIgnoreCase("Path - Bikeway")) { sb.append(getTagString("highway", "cycleway")); } else if (objectClass.equalsIgnoreCase("Hiking Trail")) { sb.append(getTagString("highway", "footway")); } else if (objectClass.equalsIgnoreCase("Road - Primary Highway")) { sb.append(getTagString("highway", "motorway")); } else if (objectClass.equalsIgnoreCase("Road - Primary Highway Link")) { sb.append(getTagString("highway", "motorway_link")); } else if (objectClass.equalsIgnoreCase("Road - Primary Highway")) { sb.append(getTagString("highway", "primary")); } else if (objectClass.equalsIgnoreCase("Road - Primary Highway Link")) { sb.append(getTagString("highway", "primary_link")); } else if (objectClass.equalsIgnoreCase("Road - City Secondary")) { sb.append(getTagString("highway", "residential")); } else if (objectClass.equalsIgnoreCase("Road - Secondary Highway")) { sb.append(getTagString("highway", "secondary")); } else if (objectClass.equalsIgnoreCase("Road - Secondary Highway Link")) { sb.append(getTagString("highway", "secondary_link")); } else if (objectClass.equalsIgnoreCase("Road - City Tertiary")) { sb.append(getTagString("highway", "tertiary")); } else if (objectClass.equalsIgnoreCase("Path - Steps")) { sb.append(getTagString("highway", "steps")); } else if (objectClass.equalsIgnoreCase("Road - Unclassified")) { sb.append(getTagString("highway", "unclassified")); } else if (objectClass.equalsIgnoreCase("Water Way - Intermittent Stream")) { sb.append(getTagString("waterway", "stream")); sb.append(getTagString("intermittent", "yes")); } else if (objectClass.equalsIgnoreCase("Water Way - River")) { sb.append(getTagString("waterway", "river")); } else if (objectClass.equalsIgnoreCase("Water Way - Stream")) { sb.append(getTagString("waterway", "stream")); } } //end polygon check return sb.toString(); } private String getTagString(String key, float value) { StringBuilder sb = new StringBuilder(); sb.append("<tag k='"); sb.append(key); sb.append("' v='"); sb.append(value); sb.append("' />\n"); return sb.toString(); } private String getTagString(String key, String value) { StringBuilder sb = new StringBuilder(); sb.append("<tag k='"); sb.append(key); sb.append("' v='"); sb.append(value); sb.append("' />\n"); return sb.toString(); } private String getWayTagOpen(long id, String timeStamp) { StringBuilder sb = new StringBuilder(); sb.append("<way id='-"); sb.append(id); sb.append("' timestamp='"); sb.append(timeStamp); sb.append("' version='1'"); sb.append(">\n"); return sb.toString(); } /** * Returns the Coordinate from the provided ArrayList using the given * Coordinate. Returns null is none of the points are using the Coordinate. * * @param points * @param c * @return */ private MapPoint pointUsingCoordinate(ArrayList<MapPoint> points, Coordinate c) { MapPoint point = null; for (MapPoint p: points) { if (p.getCoordinateList().get(0).equals(c)) { point = p; break; } } return point; } }