package org.opensha2.internal; import static com.google.common.base.Preconditions.checkState; import static org.opensha2.util.Maths.round; import org.opensha2.geo.Location; import org.opensha2.geo.LocationList; import org.opensha2.util.NamedLocation; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.annotations.SerializedName; import java.util.List; import java.util.Objects; /** * GeoJSON serialization keys, values, and utilities. * * @author Peter Powers */ @SuppressWarnings("javadoc") public final class GeoJson { public static final class Key { public static final String TYPE = "type"; public static final String FEATURES = "features"; public static final String ID = "id"; public static final String GEOMETRY = "geometry"; public static final String COORDINATES = "coordinates"; public static final String PROPERTIES = "properties"; } public static final class Value { public static final String FEATURE_COLLECTION = "FeatureCollection"; public static final String FEATURE = "Feature"; public static final String POINT = "Point"; public static final String POLYGON = "Polygon"; public static final String EXTENTS = "Extents"; } public static final class Properties { public static final class Key { public static final String TITLE = "title"; public static final String DESCRIPTION = "description"; public static final String MARKER_SIZE = "marker-size"; public static final String MARKER_SYMBOL = "marker-symbol"; public static final String MARKER_COLOR = "marker-color"; public static final String STROKE = "stroke"; public static final String STROKE_OPACITY = "stroke-opacity"; public static final String STROKE_WIDTH = "stroke-width"; public static final String FILL = "fill"; public static final String FILL_OPACITY = "fill-opacity"; public static final String SPACING = "spacing"; } } /** * Returns the {@code LocationList} represented by the values in the supplied * JSON array. {@code coordsElement} is expected to contain only a single, * nested array of coordinates that define a polygonal border with no holes * per the GeoJSON <a * href="http://geojson.org/geojson-spec.html#id4">polygon</a> spec. * * @param coordsArray to process */ public static LocationList fromCoordinates(JsonArray coordsArray) { JsonArray coords = coordsArray.get(0).getAsJsonArray(); LocationList.Builder builder = LocationList.builder(); for (JsonElement element : coords) { JsonArray coord = element.getAsJsonArray(); builder.add( coord.get(1).getAsDouble(), coord.get(0).getAsDouble()); } return builder.build(); } /** * Checks that the property in the supplied object with the name {@code key} * matches an expected {@code value}. * * @param json object to check for property * @param key property name * @param value of property */ public static void validateProperty(JsonObject json, String key, String value) { String actual = json.get(key).getAsString(); checkState( Objects.equals(value, actual), "Expected \"%s\" : \"%s\", but found \"$s\"", key, value, actual); } /* GeoJSON objectsfor stadard GSON serialization */ static class FeatureCollection { String type = "FeatureCollection"; List<Feature> features; } static class Feature { String type = "Feature"; String id; Geometry geometry = new Geometry(); PropertiesObject properties; } static Feature createPoint(NamedLocation loc) { Feature f = new Feature(); f.geometry.type = "Point"; f.geometry.coordinates = toCoordinates(loc.location()); f.properties = new PointProperties(); f.properties.title = loc.toString(); return f; } private static final String EXTENTS_COLOR = "#AA0078"; static Feature createPolygon( String name, LocationList coords, Optional<String> id, Optional<Double> spacing) { Feature f = new Feature(); PolyProperties properties = new PolyProperties(); properties.title = name; if (spacing.isPresent()) { properties.spacing = spacing.get(); } if (id.isPresent()) { f.id = id.get(); coords = coords.bounds().toList(); properties.strokeColor = EXTENTS_COLOR; properties.fillColor = EXTENTS_COLOR; } f.geometry.type = "Polygon"; f.geometry.coordinates = ImmutableList.of(toCoordinates(coords)); f.properties = properties; return f; } static class Geometry { String type; Object coordinates; } static class PropertiesObject { String title; } static class PointProperties extends PropertiesObject { @SerializedName("marker-size") String markerSize = "small"; } static class PolyProperties extends PropertiesObject { Double spacing; @SerializedName("fill") String fillColor; @SerializedName("marker-color") String strokeColor; } static double[] toCoordinates(Location loc) { return new double[] { round(loc.lon(), 5), round(loc.lat(), 5) }; } static double[][] toCoordinates(LocationList locs) { double[][] coords = new double[locs.size()][2]; for (int i = 0; i < locs.size(); i++) { coords[i] = toCoordinates(locs.get(i)); } return coords; } /* brute force compaction of coordinate array onto single line */ static String cleanPoints(String s) { return s.replace(": [\n ", ": [") .replace(",\n ", ", ") .replace("\n ]", "]") + "\n"; } /* brute force compaction of coordinate array onto single line */ static String cleanPoly(String s) { return s .replace("\n [", "[") .replace("[\n ", "[ ") .replace(",\n ", ", ") .replace("\n ]", " ]") .replace("\n ]", "]") + "\n"; } }