package mil.nga.giat.asam.map; import java.util.ArrayList; import java.util.Collection; import mil.nga.giat.asam.R; import android.app.ProgressDialog; import android.content.Context; import android.os.AsyncTask; import android.util.Log; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Polygon; import com.google.android.gms.maps.model.PolygonOptions; import com.google.android.gms.maps.model.TileOverlay; import com.google.android.gms.maps.model.TileOverlayOptions; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.MultiPolygon; public class OfflineMap { private static int FILL_COLOR = 0xFFDDDDDD; private Context mContext; private GoogleMap mMapUI; private Collection<Geometry> mOfflineFeatures; private TileOverlay backgroundTileOverlay; private Collection<Polygon> offlinePolygons = null; private ProgressDialog progressDialog; public OfflineMap(Context context, GoogleMap map, Collection<Geometry> offlineFeatures) { this.mContext = context; this.mMapUI = map; this.mOfflineFeatures = offlineFeatures; loadOfflineMaps(); } public void clear() { backgroundTileOverlay.clearTileCache(); backgroundTileOverlay.remove(); for (Polygon polygon : offlinePolygons) { polygon.remove(); } offlinePolygons.clear(); } private void loadOfflineMaps() { OfflineMapsTask task = new OfflineMapsTask(); task.execute(mOfflineFeatures.toArray(new Geometry[mOfflineFeatures.size()])); } private class OfflineMapsTask extends AsyncTask<Geometry, Void, Collection<PolygonOptions>> { @Override protected void onPreExecute() { progressDialog = ProgressDialog.show(mContext, mContext.getString(R.string.offline_map_progress_dialog_title_text), mContext.getString(R.string.offline_map_progress_dialog_content_text), true); mMapUI.setMapType(GoogleMap.MAP_TYPE_NONE); BackgroundTileProvider tileProvider = new BackgroundTileProvider(mContext); backgroundTileOverlay = mMapUI.addTileOverlay(new TileOverlayOptions().tileProvider(tileProvider).zIndex(1).visible(false)); backgroundTileOverlay.setVisible(true); } @Override protected Collection<PolygonOptions> doInBackground(Geometry... features) { Collection<PolygonOptions> polygons = new ArrayList<PolygonOptions>(features.length); for (Geometry feature : features) { if (feature instanceof com.vividsolutions.jts.geom.Polygon) { polygons.add(generatePolygon((com.vividsolutions.jts.geom.Polygon)feature)); } else if(feature instanceof com.vividsolutions.jts.geom.MultiPolygon) { MultiPolygon multiPolygon = (MultiPolygon)feature; for(int i = 0; i < multiPolygon.getNumGeometries(); i++) { Geometry geometry = multiPolygon.getGeometryN(i); if(geometry instanceof com.vividsolutions.jts.geom.Polygon) { polygons.add(generatePolygon((com.vividsolutions.jts.geom.Polygon)geometry)); } //nested MultiPolygons are ignored for now. Recursive solution has performance implications. } } } return polygons; } @Override protected void onPostExecute(Collection<PolygonOptions> polygons) { offlinePolygons = new ArrayList<Polygon>(polygons.size()); for (PolygonOptions polygon : polygons) { offlinePolygons.add(mMapUI.addPolygon(polygon)); } progressDialog.dismiss(); } /** * Utility method for generating PolygonOptions from a Polygon. * @param pPolygon A Polygon to generate. * @return A fully constructed PolygonOptions object complete with style and * z-index positioning. */ private PolygonOptions generatePolygon(com.vividsolutions.jts.geom.Polygon pPolygon) { PolygonOptions options = new PolygonOptions() .visible(true) .zIndex(2) .fillColor(FILL_COLOR) .strokeWidth(0); //Exterior Polygon for (Coordinate coordinate : pPolygon.getExteriorRing().getCoordinates()) { options.add(new LatLng(coordinate.y, coordinate.x)); } //Interior Polygons for (int i = 0; i < pPolygon.getNumInteriorRing(); i++) { Coordinate[] coordinates = pPolygon.getInteriorRingN(0).getCoordinates(); Collection<LatLng> hole = new ArrayList<LatLng>(coordinates.length); for (Coordinate coordinate : coordinates) { hole.add(new LatLng(coordinate.y, coordinate.x)); } options.addHole(hole); } return options; } } }