Android: MapController.zoomToSpan: Hacer span dado una distancia y punto central
He estado investigando esto en Google y SO, pero estoy atascado, creo que estoy perdiendo algo fundamental. La mayoría de los ejemplos que he visto no se ocupan de un mapWidth arbitrario y un único punto, sólo el lapso de una superposición.
Tengo una base de datos de puntos del mapa, un MapView
y un Geocoder
. Puedo buscar un código postal en mi aplicación y tener una Address
devuelta por mi Geocoder
.
- NullpointerException al llamar a getSystemService (Context.LOCATION_SERVICE) y onLocationChanged no se llama
- Obtenga latitud y longitud de la base de datos SQLite para usarla en Android MapOverlay
- Creación de superposición personalizada en el mapa
- Android GoogleMap o SupportMapFragment - excepción de puntero nulo
- El mapa de Google no muestra nada en el mapa
Usando esta Address
, puedo construir un GeoPoint
y buscar en mi DB y recuperar una lista de puntos cercanos. El problema viene de tratar de zoomToSpan utilizando un intervalo construido desde el punto de Address
devuelto y la distancia al punto más cercano en la base de datos.
Sólo quiero que el intervalo abarque los dos puntos más cercanos (si están disponibles). Aquí está el código relevante:
Collections.sort(listingDisplay, mComparator); listingDisplayAdapter.notifyDataSetChanged(); float spanWidth =0; if (listingDisplay.size() > 1) { spanWidth = (float) (2 * distanceFromPoint(listingDisplay.get(1), current)); } else if (listingDisplay.size() == 1) { spanWidth = (float) (2 * distanceFromPoint(listingDisplay.get(0), current)); } Log.v(TAG, "SpanWidth: " + spanWidth); // Create span int minLat = (int) (current.getLatitudeE6() - (spanWidth * 1E6) / 2); int maxLat = (int) (current.getLatitudeE6() + (spanWidth * 1E6) / 2); int minLong = (int) (current.getLongitudeE6() - (spanWidth * 1E6) / 2); int maxLong = (int) (current.getLongitudeE6() + (spanWidth * 1E6) / 2); // Zoom against span. This appears to create a very small region that doesn't encompass the points mapController.setCenter(current); mapController.zoomToSpan(Math.abs( minLat - maxLat ), Math.abs( minLong - maxLong ));
ListingDisplay
contiene una lista de los puntos más cercanos, con un comparador, mComparator
clasificando esta lista con las ubicaciones más cercanas a mi Address
devuelta (el GeoPoint
llamado: current
) en la parte superior de la lista.
A continuación, establecer el valor de spanWidth
basado en el más cercano, y tratar de averiguar el span de esto.
Mi pregunta es, ¿cómo puedo construir un tramo desde una distancia dada y un punto central ?
- Referencia MapView en SupportMapFragment
- ActionBarSherlock + Maps + Loaders = java.lang.NoClassDefFoundError
- Lo que hace que mi fragmento de mapa de carga lento?
- Map v2 SupportMapFragment dentro de Viewpager
- MapView en un fragmento (Honeycomb)
- Android: Establecer el nivel de zoom en Google Maps para incluir todos los puntos marcadores
- Google Maps y las aplicaciones con mapview tienen diferentes posiciones actuales
- ¿Modo nocturno para los mapas de Google?
Después de un tiempo muy, muy largo, finalmente me di cuenta de que no estaba considerando alguna información importante, principalmente entre ellos fue el hecho de que las distancias en Android se calculan utilizando el elipsoide WGS84.
Terminé usando los métodos auxiliares dentro de la excelente y simple clase de GeoLocation de Jan Matuschek , la cual viene con una explicación muy completa de los conceptos involucrados.
Mi método esencialmente se redujo a lo siguiente. Probablemente se puede optimizar una buena cantidad, hasta una simple consulta SQL, pero aquí es para mis propósitos, donde listingDisplay
es una matriz de objetos de LocationNode
personalizados recuperados de base de datos y la corriente de GeoPoint
se crea directamente desde una Address
devuelta de un Android estándar Geocoder.
public void setRegionForGeoPoint(GeoPoint current) { // Earth radius in KM final double EARTH_RADIUS = 6371.01; // Dummy span distance in KM for initial search; distance buffer is in M final double DISTANCE_BUFFER = 50; final double dummyDistance = 100.0; //Create a list to store distances List<Double> distancesList = new ArrayList<Double>(); // Loop through and modify LocationNodes with distance from user for (LocationNode location : listingDisplay) { location.setDistance((float) distanceFromUser(location)); // Dynamically calculate distance from our current point (epicentre) distancesList.add(distanceFromPoint(location, current)); } // Sort distances Collections.sort(distancesList); // Calculate regional span float spanWidth = (float) dummyDistance; double distance = 0; if (distancesList.size() > 0) { if (distancesList.size() > 1) { distance = distancesList.get(1); spanWidth = (float) (distance + DISTANCE_BUFFER); } else if (distancesList.size() == 1) { distance = distancesList.get(0); spanWidth = (float) (distance + DISTANCE_BUFFER); } //Obtain the spanwidth in metres. double spanWidthInKM = (double) spanWidth / 1000; // Create span GeoLocation[] boundingBoxSpan = currentGeoLocation .boundingCoordinates(spanWidthInKM, EARTH_RADIUS); //Create min/max values for final span calculation int minLatSpan = (int) (boundingBoxSpan[0].getLatitudeInDegrees() * 1E6); int maxLatSpan = (int) (boundingBoxSpan[1].getLatitudeInDegrees() * 1E6); int minLongSpan = (int) (boundingBoxSpan[0].getLongitudeInDegrees() * 1E6); int maxLongSpan = (int) (boundingBoxSpan[1].getLongitudeInDegrees() * 1E6); //Finally calculate span int latSpanE6 = Math.abs(minLatSpan - maxLatSpan); int lonSpanE6 = Math.abs(minLongSpan - maxLongSpan); // Set center mapController.setCenter(current); // Zoom to span mapController.zoomToSpan(latSpanE6, lonSpanE6); } else { //TODO: Handle the case when we have no distance values to use } } public double distanceFromPoint(LocationNode location, GeoPoint point) { // Calculate distance from user via result Location locationA = new Location("point A"); locationA.setLatitude(location.getLatitude()); locationA.setLongitude(location.getLongitude()); Location locationB = new Location("point B"); locationB.setLatitude((double) (point.getLatitudeE6() / 1E6)); locationB.setLongitude((double) (point.getLongitudeE6() / 1E6)); double distance = locationA.distanceTo(locationB); Log.v(TAG, "Calculated Distance: " + distance); return distance; }
- Configuración que no se eliminan cuando se desinstala la aplicación
- Android: Limpiar correctamente después de OpenGL