source: josm/trunk/src/org/openstreetmap/josm/io/GeoJSONWriter.java@ 10171

Last change on this file since 10171 was 10171, checked in by Don-vip, 8 years ago

update to checkstyle 6.18

  • Property svn:eol-style set to native
File size: 6.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import java.io.StringWriter;
5import java.math.BigDecimal;
6import java.math.RoundingMode;
7import java.util.HashMap;
8import java.util.Iterator;
9import java.util.Map;
10import java.util.Map.Entry;
11
12import javax.json.Json;
13import javax.json.JsonArrayBuilder;
14import javax.json.JsonObjectBuilder;
15import javax.json.JsonWriter;
16import javax.json.stream.JsonGenerator;
17
18import org.openstreetmap.josm.data.Bounds;
19import org.openstreetmap.josm.data.coor.EastNorth;
20import org.openstreetmap.josm.data.coor.LatLon;
21import org.openstreetmap.josm.data.osm.DataSet;
22import org.openstreetmap.josm.data.osm.INode;
23import org.openstreetmap.josm.data.osm.IRelation;
24import org.openstreetmap.josm.data.osm.IWay;
25import org.openstreetmap.josm.data.osm.Node;
26import org.openstreetmap.josm.data.osm.OsmPrimitive;
27import org.openstreetmap.josm.data.osm.Way;
28import org.openstreetmap.josm.data.osm.visitor.PrimitiveVisitor;
29import org.openstreetmap.josm.data.projection.Projection;
30import org.openstreetmap.josm.gui.layer.OsmDataLayer;
31
32/**
33 * Writes OSM data as a GeoJSON string, using JSR 353: Java API for JSON Processing (JSON-P).
34 */
35public class GeoJSONWriter {
36
37 private final OsmDataLayer layer;
38 private final Projection projection;
39 private static final boolean skipEmptyNodes = true;
40
41 /**
42 * Constructs a new {@code GeoJSONWriter}.
43 * @param layer The OSM data layer to save
44 * @param projection The projection to use for coordinates
45 */
46 public GeoJSONWriter(OsmDataLayer layer, Projection projection) {
47 this.layer = layer;
48 this.projection = projection;
49 }
50
51 /**
52 * Writes OSM data as a GeoJSON string (prettified).
53 * @return The GeoJSON data
54 */
55 public String write() {
56 return write(true);
57 }
58
59 /**
60 * Writes OSM data as a GeoJSON string (prettified or not).
61 * @param pretty {@code true} to have pretty output, {@code false} otherwise
62 * @return The GeoJSON data
63 * @since 6756
64 */
65 public String write(boolean pretty) {
66 StringWriter stringWriter = new StringWriter();
67 Map<String, Object> config = new HashMap<>(1);
68 config.put(JsonGenerator.PRETTY_PRINTING, pretty);
69 try (JsonWriter writer = Json.createWriterFactory(config).createWriter(stringWriter)) {
70 JsonObjectBuilder object = Json.createObjectBuilder()
71 .add("type", "FeatureCollection")
72 .add("crs", Json.createObjectBuilder().add("type", "name").add(
73 "properties", Json.createObjectBuilder().add("name", projection.toCode())))
74 .add("generator", "JOSM");
75 appendLayerBounds(layer.data, object);
76 appendLayerFeatures(layer.data, object);
77 writer.writeObject(object.build());
78 return stringWriter.toString();
79 }
80 }
81
82 private class GeometryPrimitiveVisitor implements PrimitiveVisitor {
83
84 private final JsonObjectBuilder geomObj;
85
86 GeometryPrimitiveVisitor(JsonObjectBuilder geomObj) {
87 this.geomObj = geomObj;
88 }
89
90 @Override
91 public void visit(INode n) {
92 geomObj.add("type", "Point");
93 LatLon ll = n.getCoor();
94 if (ll != null) {
95 geomObj.add("coordinates", getCoorArray(Json.createArrayBuilder(), n.getCoor()));
96 }
97 }
98
99 @Override
100 public void visit(IWay w) {
101 geomObj.add("type", "LineString");
102 if (w instanceof Way) {
103 JsonArrayBuilder array = Json.createArrayBuilder();
104 for (Node n : ((Way) w).getNodes()) {
105 LatLon ll = n.getCoor();
106 if (ll != null) {
107 array.add(getCoorArray(Json.createArrayBuilder(), ll));
108 }
109 }
110 geomObj.add("coordinates", array);
111 }
112 }
113
114 @Override
115 public void visit(IRelation r) {
116 }
117 }
118
119 private JsonArrayBuilder getCoorArray(JsonArrayBuilder builder, LatLon c) {
120 return getCoorArray(builder, projection.latlon2eastNorth(c));
121 }
122
123 private static JsonArrayBuilder getCoorArray(JsonArrayBuilder builder, EastNorth c) {
124 return builder
125 .add(BigDecimal.valueOf(c.getX()).setScale(11, RoundingMode.HALF_UP))
126 .add(BigDecimal.valueOf(c.getY()).setScale(11, RoundingMode.HALF_UP));
127 }
128
129 protected void appendPrimitive(OsmPrimitive p, JsonArrayBuilder array) {
130 if (p.isIncomplete()) {
131 return;
132 } else if (skipEmptyNodes && p instanceof Node && p.getKeys().isEmpty()) {
133 return;
134 }
135
136 // Properties
137 final JsonObjectBuilder propObj = Json.createObjectBuilder();
138 for (Entry<String, String> t : p.getKeys().entrySet()) {
139 propObj.add(t.getKey(), t.getValue());
140 }
141
142 // Geometry
143 final JsonObjectBuilder geomObj = Json.createObjectBuilder();
144 p.accept(new GeometryPrimitiveVisitor(geomObj));
145
146 // Build primitive JSON object
147 array.add(Json.createObjectBuilder()
148 .add("type", "Feature")
149 .add("properties", propObj)
150 .add("geometry", geomObj));
151 }
152
153 protected void appendLayerBounds(DataSet ds, JsonObjectBuilder object) {
154 if (ds != null) {
155 Iterator<Bounds> it = ds.getDataSourceBounds().iterator();
156 if (it.hasNext()) {
157 Bounds b = new Bounds(it.next());
158 while (it.hasNext()) {
159 b.extend(it.next());
160 }
161 appendBounds(b, object);
162 }
163 }
164 }
165
166 protected void appendBounds(Bounds b, JsonObjectBuilder object) {
167 if (b != null) {
168 JsonArrayBuilder builder = Json.createArrayBuilder();
169 getCoorArray(builder, b.getMin());
170 getCoorArray(builder, b.getMax());
171 object.add("bbox", builder);
172 }
173 }
174
175 protected void appendLayerFeatures(DataSet ds, JsonObjectBuilder object) {
176 JsonArrayBuilder array = Json.createArrayBuilder();
177 if (ds != null) {
178 for (Node n : ds.getNodes()) {
179 appendPrimitive(n, array);
180 }
181 for (Way w : ds.getWays()) {
182 appendPrimitive(w, array);
183 }
184 }
185 object.add("features", array);
186 }
187}
Note: See TracBrowser for help on using the repository browser.