- Timestamp:
- 2019-10-07T23:48:07+02:00 (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/io/GeoJSONReader.java
r15427 r15442 20 20 import javax.json.stream.JsonParser.Event; 21 21 22 import org.openstreetmap.josm.data.coor.EastNorth; 22 23 import org.openstreetmap.josm.data.coor.LatLon; 23 24 import org.openstreetmap.josm.data.osm.DataSet; … … 27 28 import org.openstreetmap.josm.data.osm.RelationMember; 28 29 import org.openstreetmap.josm.data.osm.Way; 30 import org.openstreetmap.josm.data.projection.Projection; 31 import org.openstreetmap.josm.data.projection.Projections; 29 32 import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 30 33 import org.openstreetmap.josm.gui.progress.ProgressMonitor; … … 37 40 public class GeoJSONReader extends AbstractReader { 38 41 42 private static final String CRS = "crs"; 43 private static final String NAME = "name"; 44 private static final String LINK = "link"; 39 45 private static final String COORDINATES = "coordinates"; 40 46 private static final String FEATURES = "features"; … … 43 49 private static final String TYPE = "type"; 44 50 private JsonParser parser; 51 private Projection projection = Projections.getProjectionByCode("EPSG:4326"); // WGS 84 45 52 46 53 GeoJSONReader() { … … 52 59 } 53 60 54 private void parse() {61 private void parse() throws IllegalDataException { 55 62 while (parser.hasNext()) { 56 63 Event event = parser.next(); … … 62 69 } 63 70 64 private void parseRoot(final JsonObject object) { 71 private void parseRoot(final JsonObject object) throws IllegalDataException { 72 parseCrs(object.getJsonObject(CRS)); 65 73 switch (object.getString(TYPE)) { 66 74 case "FeatureCollection": … … 78 86 } 79 87 88 /** 89 * Parse CRS as per https://geojson.org/geojson-spec.html#coordinate-reference-system-objects. 90 * CRS are obsolete in RFC7946 but still allowed for interoperability with older applications. 91 * Only named CRS are supported. 92 * 93 * @param crs CRS JSON object 94 * @throws IllegalDataException in case of error 95 */ 96 private void parseCrs(final JsonObject crs) throws IllegalDataException { 97 if (crs != null) { 98 // Inspired by https://github.com/JOSM/geojson/commit/f13ceed4645244612a63581c96e20da802779c56 99 JsonObject properties = crs.getJsonObject("properties"); 100 if (properties != null) { 101 switch (crs.getString(TYPE)) { 102 case NAME: 103 String crsName = properties.getString(NAME); 104 if ("urn:ogc:def:crs:OGC:1.3:CRS84".equals(crsName)) { 105 // https://osgeo-org.atlassian.net/browse/GEOT-1710 106 crsName = "EPSG:4326"; 107 } else if (crsName.startsWith("urn:ogc:def:crs:EPSG:")) { 108 crsName = crsName.replace("urn:ogc:def:crs:", ""); 109 } 110 projection = Optional.ofNullable(Projections.getProjectionByCode(crsName)) 111 .orElse(Projections.getProjectionByCode("EPSG:4326")); // WGS84 112 break; 113 case LINK: // Not supported (security risk) 114 default: 115 throw new IllegalDataException(crs.toString()); 116 } 117 } 118 } 119 } 120 80 121 private void parseFeatureCollection(final JsonArray features) { 81 122 for (JsonValue feature : features) { 82 123 if (feature instanceof JsonObject) { 83 JsonObject item = (JsonObject) feature; 84 parseFeature(item); 124 parseFeature((JsonObject) feature); 85 125 } 86 126 } … … 117 157 118 158 private void parseGeometryCollection(final JsonObject feature, final JsonObject geometry) { 119 JsonArray geometries = geometry.getJsonArray("geometries"); 120 for (JsonValue jsonValue : geometries) { 159 for (JsonValue jsonValue : geometry.getJsonArray("geometries")) { 121 160 parseGeometry(feature, jsonValue.asJsonObject()); 122 161 } … … 156 195 } 157 196 197 private LatLon getLatLon(final JsonArray coordinates) { 198 return projection.eastNorth2latlon(new EastNorth( 199 coordinates.getJsonNumber(0).doubleValue(), 200 coordinates.getJsonNumber(1).doubleValue())); 201 } 202 158 203 private void parsePoint(final JsonObject feature, final JsonArray coordinates) { 159 double lat = coordinates.getJsonNumber(1).doubleValue(); 160 double lon = coordinates.getJsonNumber(0).doubleValue(); 161 Node node = createNode(lat, lon); 162 fillTagsFromFeature(feature, node); 204 fillTagsFromFeature(feature, createNode(getLatLon(coordinates))); 163 205 } 164 206 165 207 private void parseMultiPoint(final JsonObject feature, final JsonObject geometry) { 166 JsonArray coordinates = geometry.getJsonArray(COORDINATES); 167 for (JsonValue coordinate : coordinates) { 208 for (JsonValue coordinate : geometry.getJsonArray(COORDINATES)) { 168 209 parsePoint(feature, coordinate.asJsonArray()); 169 210 } … … 171 212 172 213 private void parseLineString(final JsonObject feature, final JsonArray coordinates) { 173 if (coordinates.isEmpty()) { 174 return; 175 } 176 createWay(coordinates, false) 177 .ifPresent(way -> fillTagsFromFeature(feature, way)); 214 if (!coordinates.isEmpty()) { 215 createWay(coordinates, false) 216 .ifPresent(way -> fillTagsFromFeature(feature, way)); 217 } 178 218 } 179 219 180 220 private void parseMultiLineString(final JsonObject feature, final JsonObject geometry) { 181 JsonArray coordinates = geometry.getJsonArray(COORDINATES); 182 for (JsonValue coordinate : coordinates) { 221 for (JsonValue coordinate : geometry.getJsonArray(COORDINATES)) { 183 222 parseLineString(feature, coordinate.asJsonArray()); 184 223 } … … 186 225 187 226 private void parsePolygon(final JsonObject feature, final JsonArray coordinates) { 188 if (coordinates.size() == 1) { 227 final int size = coordinates.size(); 228 if (size == 1) { 189 229 createWay(coordinates.getJsonArray(0), true) 190 230 .ifPresent(way -> fillTagsFromFeature(feature, way)); 191 } else if ( coordinates.size()> 1) {231 } else if (size > 1) { 192 232 // create multipolygon 193 233 final Relation multipolygon = new Relation(); … … 196 236 .ifPresent(way -> multipolygon.addMember(new RelationMember("outer", way))); 197 237 198 for (JsonValue interiorRing : coordinates.subList(1, coordinates.size())) {238 for (JsonValue interiorRing : coordinates.subList(1, size)) { 199 239 createWay(interiorRing.asJsonArray(), true) 200 240 .ifPresent(way -> multipolygon.addMember(new RelationMember("inner", way))); … … 207 247 208 248 private void parseMultiPolygon(final JsonObject feature, final JsonObject geometry) { 209 JsonArray coordinates = geometry.getJsonArray(COORDINATES); 210 for (JsonValue coordinate : coordinates) { 249 for (JsonValue coordinate : geometry.getJsonArray(COORDINATES)) { 211 250 parsePolygon(feature, coordinate.asJsonArray()); 212 251 } 213 252 } 214 253 215 private Node createNode(final double lat, final doublelon) {216 final Node node = new Node( new LatLon(lat, lon));254 private Node createNode(final LatLon latlon) { 255 final Node node = new Node(latlon); 217 256 getDataSet().addPrimitive(node); 218 257 return node; … … 224 263 } 225 264 226 final List<LatLon> latlons = coordinates.stream().map(coordinate -> { 227 final JsonArray jsonValues = coordinate.asJsonArray(); 228 return new LatLon( 229 jsonValues.getJsonNumber(1).doubleValue(), 230 jsonValues.getJsonNumber(0).doubleValue() 231 ); 232 }).collect(Collectors.toList()); 265 final List<LatLon> latlons = coordinates.stream().map( 266 coordinate -> getLatLon(coordinate.asJsonArray())).collect(Collectors.toList()); 233 267 234 268 final int size = latlons.size(); -
trunk/test/unit/org/openstreetmap/josm/io/GeoJSONReaderTest.java
r15427 r15442 117 117 } 118 118 119 /** 120 * Test reading a GeoJSON file with a named CRS. 121 * @throws Exception in case of error 122 */ 123 @Test 124 public void testReadGeoJsonNamedCrs() throws Exception { 125 try (InputStream in = Files.newInputStream(Paths.get(TestUtils.getTestDataRoot(), "geocrs.json"))) { 126 final List<OsmPrimitive> primitives = new ArrayList<>(new GeoJSONReader() 127 .doParseDataSet(in, null) 128 .getPrimitives(it -> true)); 129 assertEquals(24, primitives.size()); 130 assertTrue(primitives.stream() 131 .filter(it -> areEqualNodes(it, new Node(new LatLon(52.5840213, 13.1724145)))) 132 .findAny().isPresent()); 133 } 134 } 135 119 136 private static boolean areEqualNodes(final OsmPrimitive p1, final OsmPrimitive p2) { 120 137 return (p1 instanceof Node) 121 138 && (p2 instanceof Node) 122 && ((Node) p1).getCoor().equals (((Node) p2).getCoor());139 && ((Node) p1).getCoor().equalsEpsilon(((Node) p2).getCoor()); 123 140 } 124 141
Note:
See TracChangeset
for help on using the changeset viewer.