Как изменить расстояние в 1 метр на пиксель?

Когда я разрабатываю приложение карты Android, я хочу нарисовать круг на карте с радиусом 1 метр. Как вы знаете, я не могу нарисовать 1 метр напрямую, я должен преобразовать 1 метр на расстояние двух пикселей в зависимости от уровня масштабирования. Как его преобразовать, есть ли какой-нибудь API, который я могу использовать.

Canvas.draw (x, y, radius), какое значение я должен использовать для этого метода?

Предполагая, что ваша карта – Карты Google, они используют проекцию Mercator, поэтому вам нужно будет использовать ее для преобразования. Под проекцией Меркатора расстояние, которое пиксель представляет в метрах, варьируется в зависимости от широты, поэтому, когда метр является очень маленьким расстоянием по сравнению с радиусом Земли, широта важна.

Все приведенные ниже примеры – это javascript, поэтому вам может потребоваться их перевести.

Вот общее объяснение системы координат:

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

Этот пример содержит объект MercatorProjection, который включает методы fromLatLngToPoint () и fromPointToLatLng ():

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

Как только вы преобразуете свои (x, y) в (lat, lon), вы рисуете круг:

 // 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) } 

Эти два mashups нарисовали окружность заданного радиуса на поверхности Земли:

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

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

Если вы решите проигнорировать проекцию, вы должны использовать декартовы координаты и просто нарисовать круг, используя теорему Пифагора:

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

Взгляните на объект Projection в api. У него есть метод, называемый meterToEquatorPixels (). Учитывая описание в api, он может быть точным только вдоль экватора, но я думал, что стоит упомянуть, если точность не была проблемой для вас.

Вот способ использовать это в методе рисования вашего наложения, учитывая радиус в метрах и широту и долготу того места, где вы хотите нарисовать круг:

 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()); 

Три вопроса, которые вы задали 1. Насколько велика ваша карта. 2. Каков уровень масштабирования. 3. Насколько велика ваш экран.

Предположим, что карта имеет тот же формат изображения, что и ваш экран (если нет, то вам нужно беспокоиться о том, какой способ обрезать (по-видимому, горизонтально) или каким образом растянуть, а затем изменить наш ответ на 1)

После того, как вы ответите 1 и 3, вы можете определить соотношение между метрами и пикселями в футляре масштаба 100%, поэтому у вас будет пиксель на метр

Затем вам нужно сохранить коэффициент масштабирования (например: увеличение двойного размера – 200%)

Ваш призыв рисовать круг будет выглядеть следующим образом:

  Canvas.draw(x,y, radius_in_meters * pixels_per_meter * zoom_factor/100); 
 public static int metersToRadius(float meters, MapView map, double latitude) { return (int) (map.getProjection().metersToEquatorPixels(meters) * (1/ Math.cos(Math.toRadians(latitude)))); } 

Вы можете рассчитать уровень масштабирования для нужного радиуса:

Сначала нам нужно рассчитать ширину экрана телефона. На уровне увеличения 1 экватор Земли имеет длину 256 пикселей, а каждый последующий уровень увеличения удваивает количество пикселей, необходимых для представления экватора Земли. Следующая функция возвращает уровень масштабирования, где на экране будет отображаться область шириной 1Km.

 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; }