Android: MapController.zoomToSpan: make a range given at a distance and in the center

I studied this on Google and SO, but I'm stuck, I think I don't have something fundamental. Most of the examples that I saw are not related to an arbitrary mapWidth and one point, but simply to the Overlay range.

I have a database of map points, MapView and Geocoder . I can find the zip code in my application and have the Address returned by my Geocoder .

Using this Address , I can build a GeoPoint and search in my database and return a list of nearby points. The problem is an attempt to scale using a span built from the returned Address point and the distance to the nearest point in the database.

I want the range to cover the next two points (if available). Here is the relevant code:

 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 contains a list of nearest points with the mComparator comparator, sorting this list with the closest locations to my returned Address ( GeoPoint called: current ) at the top of the list.

Then I set the spanWidth value based on the closest value and try to figure out the range from that.

My question is: how can I build a span from a given distance and center point ?

+4
source share
1 answer

After a very, very long time, I finally realized that I was not considering any important information, mainly among them the fact that the distances on Android were calculated using the WGS84 ellipsoid.

I ended up using helper methods inside Jan Matuchek an excellent and simple GeoLocation class that contains a very detailed explanation of the concepts involved.

My method essentially boiled down to the following. It can probably be optimized quite simply, down to a simple SQL query, but here it is for my purposes, where listingDisplay is an array of user-created LocationNode objects and the GeoPoint current GeoPoint generated directly from the returned Address standard Android geocoding.

 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; } 
+5
source

Source: https://habr.com/ru/post/1398156/


All Articles