GeometryJSON.java
- /* This file is part of Openrouteservice.
- *
- * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the
- * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- * This library 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 Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License along with this library;
- * if not, see <https://www.gnu.org/licenses/>.
- */
- package org.heigit.ors.geojson;
- import org.geotools.geometry.jts.coordinatesequence.CoordinateSequences;
- import org.heigit.ors.util.FormatUtility;
- import org.json.JSONArray;
- import org.json.JSONObject;
- import org.locationtech.jts.geom.*;
- @SuppressWarnings("unchecked")
- public class GeometryJSON {
- private static final int COORDINATE_PRECISION = 6;
- private static final GeometryFactory factory = new GeometryFactory();
- private GeometryJSON() {
- }
- public static org.json.simple.JSONArray toJSON(Polygon poly) {
- org.json.simple.JSONArray coords = new org.json.simple.JSONArray();
- LineString shell = poly.getExteriorRing();
- boolean inverse = shell.getNumPoints() > 1 && !CoordinateSequences.isCCW(shell.getCoordinateSequence());
- coords.add(toJSON(shell, inverse));
- if (poly.getNumInteriorRing() > 0) {
- int nRings = poly.getNumInteriorRing();
- for (int j = 0; j < nRings; ++j) {
- LineString ring = poly.getInteriorRingN(j);
- inverse = ring.getNumPoints() > 1 && CoordinateSequences.isCCW(ring.getCoordinateSequence());
- coords.add(toJSON(ring, inverse));
- }
- }
- return coords;
- }
- private static org.json.simple.JSONArray toJSON(LineString line, boolean inverseSeq) {
- // "coordinates": [ [100.0, 0.0], [101.0, 1.0] ]
- int size = line.getNumPoints();
- org.json.simple.JSONArray arrCoords = new org.json.simple.JSONArray();
- CoordinateSequence seq = line.getCoordinateSequence();
- for (int i = 0; i < size; ++i) {
- Coordinate coord = seq.getCoordinate(inverseSeq ? size - i - 1 : i);
- arrCoords.add(toJSON(coord));
- }
- return arrCoords;
- }
- private static org.json.simple.JSONArray toJSON(Point point) {
- return toJSON(point.getCoordinate());
- }
- public static org.json.simple.JSONArray toJSON(Coordinate c) {
- org.json.simple.JSONArray arrCoords = new org.json.simple.JSONArray();
- arrCoords.add(FormatUtility.roundToDecimals(c.x, COORDINATE_PRECISION));
- arrCoords.add(FormatUtility.roundToDecimals(c.y, COORDINATE_PRECISION));
- return arrCoords;
- }
- public static org.json.simple.JSONArray toJSON(Coordinate[] coords, boolean includeElevation) {
- org.json.simple.JSONArray arrCoords = new org.json.simple.JSONArray();
- for (Coordinate c : coords) {
- org.json.simple.JSONArray coord = new org.json.simple.JSONArray();
- coord.add(FormatUtility.roundToDecimals(c.x, COORDINATE_PRECISION));
- coord.add(FormatUtility.roundToDecimals(c.y, COORDINATE_PRECISION));
- if (includeElevation)
- coord.add(FormatUtility.roundToDecimals(c.z, 1));
- arrCoords.add(coord);
- }
- return arrCoords;
- }
- public static Geometry parse(JSONObject json) throws Exception {
- if (!json.has("type"))
- throw new Exception("type element is missing.");
- if (!json.has("coordinates"))
- throw new Exception("coordinates element is missing.");
- String type = json.getString("type");
- JSONArray arrCoords = json.getJSONArray("coordinates");
- return switch (type) {
- case "Point" -> readPoint(arrCoords);
- case "MultiPoint" -> readMultiPoint(arrCoords);
- case "LineString" -> readLineString(arrCoords);
- case "MultiLineString" -> readMultiLineString(arrCoords);
- case "Polygon" -> readPolygon(arrCoords);
- case "MultiPolygon" -> readMultiPolygon(arrCoords);
- default -> throw new Exception("invalid type: " + type);
- };
- }
- private static Point readPoint(JSONArray value) {
- Coordinate c = new Coordinate(value.getDouble(0), value.getDouble(1));
- return factory.createPoint(c);
- }
- private static MultiPoint readMultiPoint(JSONArray value) {
- return factory.createMultiPointFromCoords(readCoordinates(value));
- }
- private static LineString readLineString(JSONArray value) {
- return factory.createLineString(readCoordinates(value));
- }
- private static MultiLineString readMultiLineString(JSONArray value) {
- int n = value.length();
- LineString[] lineStrings = new LineString[n];
- for (int i = 0; i < n; i++) {
- JSONArray arrLineString = (JSONArray) value.get(i);
- lineStrings[i] = readLineString(arrLineString);
- }
- return factory.createMultiLineString(lineStrings);
- }
- private static MultiPolygon readMultiPolygon(JSONArray value) {
- int n = value.length();
- Polygon[] polys = new Polygon[n];
- for (int i = 0; i < n; i++) {
- JSONArray arrPoly = (JSONArray) value.get(i);
- polys[i] = readPolygon(arrPoly);
- }
- return factory.createMultiPolygon(polys);
- }
- private static Polygon readPolygon(JSONArray value) {
- int n = value.length();
- LinearRing shell = null;
- LinearRing[] holes = new LinearRing[n - 1];
- for (int i = 0; i < n; i++) {
- JSONArray arrLineString = (JSONArray) value.get(i);
- if (i == 0)
- shell = factory.createLinearRing(readCoordinates(arrLineString));
- else
- holes[i - 1] = factory.createLinearRing(readCoordinates(arrLineString));
- }
- if (holes.length == 0)
- return factory.createPolygon(shell);
- else
- return factory.createPolygon(shell, holes);
- }
- private static Coordinate[] readCoordinates(JSONArray value) {
- int n = value.length();
- Coordinate[] coords = new Coordinate[n];
- for (int i = 0; i < n; i++) {
- JSONArray arrCoord = value.getJSONArray(i);
- coords[i] = new Coordinate(arrCoord.getDouble(0), arrCoord.getDouble(1));
- }
- return coords;
- }
- }