Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing circle Android MapBox SDK

Tags:

android

mapbox

I use Android MapBox SDK 5.1.0-SNAPSHOT. How draw circle with coordinates and radius in meters?

Have an idea to draw many-sided polygon. But this is very problematic.

like image 209
V. Gerasimenko Avatar asked May 31 '17 11:05

V. Gerasimenko


Video Answer


2 Answers

As Zugaldia answered it, drawing a circle layer would be the easiest way to do it. But only if you want to draw a circle, disregarding size precision.

The other option would be to draw a circular perimeter around your point, to get correct distances and visualization (if tilting), I'll explain that later.

In Kotlin, sorry not sorry.

First part, drawing a circle layer :

mapView.getMapAsync {
    map = it

    // Add the source (at start, an 'empty' GeoJsonSource)
    map?.addSource(GeoJsonSource(SOURCE_ID))

    // Create a circle layer from previously defined source 
    // don't forget source identifier
    val layer = CircleLayer(CIRCLE_LAYER_ID, SOURCE_ID)
    layer.withProperties(
            circleRadius(50f),
            circleOpacity(.4f),
            circleColor(Color.WHITE)
    )

    map?.addLayer(layer)
}

And at when you possess the position you'd like to draw around :

private fun updateCircleLayer() {
    // Update the GeoJsonSource
    // !!! Beware, (longitude, latitude), not the other way around !!!
    val center = Point.fromCoordinates(doubleArrayOf(longitude, latitude))
    map?.getSourceAs<GeoJsonSource>(SOURCE_ID)?.setGeoJson(center)
}

Second part, drawing a perimeter :

I adapted this algorithm to fit the language and needs : https://stackoverflow.com/a/39006388/4258214

private fun getPerimeterFeature(radiusInKilometers: Double = .05, sides: Int = 64): Feature {
    // here, currentPosition is a class property, get your lat & long as you'd like
    val latitude = currentPosition.latitude
    val longitude = currentPosition.longitude

    val positions = mutableListOf<Position>()

    // these are conversion constants
    val distanceX: Double = radiusInKilometers / (111.319 * Math.cos(latitude * Math.PI / 180))
    val distanceY: Double = radiusInKilometers / 110.574

    val slice = (2 * Math.PI) / sides

    var theta: Double
    var x: Double
    var y: Double
    var position: Position
    for (i in 0..sides) {
        theta = i * slice
        x = distanceX * Math.cos(theta)
        y = distanceY * Math.sin(theta)

        position = Position.fromCoordinates(longitude + x, latitude + y)
        positions.add(position)
    }

    return Feature.fromGeometry(Polygon.fromCoordinates(listOf(positions)))
}

See updateCircleLayer() in the first part to provide returned Feature to the GeoJSonSource and that's it.

Hope this will help. Have fun !

like image 152
Oyzuu Avatar answered Nov 10 '22 02:11

Oyzuu


Based on @Xalamadrax answer, I have simplified his piece of code and translated it in java.

private PolygonOptions generatePerimeter(LatLng centerCoordinates, double radiusInKilometers, int numberOfSides) {
    List<LatLng> positions = new ArrayList<>();
    double distanceX = radiusInKilometers / (111.319 * Math.cos(centerCoordinates.getLatitude() * Math.PI / 180));
    double distanceY = radiusInKilometers / 110.574;

    double slice = (2 * Math.PI) / numberOfSides;

    double theta;
    double x;
    double y;
    LatLng position;
    for (int i = 0; i < numberOfSides; ++i) {
        theta = i * slice;
        x = distanceX * Math.cos(theta);
        y = distanceY * Math.sin(theta);

        position = new LatLng(centerCoordinates.getLatitude() + y,
                centerCoordinates.getLongitude() + x);
        positions.add(position);
    }
    return new PolygonOptions()
            .addAll(positions)
            .fillColor(Color.BLUE)
            .alpha(0.4f);
}

And to add it to the map:

mMapView.getMapAsync(new OnMapReadyCallback() {
    @Override
    public void onMapReady(MapboxMap mapboxMap) {
        mapboxMap.addPolygon(generatePerimeter(
                new LatLng(48.8566d, 2.3522d),
                100,
                64));
    }
});

Edit: I am very new to mapbox so maybe it can be improved.

like image 40
Blablablabli Avatar answered Nov 10 '22 00:11

Blablablabli