001 // License: GPL. For details, see LICENSE file. 002 package org.openstreetmap.josm.io; 003 004 import java.util.Map; 005 import java.util.Map.Entry; 006 import org.openstreetmap.josm.data.coor.LatLon; 007 import org.openstreetmap.josm.data.osm.Changeset; 008 import org.openstreetmap.josm.data.osm.Node; 009 import org.openstreetmap.josm.data.osm.OsmPrimitive; 010 import org.openstreetmap.josm.data.osm.Relation; 011 import org.openstreetmap.josm.data.osm.Way; 012 import org.openstreetmap.josm.data.osm.visitor.Visitor; 013 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 014 015 public class GeoJSONWriter implements Visitor { 016 017 private OsmDataLayer layer; 018 private StringBuilder out; 019 private final boolean skipEmptyNodes = true; 020 private boolean insertComma = false; 021 022 public GeoJSONWriter(OsmDataLayer layer) { 023 this.layer = layer; 024 } 025 026 public String write() { 027 out = new StringBuilder(1 << 12); 028 out.append("{\"type\": \"FeatureCollection\",\n"); 029 out.append("\"features\": [\n"); 030 for (Node n : layer.data.getNodes()) { 031 appendPrimitive(n); 032 } 033 for (Way w : layer.data.getWays()) { 034 appendPrimitive(w); 035 } 036 out.append("\n]\n}"); 037 return out.toString(); 038 } 039 040 @Override 041 public void visit(Node n) { 042 out.append("\"type\": \"Point\", \"coordinates\": "); 043 appendCoord(n.getCoor()); 044 } 045 046 @Override 047 public void visit(Way w) { 048 out.append("\"type\": \"LineString\", \"coordinates\": ["); 049 boolean insertCommaCoords = false; 050 for (Node n : w.getNodes()) { 051 if (insertCommaCoords) { 052 out.append(", "); 053 } 054 insertCommaCoords = true; 055 appendCoord(n.getCoor()); 056 } 057 out.append("]"); 058 } 059 060 @Override 061 public void visit(Relation e) { 062 } 063 064 @Override 065 public void visit(Changeset cs) { 066 } 067 068 protected String escape(String s) { 069 return s.replace("\"", "\\\"").replace("\\", "\\\\").replace("\n", "\\n"); 070 } 071 072 protected void appendPrimitive(OsmPrimitive p) { 073 if (p.isIncomplete()) { 074 return; 075 } else if (skipEmptyNodes && p instanceof Node && p.getKeys().isEmpty()) { 076 return; 077 } 078 if (insertComma) { 079 out.append(",\n"); 080 } 081 insertComma = true; 082 out.append("{\"type\": \"Feature\",\n"); 083 Map<String, String> tags = p.getKeys(); 084 if (!tags.isEmpty()) { 085 out.append("\t\"properties\": {\n"); 086 boolean insertCommaTags = false; 087 for (Entry<String, String> t : tags.entrySet()) { 088 if (insertCommaTags) { 089 out.append(",\n"); 090 } 091 insertCommaTags = true; 092 out.append("\t\t\"").append(escape(t.getKey())).append("\": "); 093 out.append("\"").append(escape(t.getValue())).append("\""); 094 } 095 out.append("\n\t},\n"); 096 } 097 { // append primitive specific 098 out.append("\t\"geometry\": {"); 099 p.visit(this); 100 out.append("}"); 101 } 102 out.append("}"); 103 } 104 105 protected void appendCoord(LatLon c) { 106 if (c != null) { 107 out.append("[").append(c.lon()).append(", ").append(c.lat()).append("]"); 108 } 109 } 110 }