在Android的地图视图上画一个特定半径的圆形

17

我想在地图视图上绘制一个圆形。 我希望用户输入半径,然后我要在地图上显示该半径的圆形。 接下来,我必须在该圆周围的某些位置上显示标记。

我知道如何在地图视图上显示标记。

我应该如何在地图视图上绘制圆形并显示在圆周边缘的标记?


这个库可能会有所帮助 - https://github.com/i-schuetz/map_areas - User
6个回答

35

只是为了更新一下...他们在Google Maps API v2上让这变得非常容易。

    mMap.addCircle(new CircleOptions()
        .center(center)
        .radius(radius)
        .strokeWidth(0f)
        .fillColor(0x550000FF));

半径单位为米。

至于边界上的标记,这应该相对容易实现-只需按照Google Maps示例代码中的“圆形”演示进行操作:https://developers.google.com/maps/documentation/android/intro#sample_code


好的,圆被画出来了。但是我想获取那个画出的圆的经纬度点,因为我想搜索一些新属性,这些属性位于所画圆形区域内。请问有人可以帮助我如何实现这个功能吗?! - Mahe
这将是被接受的答案,不错的帮助。 @Mahe 不清楚。 - Noman
工作室显示无法解析方法 radius(double)... :( - Ashish Shukla
半径参数值是浮点数,而不是双精度。 - ByteSlinger

10

如果有人在寻找使用Google Maps API v2的答案,这是我所做的简短片段。它实际上更多的是一种地理方法。

public class MapDrawer {

private GoogleMap map;
private static int EARTH_RADIUS = 6371000;

public MapDrawer(GoogleMap map) {
    this.map = map;
}

private LatLng getPoint(LatLng center, int radius, double angle) {
    // Get the coordinates of a circle point at the given angle
    double east = radius * Math.cos(angle);
    double north = radius * Math.sin(angle);

    double cLat = center.latitude;
    double cLng = center.longitude;
    double latRadius = EARTH_RADIUS * Math.cos(cLat / 180 * Math.PI);

    double newLat = cLat + (north / EARTH_RADIUS / Math.PI * 180);
    double newLng = cLng + (east / latRadius / Math.PI * 180);

    return new LatLng(newLat, newLng);
}

public Polygon drawCircle(LatLng center, int radius) {
    // Clear the map to remove the previous circle
    map.clear();
    // Generate the points
    List<LatLng> points = new ArrayList<LatLng>();
    int totalPonts = 30; // number of corners of the pseudo-circle
    for (int i = 0; i < totalPonts; i++) {
        points.add(getPoint(center, radius, i*2*Math.PI/totalPonts));
    }
    // Create and return the polygon
    return map.addPolygon(new PolygonOptions().addAll(points).strokeWidth(2).strokeColor(0x700a420b));
}

好处是,在缩放或平移地图后,你无需重新绘制任何内容 - 圆圈会相应地调整大小和移动位置。不足之处是,如果你想在北极或南极的其中一个位置上画一个圆圈 - 它会变得不稳定,但是,希望99%的时间不会出现这种情况 :)


嗨@Grisha S,我遇到了一个问题,我想在我的标记周围画一个圆圈,当用户缩放时它会变大或缩小,我认为这段代码可以工作,但是我该如何调用这个类以及要发送到您所制作的函数的参数是什么......如果您看到这个,请帮忙一下.........谢谢 - Salman Khan
1
2 @SalmanKhan:是的,这段代码应该适用于你的情况。首先,使用你想要绘制的GoogleMap对象实例化类:MapDrawer mapDrawer = new MapDrawer(map); 然后调用drawCircle方法,给它传入:1)一个指定所需绘制圆形中心地理坐标的LatLng对象,2)一个表示以米为单位的圆形半径的整数。 - Grisha S
首先感谢Grisha的回复,这对我很有帮助。但是每次我将圆形添加到地图上时,所有标记都会消失。当我注释掉drawCircle方法的调用时,它又会显示出所有标记。我不知道问题出在哪里,请问你能帮我吗? - Salman Khan
@SalmanKhan,问题出在我的代码中的“map.clear()”这一行 - 它会擦除之前绘制在地图上的所有内容。我需要它只是因为在我的情况下,我必须擦除先前绘制的圆并用新的圆替换它。只需删除此行,一切就会好 :) - Grisha S
如果我将totalPoints增加到100,会有任何性能问题吗? - amithgc
1
@AmithGC,我不确定,但你可以检查一下。我打赌在这个数字小于1000的时候,性能差别不大,尽管我不能确定。 - Grisha S

8
在实现ItemizedOverlay时,可以像onDraw方法中的drawCircle方法一样执行某些操作。
protected void drawCircle(Canvas canvas, Point curScreenCoords) {
    curScreenCoords = toScreenPoint(curScreenCoords);
    int CIRCLE_RADIUS = 50;
    // Draw inner info window
    canvas.drawCircle((float) curScreenCoords.x, (float) curScreenCoords.y, CIRCLE_RADIUS, getInnerPaint());
    // if needed, draw a border for info window
    canvas.drawCircle(curScreenCoords.x, curScreenCoordsy, CIRCLE_RADIUS, getBorderPaint());
}

private Paint innerPaint, borderPaint;

public Paint getInnerPaint() {
    if (innerPaint == null) {
        innerPaint = new Paint();
        innerPaint.setARGB(225, 68, 89, 82); // gray
        innerPaint.setAntiAlias(true);
    }
    return innerPaint;
}

public Paint getBorderPaint() {
    if (borderPaint == null) {
        borderPaint = new Paint();
        borderPaint.setARGB(255, 68, 89, 82);
        borderPaint.setAntiAlias(true);
        borderPaint.setStyle(Style.STROKE);
        borderPaint.setStrokeWidth(2);
    }
    return borderPaint;
}

@Override
protected void onDraw(Canvas canvas) {
    Point p = new Point();
    for(OverlayItem item : items) {
        drawCircle(canvas, getProjection().toPixels(item.getPoint(), p));
    }
}

如果您正在使用ItemizedOverlay,它也有一个绘制方法,因此同样适用。 - NickT
你如何获取半径等于地球米的画布圆? - Deepak kaku

4

这不是完美的,但我写了一点代码来在地图上绘制一个圆。您可以轻松扩展它以设置圆的颜色等。大多数其他代码示例都没有考虑将缩放级别与圆的大小相匹配,而这是创建圆形时常见的要求。圆半径以米为单位。

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

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

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

2

对于 Kotlin,要在地图中心绘制一个圆形,可以使用以下代码:

mMap.setOnCameraIdleListener {
        val midLatLng: LatLng = mMap.cameraPosition.target

        mMap.addCircle(CircleOptions()
                .center(midLatLng)
                .radius(radiusInMeters)
                .strokeWidth(1f)
                .fillColor(0x880000FF))
}

mMap 是指 GoogleMap


0
如果您在覆盖层的绘画方法中加入以下代码,它会在地图视图中心绘制一个半径为20像素的圆形。
@Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
long when) {
    ....
    ....

    Paint lp4;
    lp4 = new Paint();
    lp4.setColor(Color.RED);
    lp4.setAntiAlias(true);
    lp4.setStyle(Style.STROKE);
    canvas.drawCircle(mapView.getWidth()/2, mapView.getHeight()/2, 20, lp4);

    ....
    ....
    mapView.invalidate();
}

你应该能够根据自己的需求进行适应


我假设你有一个类MapOverlay,它扩展了com.google.android.maps.Overlay以绘制你的标记。这将具有一个超类方法'draw',其参数为mapView和canvas。按照所述覆盖此方法的draw,然后在画布上绘制圆形。 - NickT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接