/* * Copyright (C) 2015 Alec Dhuse * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package co.foldingmap.mapImportExport; import co.foldingmap.map.vector.LinearRing; import co.foldingmap.map.vector.MultiGeometry; import co.foldingmap.map.vector.VectorLayer; import co.foldingmap.map.vector.VectorObject; import co.foldingmap.map.vector.Coordinate; import co.foldingmap.map.vector.MapPoint; import co.foldingmap.map.vector.LineString; import co.foldingmap.map.vector.Polygon; import co.scarletshark.geojson.JsonCoordinate; import co.scarletshark.geojson.JsonObject; import co.scarletshark.geojson.JsonPair; import co.scarletshark.geojson.JsonValue; import co.foldingmap.Logger; import co.foldingmap.dataStructures.PropertyValuePair; import co.foldingmap.map.DigitalMap; import co.foldingmap.map.Layer; import co.foldingmap.map.MapObject; import co.foldingmap.map.Visibility; import co.foldingmap.map.themes.ColorStyle; import co.foldingmap.map.themes.IconStyle; import co.foldingmap.map.vector.CoordinateList; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Set; /** * * @author Alec */ public class JsonExporter { /** * Returns the VisibilityObject for an MapObject's style, if there is one. * * @param mapData * @param object * @return */ public static Visibility getObjectStyleVisibility(DigitalMap mapData, MapObject object) { ColorStyle cs = null; Visibility vis = null; if (object instanceof MapPoint) { cs = mapData.getTheme().getIconStyle(((VectorObject)object).getObjectClass()); } else if (object instanceof LineString) { cs = mapData.getTheme().getLineStyle(((VectorObject)object).getObjectClass()); } else if (object instanceof Polygon) { cs = mapData.getTheme().getPolygonStyle(((VectorObject)object).getObjectClass()); } if (cs != null) vis = cs.getVisibility(); return vis; } /** * Exports an IconStyle to Leaflet JSON format. * * @param iconStyle * @return */ public static JsonObject exportIconStyle(IconStyle iconStyle) { Double[] imgDim = new Double[2]; Double[] imgLoc = new Double[2]; Double[] popLoc = new Double[2]; JsonObject object; object = new JsonObject(); imgDim[0] = new Double(iconStyle.getObjectImage().getIconWidth()); imgDim[1] = new Double(iconStyle.getObjectImage().getIconHeight()); imgLoc[0] = new Double(iconStyle.getObjectImage().getIconWidth() / 2f); imgLoc[1] = new Double(iconStyle.getObjectImage().getIconHeight() / 2f); popLoc[0] = new Double(iconStyle.getObjectImage().getIconWidth() / 2f); popLoc[1] = new Double(iconStyle.getObjectImage().getIconHeight() / 2f); object.addPair(new JsonPair("iconUrl", iconStyle.getImageFileName())); object.addPair(new JsonPair("iconSize", new JsonValue(imgDim, JsonValue.ARRAY))); object.addPair(new JsonPair("iconAnchor", new JsonValue(imgLoc, JsonValue.ARRAY))); object.addPair(new JsonPair("popupAnchor", new JsonValue(popLoc, JsonValue.ARRAY))); return object; } public static JsonObject exportLinearRing(DigitalMap mapData, LinearRing ring) { JsonObject geometryObject, jObject, propertiesObject; jObject = new JsonObject(); propertiesObject = new JsonObject(); geometryObject = new JsonObject(); propertiesObject.addPair(new JsonPair("name", ring.getName())); geometryObject.addPair(new JsonPair("type", "LineString")); geometryObject.addPair(getCoordinatePair(ring)); jObject.addPair(new JsonPair("type", "Feature")); jObject.addPair(new JsonPair("properties", propertiesObject)); jObject.addPair(new JsonPair("geometry", geometryObject)); return jObject; } public static JsonObject exportLineString(DigitalMap mapData, LineString line) { JsonObject geometryObject, jObject, propertiesObject; jObject = new JsonObject(); propertiesObject = new JsonObject(); geometryObject = new JsonObject(); propertiesObject.addPair(new JsonPair("name", line.getName())); geometryObject.addPair(new JsonPair("type", "LineString")); geometryObject.addPair(getCoordinatePair(line)); jObject.addPair(new JsonPair("type", "Feature")); jObject.addPair(new JsonPair("properties", propertiesObject)); jObject.addPair(new JsonPair("geometry", geometryObject)); return jObject; } /** * Exports a map to a JsonObject * @param mapData * @return */ public static JsonObject exportMap(DigitalMap mapData) { ArrayList mapObjects = new ArrayList(); JsonObject featureCollection = new JsonObject(); featureCollection.addPair(new JsonPair("type", "FeatureCollection")); for (Layer l: mapData.getLayers()) { if (l instanceof VectorLayer) { VectorLayer vl = (VectorLayer) l; for (VectorObject object: vl.getObjectList()) mapObjects.add(exportVectorObject(mapData, object)); } } featureCollection.addPair(new JsonPair("features", mapObjects.toArray(new Object[1]))); return featureCollection; } /** * Exports a DigitalMap to GeoJSON written to the given file. * * @param mapData * @param file */ public static void exportMap(DigitalMap mapData, File file) { JsonObject jsonObject = exportMap(mapData); try { BufferedWriter writer = new BufferedWriter(new FileWriter(file)); String jsonString = jsonObject.toString(); writer.write(jsonString); writer.close(); } catch (Exception e) { Logger.log(Logger.ERR, "Error in JsonExporter.exportMap(DigitalMap, File) - " + e); } } /** * Exports a DigitalMap to GeoJSON written to the given file. * * @param mapData * @param file */ public static void exportMapForLeaflet(DigitalMap mapData, File file) { HashMap<String, ArrayList> classes = new HashMap<String, ArrayList>(); JsonObject jsonObject = exportMap(mapData); try { //Convert Vector Object to JsonObjects sorted by their class. for (Layer l: mapData.getLayers()) { if (l instanceof VectorLayer) { VectorLayer vl = (VectorLayer) l; for (VectorObject object: vl.getObjectList()) { ArrayList list = classes.get(object.getObjectClass()); if (list == null) { list = new ArrayList(); list.add(exportVectorObject(mapData, object)); classes.put(object.getObjectClass(), list); } else { list.add(exportVectorObject(mapData, object)); } } } } BufferedWriter writer = new BufferedWriter(new FileWriter(file)); Set<String> keySet = classes.keySet(); Collection vals = classes.values(); Object[] lists = vals.toArray(); String keys[] = keySet.toArray(new String[1]); for (int i = 0; i < lists.length; i++) { ArrayList list = (ArrayList) lists[i]; JsonObject object = new JsonObject(); object.addPair(new JsonPair("type", "FeatureCollection")); object.addPair(new JsonPair("features", list.toArray(new JsonObject[1]))); String text = "var " + keys[i].replace(" ", "") + " = " + object.toString() + ";\n\n"; writer.write(text); } writer.close(); } catch (Exception e) { Logger.log(Logger.ERR, "Error in JsonExporter.exportMapForLeaflet(DigitalMap, File) - " + e); } } public static JsonObject exportMapPoint(DigitalMap mapData, MapPoint point) { JsonObject geometryObject, jObject, propertiesObject; String popupContent; Visibility styleVis; jObject = new JsonObject(); propertiesObject = new JsonObject(); geometryObject = new JsonObject(); popupContent = "<b>" + point.getName() + "</b>" + "<br>" + point.getPopupDescription(); styleVis = getObjectStyleVisibility(mapData, point); propertiesObject.addPair(new JsonPair("name", point.getName())); propertiesObject.addPair(new JsonPair("show_on_map", true)); if (popupContent.length() > 0) propertiesObject.addPair(new JsonPair("popupContent", popupContent)); if (point.getVisibility() != null) { if (point.getVisibility().getMaxTileZoomLevel() < 25) propertiesObject.addPair(new JsonPair("maxZoom", point.getVisibility().getMaxTileZoomLevel())); if (point.getVisibility().getMinTileZoomLevel() > 0) propertiesObject.addPair(new JsonPair("minZoom", point.getVisibility().getMinTileZoomLevel())); } else if (styleVis != null) { //Export Style Visibility, if it exists and the point does not have a Visibility if (styleVis.getMaxTileZoomLevel() < 25) propertiesObject.addPair(new JsonPair("maxZoom", styleVis.getMaxTileZoomLevel())); if (styleVis.getMinTileZoomLevel() > 0) propertiesObject.addPair(new JsonPair("minZoom", styleVis.getMinTileZoomLevel())); } //Add custome data for (PropertyValuePair pvp: point.getAllCustomData()) propertiesObject.addPair(new JsonPair(pvp.getProperty(), pvp.getValue())); geometryObject.addPair(new JsonPair("type", "Point")); geometryObject.addPair(getCoordinatePair(point)); jObject.addPair(new JsonPair("type", "Feature")); jObject.addPair(new JsonPair("properties", propertiesObject)); jObject.addPair(new JsonPair("geometry", geometryObject)); return jObject; } public static JsonObject exportMultiGeometry(DigitalMap mapData, MultiGeometry multi) { JsonObject geometryObject, jObject, propertiesObject; JsonObject[] geometries; jObject = new JsonObject(); propertiesObject = new JsonObject(); geometryObject = new JsonObject(); geometries = new JsonObject[multi.getComponentObjects().size()]; propertiesObject.addPair(new JsonPair("name", multi.getName())); geometryObject.addPair(new JsonPair("type", "GeometryCollection")); for (int i = 0; i < multi.getComponentObjects().size(); i++) { VectorObject obj = multi.getComponentObjects().get(i); geometries[i] = new JsonObject(); if (obj instanceof MapPoint) { geometries[i].addPair(new JsonPair("type", "Point")); } else if (obj instanceof LineString) { geometries[i].addPair(new JsonPair("type", "LineString")); } else if (obj instanceof LinearRing) { geometries[i].addPair(new JsonPair("type", "LineString")); } else if (obj instanceof Polygon) { geometries[i].addPair(new JsonPair("type", "Polygon")); } geometries[i].addPair(getCoordinatePair(obj)); } jObject.addPair(new JsonPair("type", "Feature")); jObject.addPair(new JsonPair("properties", propertiesObject)); jObject.addPair(new JsonPair("geometries", geometryObject)); return jObject; } public static JsonObject exportPolygon(DigitalMap mapData, Polygon poly) { JsonObject geometryObject, jObject, propertiesObject; jObject = new JsonObject(); propertiesObject = new JsonObject(); geometryObject = new JsonObject(); propertiesObject.addPair(new JsonPair("name", poly.getName())); geometryObject.addPair(new JsonPair("type", "Polygon")); geometryObject.addPair(getCoordinatePair(poly)); jObject.addPair(new JsonPair("type", "Feature")); jObject.addPair(new JsonPair("properties", propertiesObject)); jObject.addPair(new JsonPair("geometry", geometryObject)); return jObject; } public static JsonObject exportVectorObject(DigitalMap mapData, VectorObject obj) { JsonObject objectJson = new JsonObject(); if (obj instanceof MapPoint) { objectJson = exportMapPoint(mapData, (MapPoint) obj); } else if (obj instanceof LineString) { objectJson = exportLineString(mapData, (LineString) obj); } else if (obj instanceof LinearRing) { objectJson = exportLinearRing(mapData, (LinearRing) obj); } else if (obj instanceof Polygon) { objectJson = exportPolygon(mapData, (Polygon) obj); } else if (obj instanceof MultiGeometry) { objectJson = exportMultiGeometry(mapData, (MultiGeometry) obj); } else { } return objectJson; } /** * Returns a JsonPair containing all the coordinates for an object. * * @param obj A vector object to extract coordinates from. * @return The JsonPair containing all the coordinates. */ public static JsonPair getCoordinatePair(VectorObject obj) { CoordinateList<Coordinate> coordinateList = obj.getCoordinateList(); JsonCoordinate[] coordinateArray = new JsonCoordinate[coordinateList.size()]; for (int i = 0; i < coordinateList.size(); i++) { Coordinate c = coordinateList.get(i); coordinateArray[i] = new JsonCoordinate(c.getLongitude(), c.getLatitude(), c.getAltitude()); } return new JsonPair("coordinates", (JsonCoordinate[]) coordinateArray); } }