package org.osmdroid.bonuspack.kml; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.os.Parcel; import android.os.Parcelable; import com.google.gson.JsonObject; import org.apache.commons.lang3.StringEscapeUtils; import org.osmdroid.bonuspack.overlays.GroundOverlay; import org.osmdroid.bonuspack.utils.BonusPackHelper; import org.osmdroid.util.BoundingBox; import org.osmdroid.util.GeoPoint; import org.osmdroid.views.MapView; import org.osmdroid.views.overlay.Overlay; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.util.ArrayList; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * KML GroundOverlay. * * mCoordinates contains the LatLonBox as 2 GeoPoints: North-West, and South-East. * * @author M.Kergall */ public class KmlGroundOverlay extends KmlFeature implements Cloneable, Parcelable { /** Overlay Icon href */ public String mIconHref; /** Overlay Icon bitmap (can be null) */ public Bitmap mIcon; /** Overlay color */ public int mColor; /** GroundOverlay rotation - default = 0 */ public float mRotation; /** NW and SE points - TODO: not the simplest way to handle that... */ public ArrayList<GeoPoint> mCoordinates; public KmlGroundOverlay(){ super(); mColor = 0xFF000000; } /** Constructs the KML feature from a GroundOverlay. */ public KmlGroundOverlay(GroundOverlay overlay){ this(); GeoPoint p = overlay.getPosition(); GeoPoint pN = p.destinationPoint(overlay.getHeight()/2, 0.0f); GeoPoint pS = p.destinationPoint(overlay.getHeight()/2, 180.0f); GeoPoint pE = p.destinationPoint(overlay.getWidth()/2, 90.0f); GeoPoint pW = p.destinationPoint(overlay.getWidth()/2, -90.0f); mCoordinates = new ArrayList<GeoPoint>(2); mCoordinates.add(new GeoPoint(pN.getLatitude(), pW.getLongitude())); //NW mCoordinates.add(new GeoPoint(pS.getLatitude(), pE.getLongitude())); //SE //mIconHref = ??? mIcon = ((BitmapDrawable)overlay.getImage()).getBitmap(); mRotation = -overlay.getBearing(); mColor = 255 - Color.alpha((int)(overlay.getTransparency()*255)); mVisibility = overlay.isEnabled(); } @Override public BoundingBox getBoundingBox(){ return BoundingBox.fromGeoPoints(mCoordinates); } /** load the icon from its href. * @param href either the full url, or a relative path to a local file. * @param containerFile the KML container file - or null if irrelevant. * @param kmzContainer current KMZ file (as a ZipFile) - or null if irrelevant. */ public void setIcon(String href, File containerFile, ZipFile kmzContainer){ mIconHref = href; if (mIconHref.startsWith("http://") || mIconHref.startsWith("https://")){ mIcon = BonusPackHelper.loadBitmap(mIconHref); } else if (kmzContainer == null) { if (containerFile != null){ String actualFullPath = containerFile.getParent()+'/'+mIconHref; mIcon = BitmapFactory.decodeFile(actualFullPath); } else mIcon = null; } else { try { final ZipEntry fileEntry = kmzContainer.getEntry(href); InputStream stream = kmzContainer.getInputStream(fileEntry); mIcon = BitmapFactory.decodeStream(stream); } catch (Exception e) { mIcon = null; } } } public void setLatLonBox(double north, double south, double east, double west){ mCoordinates = new ArrayList<GeoPoint>(2); mCoordinates.add(new GeoPoint(north, west)); mCoordinates.add(new GeoPoint(south, east)); } /** @return the corresponding GroundOverlay ready to display on the map */ @Override public Overlay buildOverlay(MapView map, Style defaultStyle, Styler styler, KmlDocument kmlDocument){ GroundOverlay overlay = new GroundOverlay(); if (mCoordinates.size()==2){ GeoPoint pNW = mCoordinates.get(0); GeoPoint pSE = mCoordinates.get(1); overlay.setPosition(GeoPoint.fromCenterBetween(pNW, pSE)); GeoPoint pNE = new GeoPoint(pNW.getLatitude(), pSE.getLongitude()); int width = pNE.distanceTo(pNW); GeoPoint pSW = new GeoPoint(pSE.getLatitude(), pNW.getLongitude()); int height = pSW.distanceTo(pNW); overlay.setDimensions((float)width, (float)height); } //TODO: else if size=4, nonrectangular quadrilateral if (mIcon != null){ overlay.setImage(new BitmapDrawable(mIcon)); //TODO: not clearly defined in KML spec, but color is supposed to be blended with the image. float transparency = 1.0f - Color.alpha(mColor)/255.0f; //KML transparency is the transparency part of the "color" element. overlay.setTransparency(transparency); } else { //when no image available, set it as a rectangle filled with the KML color Bitmap bitmap = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888); bitmap.eraseColor(mColor); overlay.setImage(new BitmapDrawable(bitmap)); } overlay.setBearing(-mRotation); //from KML counterclockwise to Google Maps API which is clockwise if (styler == null) overlay.setEnabled(mVisibility); else styler.onFeature(overlay, this); return overlay; } /** write elements specific to GroundOverlay in KML format */ @Override public void writeKMLSpecifics(Writer writer){ try { writer.write("<color>"+ColorStyle.colorAsKMLString(mColor)+"</color>\n"); writer.write("<Icon><href>"+StringEscapeUtils.escapeXml10(mIconHref)+"</href></Icon>\n"); writer.write("<LatLonBox>"); GeoPoint pNW = mCoordinates.get(0); GeoPoint pSE = mCoordinates.get(1); writer.write("<north>"+pNW.getLatitude()+"</north>"); writer.write("<south>"+pSE.getLatitude()+"</south>"); writer.write("<east>"+pSE.getLongitude()+"</east>"); writer.write("<west>"+pNW.getLongitude()+"</west>"); writer.write("<rotation>"+mRotation+"</rotation>"); writer.write("</LatLonBox>\n"); } catch (IOException e) { e.printStackTrace(); } } @Override public JsonObject asGeoJSON(boolean isRoot) { //TODO: GroundOverlay is not supported by GeoJSON. Output enclosing polygon with mColor? return null; } //Cloneable implementation ------------------------------------ public KmlGroundOverlay clone(){ KmlGroundOverlay kmlGroundOverlay = (KmlGroundOverlay)super.clone(); kmlGroundOverlay.mCoordinates = KmlGeometry.cloneArrayOfGeoPoint(mCoordinates); return kmlGroundOverlay; } //Parcelable implementation ------------ @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeString(mIconHref); out.writeParcelable(mIcon, flags); out.writeInt(mColor); out.writeFloat(mRotation); out.writeList(mCoordinates); } public static final Creator<KmlGroundOverlay> CREATOR = new Creator<KmlGroundOverlay>() { @Override public KmlGroundOverlay createFromParcel(Parcel source) { return new KmlGroundOverlay(source); } @Override public KmlGroundOverlay[] newArray(int size) { return new KmlGroundOverlay[size]; } }; public KmlGroundOverlay(Parcel in){ super(in); mIconHref = in.readString(); mIcon = in.readParcelable(Bitmap.class.getClassLoader()); mColor = in.readInt(); mRotation = in.readFloat(); mCoordinates = in.readArrayList(GeoPoint.class.getClassLoader()); } }