在 Android MapView 上画一个圆

发布于 2024-10-21 11:49:50 字数 1833 浏览 5 评论 0原文

这是我的解决方案:

编辑:更新以反映 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()));

希望这会有所帮助。

Got it fixed here is my solution:

Edit: updated to reflect robguinness answer.

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

}

To "Draw" it needs to be added to the maps overlays

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

Hope this helps.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

青丝拂面 2024-10-28 11:49:50

接受的答案有错误。我试图纠正它,但我的编辑由于某种奇怪的原因被拒绝。无论如何,这里是一个正确的答案:

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

Scott 答案中的问题是,circleRadius 是使用一种将赤道处的点从米转换为像素的方法来计算的。但是,如果您想要的点不在赤道上,则半径将太小,因为转换没有考虑经线在两极汇聚的事实。不过,这可以通过乘以 (1/ FloatMath.cos((float) Math.toRadians(mLat))) 来纠正,这是我对 Scott 原始答案所做的唯一更改。

我希望这对某人有帮助,因为我以艰难的方式发现了这个问题。我住在芬兰,在那里使用原始方法,画出的圆圈比应有的小约两倍!

The accepted answer has an error. I attempted to correct it, but my edit was rejected for some strange reason. In any case, here is a corrected answer:

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

The problem in Scott's answer is that the circleRadius was calculated using a method that converts from meters to pixels for points at the equator. If, however, your desired point is not on the equator, the radius will be too small because the conversion does not account for the fact that meridians come together at the poles. This can be corrected, however, by multiplying by (1/ FloatMath.cos((float) Math.toRadians(mLat))), which is the only change that I made to Scott's original answer.

I hope this helps someone because I discovered the problem the hard way. I live in Finland, where using the original method, the circles were drawn ~2 times smaller than they should have been!

揪着可爱 2024-10-28 11:49:50

我采用了上面的示例并将其扩展为考虑到需要根据地图缩放级别进行缩放的圆圈(即:相对于地面距离的圆圈)。

有些人可能会发现它很有用。

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

I've taken the above sample and expanded it to take into account circles which need to be scaled with the map zoom level (ie: circles relative to ground distance).

Some people might find it useful.

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);
    }
}
楠木可依 2024-10-28 11:49:50
  1. 您要显示的地理点是(0.1275、51.507222)吗?这是索马里海岸附近的某个地方。

  2. super.draw(..) 应该是 draw() 方法中的第一个语句。

  1. Is the geo point you are trying to show (0.1275, 51.507222)? This is somewhere off the coast of Somalia.

  2. super.draw(..) should be the first statement in your draw() method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文