package org.osmdroid.bonuspack.kml; import android.os.Parcel; import android.os.Parcelable; import com.google.gson.JsonElement; import com.google.gson.JsonNull; import com.google.gson.JsonObject; import org.osmdroid.util.BoundingBox; import org.osmdroid.util.GeoPoint; import org.osmdroid.views.MapView; import org.osmdroid.views.overlay.Marker; import org.osmdroid.views.overlay.Overlay; import org.osmdroid.views.overlay.Polygon; import org.osmdroid.views.overlay.Polyline; import java.io.Writer; import java.util.ArrayList; import java.util.Map; import java.util.Set; /** * KML Placemark. Support the following Geometry: Point, LineString, and Polygon. * @author M.Kergall */ public class KmlPlacemark extends KmlFeature implements Cloneable, Parcelable { /** the KML Geometry of the Placemark. Null if none. */ public KmlGeometry mGeometry; /** constructs a Placemark of unknown Geometry */ public KmlPlacemark(){ super(); } /** * constructs a Placemark with a Point Geometry. * @param position position of the Point */ public KmlPlacemark(GeoPoint position){ this(); mGeometry = new KmlPoint(position); } /** constructs a Placemark from a Marker, as a KML Point */ public KmlPlacemark(Marker marker){ this(marker.getPosition()); mName = marker.getTitle(); mDescription = marker.getSnippet(); mVisibility = marker.isEnabled(); //TODO: Style / IconStyle => transparency, hotspot, bearing. } /** constructs a Placemark from a Polygon overlay, as a KML Polygon */ public KmlPlacemark(Polygon polygon, KmlDocument kmlDoc){ this(); mName = polygon.getTitle(); mDescription = polygon.getSnippet(); mGeometry = new KmlPolygon(); mGeometry.mCoordinates = (ArrayList<GeoPoint>)polygon.getPoints(); ((KmlPolygon)mGeometry).mHoles = (ArrayList<ArrayList<GeoPoint>>)polygon.getHoles(); mVisibility = polygon.isEnabled(); //Style: Style style = new Style(); style.mPolyStyle = new ColorStyle(polygon.getFillColor()); style.mLineStyle = new LineStyle(polygon.getStrokeColor(), polygon.getStrokeWidth()); mStyle = kmlDoc.addStyle(style); } /** constructs a Placemark from a Polyline overlay, as a KML LineString */ public KmlPlacemark(Polyline polyline, KmlDocument kmlDoc){ this(); mName = polyline.getTitle(); mDescription = polyline.getSnippet(); mGeometry = new KmlLineString(); mGeometry.mCoordinates = (ArrayList<GeoPoint>)polyline.getPoints(); mVisibility = polyline.isEnabled(); //Style: Style style = new Style(); style.mLineStyle = new LineStyle(polyline.getColor(), polyline.getWidth()); mStyle = kmlDoc.addStyle(style); } /** GeoJSON constructor */ public KmlPlacemark(JsonObject json){ this(); if (json.has("id")) mId = json.get("id").getAsString(); JsonElement element = json.get("geometry"); if (element != null && !element.isJsonNull()) { JsonObject geometry = element.getAsJsonObject(); mGeometry = KmlGeometry.parseGeoJSON(geometry); } if (json.has("properties")){ //Parse properties: element = json.get("properties"); if (!element.isJsonNull()) { JsonObject properties = json.getAsJsonObject("properties"); Set<Map.Entry<String, JsonElement>> entrySet = properties.entrySet(); for (Map.Entry<String, JsonElement> entry : entrySet) { String key = entry.getKey(); JsonElement je = entry.getValue(); String value; try { value = je.getAsString(); } catch (Exception e) { value = je.toString(); } if (key != null && value != null) setExtendedData(key, value); } //Put "name" property in standard KML format: if (mExtendedData != null && mExtendedData.containsKey("name")) { mName = mExtendedData.get("name"); mExtendedData.remove("name"); } } } } @Override public BoundingBox getBoundingBox(){ if (mGeometry != null) return mGeometry.getBoundingBox(); else return null; } @Override public Overlay buildOverlay(MapView map, Style defaultStyle, Styler styler, KmlDocument kmlDocument){ if (mGeometry != null) return mGeometry.buildOverlay(map, defaultStyle, styler, this, kmlDocument); else return null; } @Override public void writeKMLSpecifics(Writer writer){ if (mGeometry != null) mGeometry.saveAsKML(writer); } protected JsonObject geoJSONProperties(){ try { JsonObject json = new JsonObject(); if (mName != null){ json.addProperty("name", mName); } if (mExtendedData != null){ for (Map.Entry<String, String> entry : mExtendedData.entrySet()) { String name = entry.getKey(); String value = entry.getValue(); json.addProperty(name, value); } } return json; } catch (Exception e) { e.printStackTrace(); return null; } } /** @return this as a GeoJSON object. */ @Override public JsonObject asGeoJSON(boolean isRoot){ JsonObject json = new JsonObject(); json.addProperty("type", "Feature"); if (mId != null) json.addProperty("id", mId); if (mGeometry != null) json.add("geometry", mGeometry.asGeoJSON()); else json.add("geometry", JsonNull.INSTANCE); json.add("properties", geoJSONProperties()); return json; } //Cloneable implementation ------------------------------------ @Override public KmlPlacemark clone(){ KmlPlacemark kmlPlacemark = (KmlPlacemark)super.clone(); if (mGeometry != null) kmlPlacemark.mGeometry = mGeometry.clone(); return kmlPlacemark; } //Parcelable implementation ------------ @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeParcelable(mGeometry, flags); } public static final Creator<KmlPlacemark> CREATOR = new Creator<KmlPlacemark>() { @Override public KmlPlacemark createFromParcel(Parcel source) { return new KmlPlacemark(source); } @Override public KmlPlacemark[] newArray(int size) { return new KmlPlacemark[size]; } }; public KmlPlacemark(Parcel in){ super(in); mGeometry = in.readParcelable(KmlGeometry.class.getClassLoader()); } }