svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.jts / src / main / java / org / gvsig / fmap / geom / jts / formats / geojson / GeoJsonWriter.java @ 47755
History | View | Annotate | Download (8.16 KB)
1 |
|
---|---|
2 |
package org.gvsig.fmap.geom.jts.formats.geojson; |
3 |
|
4 |
import java.io.IOException; |
5 |
import java.io.StringWriter; |
6 |
import java.io.Writer; |
7 |
import java.util.ArrayList; |
8 |
import java.util.LinkedHashMap; |
9 |
import java.util.List; |
10 |
import java.util.Map; |
11 |
|
12 |
import org.json.simple.JSONAware; |
13 |
import org.json.simple.JSONObject; |
14 |
|
15 |
import com.vividsolutions.jts.geom.CoordinateSequence; |
16 |
import com.vividsolutions.jts.geom.Geometry; |
17 |
import com.vividsolutions.jts.geom.GeometryCollection; |
18 |
import com.vividsolutions.jts.geom.LineString; |
19 |
import com.vividsolutions.jts.geom.MultiLineString; |
20 |
import com.vividsolutions.jts.geom.MultiPoint; |
21 |
import com.vividsolutions.jts.geom.MultiPolygon; |
22 |
import com.vividsolutions.jts.geom.Point; |
23 |
import com.vividsolutions.jts.geom.Polygon; |
24 |
import com.vividsolutions.jts.util.Assert; |
25 |
|
26 |
/**
|
27 |
* Writes {@link Geometry}s as JSON fragments in GeoJson format.
|
28 |
*
|
29 |
* @author Martin Davis
|
30 |
* @author Paul Howells, Vivid Solutions
|
31 |
*/
|
32 |
public class GeoJsonWriter { |
33 |
|
34 |
public static final String EPSG_PREFIX = "EPSG:"; |
35 |
|
36 |
private double scale; |
37 |
protected boolean isEncodeCRS = true; |
38 |
|
39 |
/**
|
40 |
* Constructs a GeoJsonWriter instance.
|
41 |
*/
|
42 |
public GeoJsonWriter() {
|
43 |
this(8); |
44 |
} |
45 |
|
46 |
/**
|
47 |
* Constructs a GeoJsonWriter instance specifying the number of decimals to
|
48 |
* use when encoding floating point numbers.
|
49 |
*/
|
50 |
public GeoJsonWriter(int decimals) { |
51 |
this.scale = Math.pow(10, decimals); |
52 |
} |
53 |
|
54 |
public void setEncodeCRS(boolean isEncodeCRS) { |
55 |
this.isEncodeCRS = isEncodeCRS;
|
56 |
} |
57 |
|
58 |
/**
|
59 |
* Writes a {@link Geometry} in GeoJson format to a String.
|
60 |
*
|
61 |
* @param geometry
|
62 |
* @return String GeoJson Encoded Geometry
|
63 |
*/
|
64 |
public String write(Geometry geometry) { |
65 |
|
66 |
StringWriter writer = new StringWriter(); |
67 |
try {
|
68 |
write(geometry, writer); |
69 |
} catch (IOException ex) { |
70 |
Assert.shouldNeverReachHere(); |
71 |
} |
72 |
|
73 |
return writer.toString();
|
74 |
} |
75 |
|
76 |
/**
|
77 |
* Writes a {@link Geometry} in GeoJson format into a {@link Writer}.
|
78 |
*
|
79 |
* @param geometry
|
80 |
* Geometry to encode
|
81 |
* @param writer
|
82 |
* Stream to encode to.
|
83 |
* @throws IOException
|
84 |
* throws an IOException when unable to write the JSON string
|
85 |
*/
|
86 |
public void write(Geometry geometry, Writer writer) throws IOException { |
87 |
Map<String, Object> map = create(geometry, isEncodeCRS); |
88 |
JSONObject.writeJSONString(map, writer); |
89 |
writer.flush(); |
90 |
} |
91 |
|
92 |
protected Map<String, Object> create(Geometry geometry, boolean encodeCRS) { |
93 |
|
94 |
Map<String, Object> result = new LinkedHashMap<String, Object>(); |
95 |
result.put(GeoJsonConstants.NAME_TYPE, geometry.getGeometryType()); |
96 |
|
97 |
if (geometry instanceof Point) { |
98 |
Point point = (Point) geometry; |
99 |
|
100 |
final String jsonString = getJsonString(point.getCoordinateSequence()); |
101 |
|
102 |
result.put(GeoJsonConstants.NAME_COORDINATES, new JSONAware() {
|
103 |
|
104 |
public String toJSONString() { |
105 |
return jsonString;
|
106 |
} |
107 |
}); |
108 |
|
109 |
} else if (geometry instanceof LineString) { |
110 |
LineString lineString = (LineString) geometry; |
111 |
|
112 |
final String jsonString = getJsonString(lineString |
113 |
.getCoordinateSequence()); |
114 |
|
115 |
result.put(GeoJsonConstants.NAME_COORDINATES, new JSONAware() {
|
116 |
|
117 |
public String toJSONString() { |
118 |
return jsonString;
|
119 |
} |
120 |
}); |
121 |
|
122 |
} else if (geometry instanceof Polygon) { |
123 |
Polygon polygon = (Polygon) geometry; |
124 |
|
125 |
result.put(GeoJsonConstants.NAME_COORDINATES, makeJsonAware(polygon)); |
126 |
|
127 |
} else if (geometry instanceof MultiPoint) { |
128 |
MultiPoint multiPoint = (MultiPoint) geometry; |
129 |
|
130 |
result.put(GeoJsonConstants.NAME_COORDINATES, makeJsonAware(multiPoint)); |
131 |
|
132 |
} else if (geometry instanceof MultiLineString) { |
133 |
MultiLineString multiLineString = (MultiLineString) geometry; |
134 |
|
135 |
result.put(GeoJsonConstants.NAME_COORDINATES, makeJsonAware(multiLineString)); |
136 |
|
137 |
} else if (geometry instanceof MultiPolygon) { |
138 |
MultiPolygon multiPolygon = (MultiPolygon) geometry; |
139 |
|
140 |
result.put(GeoJsonConstants.NAME_COORDINATES, makeJsonAware(multiPolygon)); |
141 |
|
142 |
} else if (geometry instanceof GeometryCollection) { |
143 |
GeometryCollection geometryCollection = (GeometryCollection) geometry; |
144 |
|
145 |
ArrayList<Map<String, Object>> geometries = new ArrayList<Map<String, Object>>( |
146 |
geometryCollection.getNumGeometries()); |
147 |
|
148 |
for (int i = 0; i < geometryCollection.getNumGeometries(); i++) { |
149 |
geometries.add(create(geometryCollection.getGeometryN(i), false));
|
150 |
} |
151 |
|
152 |
result.put(GeoJsonConstants.NAME_GEOMETRIES, geometries); |
153 |
|
154 |
} else {
|
155 |
throw new IllegalArgumentException("Unable to encode geometry " + geometry.getGeometryType() ); |
156 |
} |
157 |
|
158 |
if (encodeCRS) {
|
159 |
result.put(GeoJsonConstants.NAME_CRS, createCRS(geometry.getSRID())); |
160 |
} |
161 |
|
162 |
return result;
|
163 |
} |
164 |
|
165 |
private Map<String, Object> createCRS(int srid) { |
166 |
|
167 |
Map<String, Object> result = new LinkedHashMap<String, Object>(); |
168 |
result.put(GeoJsonConstants.NAME_TYPE, GeoJsonConstants.NAME_NAME); |
169 |
|
170 |
Map<String, Object> props = new LinkedHashMap<String, Object>(); |
171 |
props.put(GeoJsonConstants.NAME_NAME, EPSG_PREFIX + srid); |
172 |
|
173 |
result.put(GeoJsonConstants.NAME_PROPERTIES, props); |
174 |
|
175 |
return result;
|
176 |
} |
177 |
|
178 |
private List<JSONAware> makeJsonAware(Polygon poly) { |
179 |
ArrayList<JSONAware> result = new ArrayList<JSONAware>(); |
180 |
|
181 |
{ |
182 |
final String jsonString = getJsonString(poly.getExteriorRing() |
183 |
.getCoordinateSequence()); |
184 |
result.add(new JSONAware() {
|
185 |
|
186 |
public String toJSONString() { |
187 |
return jsonString;
|
188 |
} |
189 |
}); |
190 |
} |
191 |
for (int i = 0; i < poly.getNumInteriorRing(); i++) { |
192 |
final String jsonString = getJsonString(poly.getInteriorRingN(i) |
193 |
.getCoordinateSequence()); |
194 |
result.add(new JSONAware() {
|
195 |
|
196 |
public String toJSONString() { |
197 |
return jsonString;
|
198 |
} |
199 |
}); |
200 |
} |
201 |
|
202 |
return result;
|
203 |
} |
204 |
|
205 |
private List<Object> makeJsonAware(GeometryCollection geometryCollection) { |
206 |
|
207 |
ArrayList<Object> list = new ArrayList<Object>( |
208 |
geometryCollection.getNumGeometries()); |
209 |
for (int i = 0; i < geometryCollection.getNumGeometries(); i++) { |
210 |
Geometry geometry = geometryCollection.getGeometryN(i); |
211 |
|
212 |
if (geometry instanceof Polygon) { |
213 |
Polygon polygon = (Polygon) geometry; |
214 |
list.add(makeJsonAware(polygon)); |
215 |
} |
216 |
else if (geometry instanceof LineString) { |
217 |
LineString lineString = (LineString) geometry; |
218 |
final String jsonString = getJsonString(lineString |
219 |
.getCoordinateSequence()); |
220 |
list.add(new JSONAware() {
|
221 |
|
222 |
public String toJSONString() { |
223 |
return jsonString;
|
224 |
} |
225 |
}); |
226 |
} |
227 |
else if (geometry instanceof Point) { |
228 |
Point point = (Point) geometry; |
229 |
final String jsonString = getJsonString(point.getCoordinateSequence()); |
230 |
list.add(new JSONAware() {
|
231 |
|
232 |
public String toJSONString() { |
233 |
return jsonString;
|
234 |
} |
235 |
}); |
236 |
} |
237 |
} |
238 |
|
239 |
return list;
|
240 |
} |
241 |
|
242 |
private String getJsonString(CoordinateSequence coordinateSequence) { |
243 |
StringBuffer result = new StringBuffer(); |
244 |
|
245 |
if (coordinateSequence.size() > 1) { |
246 |
result.append("[");
|
247 |
} |
248 |
for (int i = 0; i < coordinateSequence.size(); i++) { |
249 |
if (i > 0) { |
250 |
result.append(",");
|
251 |
} |
252 |
result.append("[");
|
253 |
result.append(formatOrdinate(coordinateSequence.getOrdinate(i, CoordinateSequence.X))); |
254 |
result.append(",");
|
255 |
result.append(formatOrdinate(coordinateSequence.getOrdinate(i, CoordinateSequence.Y))); |
256 |
|
257 |
if (coordinateSequence.getDimension() > 2 ) { |
258 |
double z = coordinateSequence.getOrdinate(i, CoordinateSequence.Z);
|
259 |
if (! Double.isNaN(z)) { |
260 |
result.append(",");
|
261 |
result.append(formatOrdinate(z)); |
262 |
} |
263 |
} |
264 |
|
265 |
result.append("]");
|
266 |
|
267 |
} |
268 |
|
269 |
if (coordinateSequence.size() > 1) { |
270 |
result.append("]");
|
271 |
} |
272 |
|
273 |
return result.toString();
|
274 |
} |
275 |
|
276 |
private String formatOrdinate(double x) { |
277 |
String result = null; |
278 |
|
279 |
if (Math.abs(x) >= Math.pow(10, -3) && x < Math.pow(10, 7)) { |
280 |
x = Math.floor(x * scale + 0.5) / scale; |
281 |
long lx = (long) x; |
282 |
if (lx == x) {
|
283 |
result = Long.toString(lx);
|
284 |
} else {
|
285 |
result = Double.toString(x);
|
286 |
} |
287 |
} else {
|
288 |
result = Double.toString(x);
|
289 |
} |
290 |
|
291 |
return result;
|
292 |
} |
293 |
|
294 |
} |