package org.osmdroid.bonuspack.overlays; import android.graphics.Canvas; import org.osmdroid.bonuspack.utils.BonusPackHelper; import org.osmdroid.util.BoundingBox; import org.osmdroid.views.MapView; import org.osmdroid.views.overlay.Overlay; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; /** * A Folder overlay implementing 2 advanced features: * * 1) Z-Index to all overlays that it contains. * Like Google Maps Android API: * "An overlay with a larger z-index is drawn over overlays with smaller z-indices. * The order of overlays with the same z-index value is arbitrary. * The default is 0." * Unlike Google Maps Android API, this applies to all overlays, including Markers. * * 2) Drawing optimization based on Bounding Box culling. * * TODO - DO NOT USE YET. WORK IN PROGRESS. * * @author M.Kergall */ public class FolderZOverlay extends Overlay { protected TreeSet<ZOverlay> mList; protected String mName, mDescription; protected class ZOverlay implements Comparator<ZOverlay> { float mZIndex; BoundingBox mBoundingBox; boolean mBoundingBoxSet; Overlay mOverlay; public ZOverlay(Overlay o, float zIndex){ mOverlay = o; mZIndex = zIndex; mBoundingBoxSet = false; } @Override public int compare(ZOverlay o1, ZOverlay o2){ return (int)Math.signum(o1.mZIndex - o2.mZIndex); } public void setBoundingBox(BoundingBox bb){ mBoundingBox = BonusPackHelper.cloneBoundingBox(bb); mBoundingBoxSet = true; } public void unsetBoundingBox(){ mBoundingBox = null; mBoundingBoxSet = false; } /** * @param mapBB bounding box of the map view * @param mapOrientation orientation of the map view * @return true if the overlay should be drawn. */ public boolean shouldBeDrawn(BoundingBox mapBB, float mapOrientation){ if (!mBoundingBoxSet) return true; if (mBoundingBox == null) //null bounding box means overlay is empty, so nothing to draw: return false; if (mapOrientation != 0.0f) //TODO - handle map rotation... return true; if (mBoundingBox.getLatSouth() > mapBB.getLatNorth() || mBoundingBox.getLatNorth() < mapBB.getLatSouth() || mBoundingBox.getLonWest() > mapBB.getLonEast() || mBoundingBox.getLonEast() < mapBB.getLonWest()) //completely outside the map view: return false; return true; } } public FolderZOverlay(){ super(); mList = new TreeSet<>(); mName = ""; mDescription = ""; } public void setName(String name){ mName = name; } public String getName(){ return mName; } public void setDescription(String description){ mDescription = description; } public String getDescription(){ return mDescription; } public boolean add(Overlay item, float zIndex){ return mList.add(new ZOverlay(item, zIndex)); } public boolean add(Overlay item){ return add(item, 0); } protected ZOverlay get(Overlay overlay){ Iterator<ZOverlay> itr = mList.iterator(); while (itr.hasNext()) { ZOverlay item = itr.next(); if (item.mOverlay == overlay) { mList.remove(item); return item; } } return null; } public boolean remove(Overlay overlay) { ZOverlay item = get(overlay); if (item != null) { mList.remove(item); return true; } else return false; } /** * Change the Z-Index of an overlay. * @param overlay overlay to change * @param zIndex new Z-Index to set */ public void setZIndex(Overlay overlay, float zIndex){ ZOverlay item = get(overlay); if (item == null) return; mList.remove(item); item.mZIndex = zIndex; //TODO Check if removal/addition is really necessary. mList.add(item); } /** * Define the bounding box of this overlay. * This may dramatically increase drawing performance when the overlay is completely outside the current view. * @param overlay * @param bb the bounding box of this overlay. */ public void setBoundingBox(Overlay overlay, BoundingBox bb){ ZOverlay item = get(overlay); if (item == null) return; item.setBoundingBox(bb); } public void unsetBoundingBox(Overlay overlay){ ZOverlay item = get(overlay); if (item == null) return; item.unsetBoundingBox(); } //TODO: //get highest z-index => getMaxZIndex @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { if (shadow) return; Iterator<ZOverlay> itr=mList.iterator(); while(itr.hasNext()){ ZOverlay item = itr.next(); Overlay overlay = item.mOverlay; if (overlay!=null && overlay.isEnabled()) { if (item.shouldBeDrawn(mapView.getBoundingBox(), mapView.getMapOrientation())) { overlay.draw(canvas, mapView, false); } } } } //TODO Implement events }