Android Maps API v2 draw circle

后端 未结 6 1892
旧时难觅i
旧时难觅i 2020-11-30 02:18

Having the following code to draw circle (taken from Google Play Services \"maps\" sample):

    PolylineOptions options = new PolylineOptions();
    int radi         


        
相关标签:
6条回答
  • 2020-11-30 02:33

    Google made is simple in maps v2. The snippet below demonstrates both drawing markers and circles along with updating their positions together.

    private Circle mCircle;
    private Marker mMarker;
    private GoogleMap mGoogleMap;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mGoogleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.mapFragment)).getMap();
        mGoogleMap.setMyLocationEnabled(true);
        mGoogleMap.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
            @Override
            public void onMyLocationChange(Location location) {
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
                if(mCircle == null || mMarker == null){
                    drawMarkerWithCircle(latLng);
                }else{
                    updateMarkerWithCircle(latLng);
                }
            }
        });
    }
    
    private void updateMarkerWithCircle(LatLng position) {
        mCircle.setCenter(position);
        mMarker.setPosition(position);
    }
    
    private void drawMarkerWithCircle(LatLng position){
        double radiusInMeters = 100.0;
        int strokeColor = 0xffff0000; //red outline
        int shadeColor = 0x44ff0000; //opaque red fill
    
        CircleOptions circleOptions = new CircleOptions().center(position).radius(radiusInMeters).fillColor(shadeColor).strokeColor(strokeColor).strokeWidth(8);
        mCircle = mGoogleMap.addCircle(circleOptions);
    
        MarkerOptions markerOptions = new MarkerOptions().position(position);
        mMarker = mGoogleMap.addMarker(markerOptions);
    }
    
    0 讨论(0)
  • 2020-11-30 02:33

    Yesterday Android Developer team intoduced Google Play service v3. Abuse it! ;) https://developers.google.com/maps/documentation/android/shapes#circles

    0 讨论(0)
  • 2020-11-30 02:36

    Android 2.0 API you can use CircleOption to draw a circle, works really well, no messy conversions of pixels to meters.

    public CircleOptions getCircleOptions() {
        CircleOptions co = new CircleOptions();
        co.center(latlng);
        co.radius(getCircleSize());
        co.fillColor(getCircleColor());
        co.strokeColor(getStrokeColor());
        co.strokeWidth(2.0f);
        return co;
    }
    
        Circle circle = mapView.getMap().addCircle(munzeeMarker.getCircleOptions());
    
    0 讨论(0)
  • 2020-11-30 02:40

    Here's my code, just for added variation. I haven't found a way to solve the problems with antialiasing or shape simplification:

    // Make a circle of latitude and longitude points.
    // Radius is in metres.
    // Probably won't work if the circle is large or near the poles.
    private ArrayList<LatLng> makeCircle(LatLng centre, double radius)
    {
        ArrayList<LatLng> points = new ArrayList<LatLng>();
    
        double EARTH_RADIUS = 6378100.0;
        // Convert to radians.
        double lat = centre.latitude * Math.PI / 180.0;
        double lon = centre.longitude * Math.PI / 180.0;
    
        for (double t = 0; t <= Math.PI * 2; t += 0.1)
        {
            // y
            double latPoint = lat + (radius / EARTH_RADIUS) * Math.sin(t);
            // x
            double lonPoint = lon + (radius / EARTH_RADIUS) * Math.cos(t) / Math.cos(lat);
            points.add(new LatLng(latPoint * 180.0 / Math.PI, lonPoint * 180.0 / Math.PI));
        }
    
        return points;
    }
    

    Explanation of maths

    Google Earth uses the Mercator projection which means that physical circles do not appear as circles on the map - instead they are distorted as shown in the question. The closer to the poles you go the more distorted they are. To draw a circle on the map but with coordinates given in latitude/longitude we need to invert the distortion.

    First we find the centre of the circle in radians - that is pretty simple and is stored in lat and lon.

    Then we go around the circle finding points on its edge. If we were making a physical circle, the latitude and longitude of each point is just:

            double latPoint = lat + (radius / EARTH_RADIUS) * Math.sin(t);
            double lonPoint = lon + (radius / EARTH_RADIUS) * Math.cos(t);
    

    That's pretty simple trigonometry. The (radius / EARTH_RADIUS) is the angular radius of the circle in radians (e.g. a circle with a radius of 100 m would have an angular radius of 0.000015 rad).

    If we used that simple code we would find that the circle shown on the map was squished by cos(lat) horizontally, so we simply divide by cos(lat) to unsquish it.

    We could equally have done this:

            double latPoint = lat + (radius / EARTH_RADIUS) * Math.sin(t) * Math.cos(lat);
            double lonPoint = lon + (radius / EARTH_RADIUS) * Math.cos(t);
    

    Resulting in a large circle - it depends whether the radius function parameter refers to latitude or longitude.

    This explanation could use some diagrams but I can't be bothered, sorry.

    0 讨论(0)
  • 2020-11-30 02:54

    How to draw circle in Google Maps v2 (bitmap)

    // 1. some variables:
    
        private static final double EARTH_RADIUS = 6378100.0;
        private int offset;
    
    // 2. convert meters to pixels between 2 points in current zoom:
    
        private int convertMetersToPixels(double lat, double lng, double radiusInMeters) {
    
             double lat1 = radiusInMeters / EARTH_RADIUS;
             double lng1 = radiusInMeters / (EARTH_RADIUS * Math.cos((Math.PI * lat / 180)));
    
             double lat2 = lat + lat1 * 180 / Math.PI;
             double lng2 = lng + lng1 * 180 / Math.PI; 
    
             Point p1 = YourActivity.getMap().getProjection().toScreenLocation(new LatLng(lat, lng));
             Point p2 = YourActivity.getMap().getProjection().toScreenLocation(new LatLng(lat2, lng2));
    
             return Math.abs(p1.x - p2.x);
        }
    
    // 3. bitmap creation:
    
        private Bitmap getBitmap() {
    
            // fill color
            Paint paint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint1.setColor(0x110000FF);
            paint1.setStyle(Style.FILL);
    
            // stroke color
            Paint paint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint2.setColor(0xFF0000FF);
            paint2.setStyle(Style.STROKE);
    
            // icon
            Bitmap icon = BitmapFactory.decodeResource(YourActivity.getResources(), R.drawable.blue);
    
            // circle radius - 200 meters
            int radius = offset = convertMetersToPixels(lat, lng, 200);
    
            // if zoom too small
            if (radius < icon.getWidth() / 2) {
    
                radius = icon.getWidth() / 2;
            }
    
            // create empty bitmap 
            Bitmap b = Bitmap.createBitmap(radius * 2, radius * 2, Config.ARGB_8888);
            Canvas c = new Canvas(b);
    
            // draw blue area if area > icon size
            if (radius != icon.getWidth() / 2) {
    
                c.drawCircle(radius, radius, radius, paint1);
                c.drawCircle(radius, radius, radius, paint2);
            }
    
            // draw icon
            c.drawBitmap(icon, radius - icon.getWidth() / 2, radius - icon.getHeight() / 2, new Paint());
    
            return b;
        }
    
    // 4. calculate image offset:
    
        private LatLng getCoords(double lat, double lng) {
    
            LatLng latLng = new LatLng(lat, lng);
    
            Projection proj = YourActivity.getMap().getProjection();
            Point p = proj.toScreenLocation(latLng);
            p.set(p.x, p.y + offset);
    
            return proj.fromScreenLocation(p);
        }
    
    // 5. draw:
    
            MarkerOptions options = new MarkerOptions();
                options.position(getCoords(lat, lng));
                options.icon(BitmapDescriptorFactory.fromBitmap(getBitmap()));
    
                marker = YourActivity.getMap().addMarker(options);
    

    and result:

    google maps v2 draw circle

    0 讨论(0)
  • 2020-11-30 02:54

    Google today, Feb 26, just released Circle as an overlay type.

    https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/model/Circle

    0 讨论(0)
提交回复
热议问题