Нарисуйте географически точную дугу на карте для Android

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

До сих пор я пробовал Google Maps для Android. Mapbox для Android. ARCGIS для Android. Кажется, никто из них не может выполнить эту простую задачу.

Я предполагаю, что мне нужно какое-то наложение?

введите описание изображения здесь введите описание изображения здесь

2 ответа

Решение

Прежде всего, вы должны изменить представление геоданных.

Из этого:

36 ° 46'02,5 "S 174 ° 50'03,6"E    GRC
36°56'18.3"S    174°33'09.7"E    CWA    36°52'19.2"S    174°29'23.5"E    5.0'    NM
36°48'19,8 "S 174 ° 25'37,7"E    GRC
36°41'06,1 "ю.ш. 174 ° 37'32,9" в.д. с. 36 ° 39'54,5 "ю.ш. 174 ° 38'40,7" в.
36°41'00.3"S    174°39'57.1"E    GRC
36°39'49.4"ю.ш. 174 ° 41'32.3" в.д. С. 36 ° 38'43.5 "ю.ш. 174 ° 40'15.7" в.д. 1,5 'м.д.
36°39'17.5"S    174°41'59.7"E    GRC
36°39'38.6"S    174°44'37.7"E    GRC
36°37'08,8 "S 174 ° 47'27,4"E    CWA    36°42'03,8 "S 174 ° 46'17,0" E 5,0 'НМ

К этому:

-36,76736 174,83433 СФБ -36,93842 174,55269 КАМ -36,87200 174,48986 0,08333 Н.М. -36,80550 174,42714 СФБ -36,68503 174,62581 ССА -36,66514 174,64464 0,02500 Н.М. -36,68342 174,66586 СФБ -36,66372 174,69231 ССА -36,64542 174,67103 0,02500 Н.М. -36,65486 174,69992 174,74381 -36,66072 СФБ СФБ -36,61911 174,79094 CWA    -36,70106 174,77139 0,08333 НМ

Затем вы можете использовать их для построения пути (например, SVG-путь):

<svg
  ...>
  <g
     transform="matrix(1250,0,0,1250,46206.909,-217995.49)"
     ...>
    <path
       d=" M -36.76736,174.83433 L -36.93842,174.55269 A 0.08333,0.08333 0 0,1 -36.80550,174.42714 L -36.68503,174.62581 A 0.02500,0.02500 0 0,0 -36.68342,174.66586 L -36.66372,174.69231 A 0.02500,0.02500 0 0,0 -36.65486,174.69992 L -36.66072,174.74381 L -36.61911,174.79094 A 0.08333,0.08333 0 0,1 -36.76736,174.83433 Z"
       .../>
  </g>
</svg>

Пример SVG

На самом деле, в GMaps / OSMDroid нет API для создания кривых, дуг и т. Д., Поэтому вы должны нарисовать их как можно большим количеством маленьких линий. Это значит, что нужно заняться математикой, но эта математика может быть сделана библиотекой GeographicLib:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    MapView map = (MapView) findViewById(R.id.map);
    map.setTileSource(TileSourceFactory.MAPNIK);
    map.setBuiltInZoomControls(true);
    map.setMultiTouchControls(true);


    IMapController mapController = map.getController();
    mapController.setZoom(9);
    GeoPoint startPoint = new GeoPoint(-36.66372, 174.69231);
    mapController.setCenter(startPoint);

    Polygon polyline = new Polygon(this);
    List<GeoPoint> points = new LinkedList<>();

    // I filled the data manually, but it can be done more clever, of course.
    GRC(points, new GeoPoint(-36.76736, 174.83433));
    CWA(points, new GeoPoint(-36.93842, 174.55269),
                new GeoPoint(-36.87200, 174.48986),
                new GeoPoint(-36.80550, 174.42714),
                0.08333);
    CCA(points, new GeoPoint(-36.68503, 174.62581),
                new GeoPoint(-36.66514, 174.64464),
                new GeoPoint(-36.68342, 174.66586),
                0.02500);
    CCA(points, new GeoPoint(-36.66372, 174.69231),
                new GeoPoint(-36.64542, 174.67103),
                new GeoPoint(-36.65486, 174.69992),
                0.02500);
    GRC(points, new GeoPoint(-36.66072, 174.74381));
    CWA(points, new GeoPoint(-36.61911, 174.79094),
                new GeoPoint(-36.70106, 174.77139),
                new GeoPoint(-36.76736, 174.83433), //close shape going to the start point
                0.08333);

    polyline.setPoints(points);
    polyline.setFillColor(0xA0FF00FF);
    polyline.setStrokeColor(Color.BLACK);
    polyline.setStrokeWidth(2f);
    map.getOverlays().add(polyline);
    map.invalidate();
}

private void CCA(List<GeoPoint> points, GeoPoint startPoint, GeoPoint centerPoint, GeoPoint endPoint, double radius) {
    points.add(startPoint);

    GeodesicData f = Geodesic.WGS84.Inverse(centerPoint.getLatitude(), centerPoint.getLongitude(), startPoint.getLatitude(), startPoint.getLongitude());
    GeodesicData t = Geodesic.WGS84.Inverse(centerPoint.getLatitude(), centerPoint.getLongitude(), endPoint.getLatitude(), endPoint.getLongitude());

    double ffaz = f.azi1;
    double tfaz = t.azi1;

    final int decrement = 1;
    while (Math.abs((int)ffaz) != Math.abs((int)tfaz)) {
        GeodesicData llb = Geodesic.WGS84.Direct(centerPoint.getLatitude(), centerPoint.getLongitude(), ffaz,  f.s12);
        points.add(new GeoPoint(llb.lat2, llb.lon2));
        ffaz -= decrement;
        if (ffaz <0) {
            ffaz += 360;
        }
    }

    points.add(endPoint);
}

private void CWA(List<GeoPoint> points, GeoPoint startPoint, GeoPoint centerPoint, GeoPoint endPoint, double radius) {
    points.add(startPoint);

    GeodesicData f = Geodesic.WGS84.Inverse(centerPoint.getLatitude(), centerPoint.getLongitude(), startPoint.getLatitude(), startPoint.getLongitude());
    GeodesicData t = Geodesic.WGS84.Inverse(centerPoint.getLatitude(), centerPoint.getLongitude(), endPoint.getLatitude(), endPoint.getLongitude());

    double ffaz = f.azi1;
    double tfaz = t.azi1 > 0 ? t.azi1 : 360 + t.azi1;

    final int increment = 1;
    while (Math.abs((int)ffaz) != Math.abs((int)tfaz)) {
        GeodesicData llb = Geodesic.WGS84.Direct(centerPoint.getLatitude(), centerPoint.getLongitude(), ffaz, f.s12);
        points.add(new GeoPoint(llb.lat2, llb.lon2));
        ffaz += increment;
        if (ffaz>360) {
            ffaz -= 360;
        }
    }

    points.add(endPoint);
}

private void GRC(List<GeoPoint> points, GeoPoint geoPoint) {
    points.add(geoPoint);
}

Я использовал osmdroid+OSMBonusPack, но код достаточно универсален и может быть легко использован с Google Maps.

Полный исходный код.

Результат:

https://raw.githubusercontent.com/lassana/osmdroid-shape-extention/master/media/device-2016-04-01-195435.png

Кроме того, не могли бы вы рассказать, какие геоданные вы разместили? Думаю, фигура на карте выглядит как зона разрешенного полета.

К сожалению, я не могу дать вам полный ответ прямо сейчас, так как этот вопрос требует серьезной математики, и я не могу полностью понять данные, которые вы показали в таблице. Я предполагаю, что вы пытаетесь получить конечный результат, который выглядит примерно так. Если это так, у вас есть центральная точка, радиус и дуга, начиная с LatLng и заканчивая LatLng (это также можно рассчитать по центральной точке с помощью дополнительной математики). Я постараюсь обновить этот ответ, если у меня будет возможность написать некоторый код для математической стороны. Насколько я знаю, ни одна из библиотек карт (Google Maps, Mapbox) не включает это.

По сути, я бы написал метод, который возвращает множество точек, следующих за дугой, которую вы хотите нарисовать. Из этого я бы нарисовал линию, используя addPolyline метод.

// Draw line from list of LatLng called pointsArray
mapView.addPolyline(new PolylineOptions()
        .add(pointsArray)
        .color(Color.parseColor("#3bb2d0"))
        .width(2));

Надеюсь, это поможет вам, по крайней мере, с самого начала, и, как я уже сказал, я постараюсь добавить математические биты позже, если у меня будет шанс.

Другие вопросы по тегам