Нарисовать круг на Android MapView

165
13

Исправлено это мое решение:


Изменить: обновлено, чтобы отразить ответ robguinness.


import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;

public class CircleOverlay extends Overlay {

Context context;
double mLat;
double mLon;
float mRadius;

public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
context = _context;
mLat = _lat;
mLon = _lon;
mRadius = radius;
}

public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
context = _context;
mLat = _lat;
mLon = _lon;
mRadius = radius;
}

public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);

if(shadow) return; // Ignore the shadow layer

Projection projection = mapView.getProjection();

Point pt = new Point();

GeoPoint geo = new GeoPoint((int) (mLat *1e6), (int)(mLon * 1e6));

projection.toPixels(geo ,pt);
float circleRadius = projection.metersToEquatorPixels(mRadius) * (1/ FloatMath.cos((float) Math.toRadians(mLat)));

Paint innerCirclePaint;

innerCirclePaint = new Paint();
innerCirclePaint.setColor(Color.BLUE);
innerCirclePaint.setAlpha(25);
innerCirclePaint.setAntiAlias(true);

innerCirclePaint.setStyle(Paint.Style.FILL);

canvas.drawCircle((float)pt.x, (float)pt.y, circleRadius, innerCirclePaint);
}


}


Чтобы "нарисовать" его нужно добавить в наложения карт


mMapView.getOverlays().add(new CircleOverlay(context, loc.getLatitude(),loc.getLongitude()));

Надеюсь, что это поможет.

спросил(а) 2011-03-14T04:00:00+03:00 9 лет, 7 месяцев назад
1
Решение
120

В принятом ответе есть ошибка. Я попытался исправить это, но мое редактирование было отклонено по какой-то странной причине. В любом случае, это исправленный ответ:


import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;

public class CircleOverlay extends Overlay {

Context context;
double mLat;
double mLon;
float mRadius;

public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
context = _context;
mLat = _lat;
mLon = _lon;
mRadius = radius;
}

public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
context = _context;
mLat = _lat;
mLon = _lon;
mRadius = radius;
}

public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);

if(shadow) return; // Ignore the shadow layer

Projection projection = mapView.getProjection();

Point pt = new Point();

GeoPoint geo = new GeoPoint((int) (mLat *1e6), (int)(mLon * 1e6));

projection.toPixels(geo ,pt);
float circleRadius = projection.metersToEquatorPixels(mRadius) * (1/ FloatMath.cos((float) Math.toRadians(mLat)));

Paint innerCirclePaint;

innerCirclePaint = new Paint();
innerCirclePaint.setColor(Color.BLUE);
innerCirclePaint.setAlpha(25);
innerCirclePaint.setAntiAlias(true);

innerCirclePaint.setStyle(Paint.Style.FILL);

canvas.drawCircle((float)pt.x, (float)pt.y, circleRadius, innerCirclePaint);
}
}

Проблема в ответе Скотта заключается в том, что circleRadius был рассчитан с использованием метода, который преобразуется из метров в пиксели для точек на экваторе. Если, однако, ваша желаемая точка не находится на экваторе, радиус будет слишком мал, потому что преобразование не учитывает тот факт, что меридианы собираются вместе на полюсах. Это можно исправить, однако, путем умножения на (1/ FloatMath.cos((float) Math.toRadians(mLat))), что является единственным изменением, которое я сделал для исходного ответа Скотта.


Я надеюсь, что это поможет кому-то, потому что я обнаружил проблему с трудом. Я живу в Финляндии, где, используя оригинальный метод, круги были нарисованы в 2 раза меньше, чем они должны были быть!

ответил(а) 2012-08-21T17:41:00+04:00 8 лет, 2 месяца назад
115

Я взял вышеприведенный образец и расширил его, чтобы учесть круги, которые нужно масштабировать с помощью уровня масштабирования карты (т.е. кругов относительно расстояния до земли).


Некоторые люди могут найти это полезным.

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;

public class CircleOverlay extends Overlay {

Context context;
double mLat;
double mLon;
float mRadius;

public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
context = _context;
mLat = _lat;
mLon = _lon;
mRadius = radius;
}

public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);

if(shadow) return; // Ignore the shadow layer

Projection projection = mapView.getProjection();

Point pt = new Point();

GeoPoint geo = new GeoPoint((int) (mLat *1e6), (int)(mLon * 1e6));

projection.toPixels(geo ,pt);
float circleRadius = projection.metersToEquatorPixels(mRadius) * (1/ FloatMath.cos((float) Math.toRadians(mLat)));

Paint innerCirclePaint;

innerCirclePaint = new Paint();
innerCirclePaint.setColor(Color.BLUE);
innerCirclePaint.setAlpha(25);
innerCirclePaint.setAntiAlias(true);

innerCirclePaint.setStyle(Paint.Style.FILL);

canvas.drawCircle((float)pt.x, (float)pt.y, circleRadius, innerCirclePaint);
}
}

ответил(а) 2012-05-04T08:39:00+04:00 8 лет, 5 месяцев назад
41

    Является ли точка геометрии, которую вы пытаетесь показать (0.1275, 51.507222)? Это где-то недалеко от побережья Сомали.


    super.draw(..) должен быть первым выражением в вашем методе draw().


ответил(а) 2011-03-14T04:24:00+03:00 9 лет, 7 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема