Неправильные расстояния при создании случайных локаций

Я пытаюсь создать случайные местоположения рядом с моим местоположением. Я хочу создать случайные пары широта/долгота внутри 200-метрового круга, окружающего мое местоположение. Задав этот вопрос: генерировать случайные местоположения рядом с моим местоположением это то, что у меня есть придумать.

в onLocationChanged вот что я делаю:

private void updateWithNewLocation(Location location) {
    if (location != null) {
        this.myItemizedOverlay.clear();
        this.nonPlayerItemizedOverlay.clear();
        this.mapOverlays.clear();
        // Update my map location.
        Double latitude = location.getLatitude() * 1E6;
        Double longitude = location.getLongitude() * 1E6;
        GeoPoint geoPoint = new GeoPoint(latitude.intValue(),
                longitude.intValue());

        CustomOverlayItem pcOverlayItem = new CustomOverlayItem(geoPoint,
                "", "", "");

        this.mapController.animateTo(geoPoint);

        this.myItemizedOverlay.setLocation(location);
        this.myItemizedOverlay.addOverlay(pcOverlayItem);
        this.mapOverlays.add(this.myItemizedOverlay);

        // Everytime i get a new location i generate random non player
        // characters near my location
        int numberOfNonPlayers = new Random().nextInt(5);

        for (int i = 0; i < numberOfNonPlayers; i++) {
            int radius = (int) this.myMapView.getProjection()
                    .metersToEquatorPixels(200);
            double lowerLimit = -1;
            double upperLimit = 1;

            Double newLatitude = location.getLatitude()
                    * 1E6
                    + (radius * (lowerLimit + (Math.random() * ((upperLimit - lowerLimit) + 1))));
            Double newLongitude = location.getLongitude()
                    * 1E6
                    + (radius * (lowerLimit + (Math.random() * ((upperLimit - lowerLimit) + 1))));

            GeoPoint geoPoint2 = new GeoPoint(newLatitude.intValue(),
                    newLongitude.intValue());

            CustomOverlayItem npcOverlayItem = new CustomOverlayItem(
                    geoPoint2, "", "", "");

            Location newLocation = new Location("npc " + i);
            newLocation.setLatitude(newLatitude);
            newLocation.setLongitude(newLongitude);

            this.nonPlayerItemizedOverlay = new NonPlayerItemizedOverlay(
                    this.nonPlayerDrawable, this.myMapView);
            this.nonPlayerItemizedOverlay.setLocation(newLocation);
            this.nonPlayerItemizedOverlay.addOverlay(npcOverlayItem);
            this.mapOverlays.add(this.nonPlayerItemizedOverlay);
        }
    }
}

А это мой класс NonPlayerItemizedOverlay:

public class NonPlayerItemizedOverlay extends BaseItemizedOverlay {

public NonPlayerItemizedOverlay(Drawable defaultMarker, MapView mapView) {
    super(defaultMarker, mapView);
    // TODO Auto-generated constructor stub
}

private Location location;

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

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

    if (shadow == false) {
        Projection projection = mapView.getProjection();

        // Get the current location
        Double latitude = location.getLatitude();
        Double longitude = location.getLongitude();
        GeoPoint geoPoint = new GeoPoint(latitude.intValue(),
                longitude.intValue());

        // Convert the location to screen pixels
        Point point = new Point();
        projection.toPixels(geoPoint, point);

        // int radius = metersToRadius(30, mapView, latitude);
        int radius = (int) mapView.getProjection()
                .metersToEquatorPixels(50);

        RectF oval = new RectF(point.x - radius, point.y - radius, point.x
                + radius, point.y + radius);

        // Setup the paint
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStrokeWidth(2.0f);

        paint.setColor(0xffE62020);
        paint.setStyle(Style.STROKE);
        canvas.drawOval(oval, paint);

        paint.setColor(0x18E62020);
        paint.setStyle(Style.FILL);
        canvas.drawOval(oval, paint);
    }
}

public Location getLocation() {
    return location;
}

public void setLocation(Location location) {
    this.location = location;
}

И мой класс MyItemizedOverlay:

public class MyItemizedOverlay extends BaseItemizedOverlay {

public MyItemizedOverlay(Drawable defaultMarker, MapView mapView) {
    super(defaultMarker, mapView);
    // TODO Auto-generated constructor stub
}

private Location location;

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

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

    if (shadow == false) {
        Projection projection = mapView.getProjection();

        // Get the current location
        Double latitude = location.getLatitude() * 1E6;
        Double longitude = location.getLongitude() * 1E6;
        GeoPoint geoPoint = new GeoPoint(latitude.intValue(),
                longitude.intValue());

        // Convert the location to screen pixels
        Point point = new Point();
        projection.toPixels(geoPoint, point);

        // int radius = metersToRadius(100, mapView, latitude);
        int radius = (int) mapView.getProjection().metersToEquatorPixels(
                200);

        RectF oval = new RectF(point.x - radius, point.y - radius, point.x
                + radius, point.y + radius);

        // Setup the paint
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStrokeWidth(2.0f);

        paint.setColor(0xff6666ff);
        paint.setStyle(Style.STROKE);
        canvas.drawOval(oval, paint);

        paint.setColor(0x186666ff);
        paint.setStyle(Style.FILL);
        canvas.drawOval(oval, paint);
    }
}

public Location getLocation() {
    return location;
}

public void setLocation(Location location) {
    this.location = location;
}

Дело в том, что происходит что-то странное, потому что все случайные локации слишком близки к моему центру локации, кажется, что формула не покрывает весь радиус, и я думаю, что расстояния не в реальных метрах.

Любая идея о том, что может быть не так с моей формулой?

заранее спасибо


person pindleskin    schedule 21.05.2012    source источник
comment
Я не эксперт по картографическим проекциям, но эти ребята могут быть: gis.stackexchange.com   -  person Tony the Pony    schedule 21.05.2012
comment
Спасибо, Тони, эта ссылка действительно помогла мне. Если вы напишете ответ с ним, я отмечу его как принятый   -  person pindleskin    schedule 22.05.2012


Ответы (2)


По вопросам, касающимся картографических проекций и расчетов координат, может быть полезен этот сайт SE: http://gis.stackexchange.com (геоинформационные системы).

person Tony the Pony    schedule 22.05.2012

Чтобы быть уверенным, используйте формулу DistanceTo() класса местоположения. Вы можете сделать это следующим образом:

double distance  = a.distanceTo(b);

где a и b — объекты Location.

person NiVeR    schedule 21.05.2012
comment
Спасибо. После проверки расстояния указаны в реальных метрах. Теперь кажется, что я создаю локации не по всему радиусу, а по половине. - person pindleskin; 21.05.2012