2010-08-02 18 views
8

Cuando desarrollo una aplicación de mapa de Android, quiero dibujar un círculo en el mapa cuyo radio es de 1 metro. Como sabías, no puedo dibujar 1 metro directamente, debería convertir 1 metro a la distancia de dos píxeles dependiendo del nivel de zoom. Cómo lo convierto, ¿hay algo de API que pueda usar?¿Cómo cambiar la distancia de 1 metro a píxel?

Canvas.draw (x, y, radius), ¿qué valor debo poner a este método?

+1

si quieres convertir 1 metro a dos píxeles, y quieres un radio de 1 metro, entonces quieres pasar '2' al parámetro' radius'. Ahora, dices * depende del nivel de zoom *, así que supongo que tendrás que pasar algo como '2 * (zoomLevel * zoomLevelCoefficient)' –

+0

Esta fue una pregunta interesante, ¿encontraste una solución que funcionaba para ti? – Idistic

Respuesta

3

Tres preguntas tienes que pedir permiso 1- ¿Qué tan grande es su mapa 2- ¿Cuál es su nivel de zoom 3- ¿Qué tan grande es su pantalla

Vamos a hacer la suposición de que el mapa tiene la misma relación de aspecto como su pantalla (si no es así, debe preocuparse por qué manera de recortar (en realidad, horizontalmente) o qué forma de estirar y luego cambiar nuestra respuesta a 1)

Una vez que tenga la respuesta 1 y 3 puede trabajar la relación entre los metros y los píxeles en la caja del zoom al 100%, por lo que tendrá un píxeles por metro

continuación, tiene que mantener un factor de zoom (por ejemplo: el zoom de doble tamaño es 200%)

su llamada para dibujar el círculo se verá así

Canvas.draw(x,y, radius_in_meters * pixels_per_meter * zoom_factor/100); 
+0

Encontrar píxeles por metro es el quid de esta pregunta. ¿Qué tan grande es su mapa es probable que se responda fácilmente de una manera latitud por longitud, no píxeles al cuadrado. ¿Cómo pasas de latxlon a píxeles cuadrados? – jamesh

9

Suponiendo que su mapa es Google Maps, utilizan la proyección de Mercator, por lo que necesitaría usar eso para la conversión. Bajo la proyección de Mercator, la distancia que un píxel representa en metros varía con la latitud, por lo que mientras que un metro es una distancia muy pequeña en comparación con el radio de la Tierra, la latitud es importante.

Todos los ejemplos a continuación son javascript, por lo que puede que necesite traducirlos.

Aquí es una explicación general del sistema de coordenadas:

http://code.google.com/apis/maps/documentation/javascript/maptypes.html#WorldCoordinates

Este ejemplo contiene un objeto de Proyección de Mercator, que incluye los métodos fromLatLngToPoint() y fromPointToLatLng():

http://code.google.com/apis/maps/documentation/javascript/examples/map-coordinates.html

Una vez que haya convertido su (x, y) a (lat, lon), esta es la forma de dibujar un círculo:

// Pseudo code 
var d = radius/6378800; // 6378800 is Earth radius in meters 
var lat1 = (PI/180)* centerLat; 
var lng1 = (PI/180)* centerLng; 

// Go around a circle from 0 to 360 degrees, every 10 degrees 
for (var a = 0 ; a < 361 ; a+=10) { 
    var tc = (PI/180)*a; 
    var y = asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc)); 
    var dlng = atan2(sin(tc)*sin(d)*cos(lat1),cos(d)-sin(lat1)*sin(y)); 
    var x = ((lng1-dlng+PI) % (2*PI)) - PI ; 
    var lat = y*(180/PI); 
    var lon = x*(180/PI); 

    // Convert the lat and lon to pixel (x,y) 
} 

Estos dos mashups dibujar un círculo de un radio dado en la superficie de la Tierra:

http://maps.forum.nu/gm_sensitive_circle2.html

http://maps.forum.nu/gm_drag_polygon.html

Si decide hacer caso omiso de la proyección a continuación, tendrá que utilizar coordenadas cartesianas y simplemente dibuje el círculo usando el Teorema de Pitágoras:

http://en.wikipedia.org/wiki/Circle#Cartesian_coordinates

8

Eche un vistazo al objeto Projection en la API. Tiene un método llamado metrosParaEquivarPíxeles(). Dada la descripción en la API, podría ser solo precisa a lo largo del ecuador, pero pensé que valía la pena mencionarla en caso de que la precisión no fuera un problema para ti.

Aquí está la forma de utilizar esta dentro del método de estiramiento de la superposición, dado el radio en metros y la latitud y longitud del lugar donde desea dibujar el círculo:

Projection projection = mapView.getProjection(); 
Point center = projection.toPixels(new GeoPoint(yourLat * E6, yourLong * E6), null); 
float radius = projection.metersToEquatorPixels(radiusInMeters); 
canvas.draw(center.x, center.y, radius, new Paint()); 
+0

Puede que le interese este tema, que ofrece una fórmula simple para compensar la distorsión de Mercator: http://stackoverflow.com/questions/2077054/how-to-compute-a-radius-around-a-point-in -an-android-mapview – Gromix

2
public static int metersToRadius(float meters, MapView map, double latitude) { 
    return (int) (map.getProjection().metersToEquatorPixels(meters) * (1/ Math.cos(Math.toRadians(latitude))));   
} 
1

se puede calcular el nivel de zoom para el radio que desea:

Primero debemos calcular el ancho de la pantalla del teléfono. En el nivel de zoom 1, el ecuador de la Tierra tiene 256 píxeles de largo y cada nivel de zoom duplica la cantidad de píxeles necesarios para representar tierra ecuador. La siguiente función devuelve el nivel de zoom donde la pantalla mostrará un área de 1Km de ancho.

private int calculateZoomLevel() { 

    int ht, screenWidth; 
    DisplayMetrics displaymetrics = new DisplayMetrics(); 
    getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); 
    ht = displaymetrics.heightPixels; 
    screenWidth = displaymetrics.widthPixels; 

    double equatorLength = 40075004; // in meters 
    double widthInPixels = screenWidth; 
    double metersPerPixel = equatorLength/256; 
    int zoomLevel = 1; 
    while ((metersPerPixel * widthInPixels) > 1000) { 
     metersPerPixel /= 2; 
     ++zoomLevel; 
    } 

    Log.i(tag, "zoom level = " + zoomLevel); 
    return zoomLevel; 
} 
Cuestiones relacionadas