Нарисуйте ARC Polyline в Карте Google

Как рисовать дугу из полилинии на карте Google?

Я уже использовал этот код для создания полилинии изогнутой.

Вот метод для рисования криволинейной полилинии:

private void showCurvedPolyline (LatLng p1, LatLng p2, double k) {
    //Calculate distance and heading between two points
    double d = SphericalUtil.computeDistanceBetween(p1,p2);
    double h = SphericalUtil.computeHeading(p1, p2);

    //Midpoint position
    LatLng p = SphericalUtil.computeOffset(p1, d*0.5, h);

    //Apply some mathematics to calculate position of the circle center
    double x = (1-k*k)*d*0.5/(2*k);
    double r = (1+k*k)*d*0.5/(2*k);

    LatLng c = SphericalUtil.computeOffset(p, x, h + 90.0);

    //Polyline options
    PolylineOptions options = new PolylineOptions();
    List<PatternItem> pattern = Arrays.<PatternItem>asList(new Dash(30), new Gap(20));

    //Calculate heading between circle center and two points
    double h1 = SphericalUtil.computeHeading(c, p1);
    double h2 = SphericalUtil.computeHeading(c, p2);

    //Calculate positions of points on circle border and add them to polyline options
    int numpoints = 100;
    double step = (h2 -h1) / numpoints;

    for (int i=0; i < numpoints; i++) {
        LatLng pi = SphericalUtil.computeOffset(c, r, h1 + i * step);
        options.add(pi);
    }

    //Draw polyline
    mMap.addPolyline(options.width(10).color(Color.MAGENTA).geodesic(false).pattern(pattern));
}

ВЫХОД

1. Если я использую this.showCurvedPolyline(latLng1, latLng2, 0.1); затем получение:

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

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

2. Если я использую this.showCurvedPolyline(latLng1, latLng2, 1); затем получение:

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

3. Если я использую LatLng c = SphericalUtil.computeOffset(p, x, h - 90.0); затем получение:

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

Примечание: Я не хочу иметь такую ​​большую форму круга, действительно Я не хочу, чтобы была такая высота.

Вот что Я хочу ARC Shape, как показано на рисунке ниже

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

Вот CODE, который я использую для добавления изогнутой полилинии между двумя geo-locatios:

private void addCurvedPolyLine() {

        LatLng latLng1 = new LatLng(40.7128, 74.0059); // New York
        LatLng latLng2 = new LatLng(51.5074, 0.1278); // London

        Marker marker1 = mMap.addMarker(new MarkerOptions().position(latLng1).title("Start"));
        Marker marker2 = mMap.addMarker(new MarkerOptions().position(latLng2).title("End"));

        LatLngBounds.Builder builder = new LatLngBounds.Builder();

        builder.include(marker1.getPosition());
        builder.include(marker2.getPosition());

        LatLngBounds bounds = builder.build();
        int padding = 0; // offset from edges of the map in pixels
        CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
        mMap.moveCamera(cu);
        mMap.animateCamera(cu);

        this.showCurvedPolyline(latLng1, latLng2, 0.1);

    }

Ответ 1

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

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

public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;

    mMap.getUiSettings().setZoomControlsEnabled(true);

    LatLng latLng1 = new LatLng(40.7128, 74.0059); // New York
    LatLng latLng2 = new LatLng(51.5074, 0.1278); // London

    Marker marker1 = mMap.addMarker(new MarkerOptions().position(latLng1).title("Start"));
    Marker marker2 = mMap.addMarker(new MarkerOptions().position(latLng2).title("End"));

    List<PatternItem> pattern = Arrays.<PatternItem>asList(new Dash(30), new Gap(20));
    PolylineOptions popt = new PolylineOptions().add(latLng1).add(latLng2)
       .width(10).color(Color.MAGENTA).pattern(pattern)
       .geodesic(true);
    mMap.addPolyline(popt);

    LatLngBounds.Builder builder = new LatLngBounds.Builder();

    builder.include(marker1.getPosition());
    builder.include(marker2.getPosition());

    LatLngBounds bounds = builder.build();
    int padding = 150; // offset from edges of the map in pixels
    CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
    mMap.moveCamera(cu);
    mMap.animateCamera(cu);
}  

Полученная ломаная линия показана на моем скриншоте

enter image description here

Надеюсь, это поможет!

Ответ 2

Вот объект Route, который я использую после некоторого улучшения из @xomena

Route.java

Мои изменения:

  • Используйте heading - 90.0 вместо heading + 90.0
  • Переименуйте переменные, создайте константы (все еще выясняя, что делает какая-то часть кода...)
  • Перепишите с моей новой логикой

В принципе, я рисую маршрут кривой только в том случае, если расстояние между источником и dest составляет менее 1000 км. Для более длительного расстояния, как я упоминал в здесь, я узнал, что часть h1 + i * step внутри цикла делает небольшую ошибку из-за double calculation error в каждом итераторе и делает окончательный маршрут не помещается правильно.

Мой безопасный выбор заключается в том, чтобы нарисовать маршрут полета ворона вместо этого, но мое предложение не использовать k = 1 для этого, это не эффективность работы. Я написал еще один метод, который просто добавляет начало и dest указывает на Маршрут, пропускает все другие сложные вычисления.

В будущем я попытаюсь вернуться к этой проблеме с длинными кривыми маршрутов, но пока это решение по-прежнему подходит для моей проблемы.

EDIT:

Вот мое решение для второй проблемы:

  • Изменить heading + 90 или heading - 90 не удалось устранить проблему, поэтому не
  • Вместо этого измените вычисление переменной step следующим образом:

    double step = Math.toDegrees(Math.atan(расстояние/2/midPerpendicularLength)) * 2/DEFAULT_CURVE_POINTS;

Ответ 3

Hy, вам необходимо изменить метод showCurvePolyline с помощью этого метода.

    private void showCurvedPolyline (LatLng p1, LatLng p2, double k) {
    //Calculate distance and heading between two points
    double d = 0;


if (d == 0)
        d= SphericalUtil.computeDistanceBetween(origin, dest);



double h = SphericalUtil.computeHeading(p1, p2);

    // Calculate midpoint position
    LatLng midPoint = SphericalUtil.computeOffset(p1, d / 2, h);




    //Apply some mathematics to calculate position of the circle center
    double x = (1-k*k)*d*0.5/(2*k);
    double r = (1+k*k)*d*0.5/(2*k);

    LatLng c = SphericalUtil.computeOffset(p, x, h + 90.0);

    //Polyline options
    PolylineOptions options = new PolylineOptions();
    List<PatternItem> pattern = Arrays.<PatternItem>asList(new Dash(30), new Gap(20));

    //Calculate heading between circle center and two points
    double h1 = SphericalUtil.computeHeading(c, p1);
    double h2 = SphericalUtil.computeHeading(c, p2);

// Calculate position of the curve center point
    double sqrCurvature = DEFAULT_CURVE_ROUTE_CURVATURE * DEFAULT_CURVE_ROUTE_CURVATURE;
    double extraParam = distance / (4 * DEFAULT_CURVE_ROUTE_CURVATURE);
    double midPerpendicularLength = (1 - sqrCurvature) * extraParam;
    double r = (1 + sqrCurvature) * extraParam;

    LatLng midCurvePoint = SphericalUtil.computeOffset(midPoint, midPerpendicularLength, heading - 90.0);

    // Calculate heading between circle center and two points
    double headingToOrigin = SphericalUtil.computeHeading(midCurvePoint, origin);
    double headingToDest = SphericalUtil.computeHeading(midCurvePoint, dest);
    // Calculate positions of points on the curve
    double step = (headingToDest - headingToOrigin) / DEFAULT_CURVE_POINTS;

    List<LatLng> points = new ArrayList<>();
    for (int i = 0; i < DEFAULT_CURVE_POINTS; ++i) {
        points.add(SphericalUtil.computeOffset(midCurvePoint, r, headingToOrigin + i * step));
    }


    for (int i=0; i <points; i++) {
        LatLng pi = SphericalUtil.computeOffset(c, r, h1 + i * step);
        options.add(pi);
    }

    //Draw polyline
    mMap.addPolyline(options.width(10).color(Color.MAGENTA).geodesic(false).pattern(pattern));
}

тогда вы можете нарисовать arcPolyLine. Он был предоставлен в файле, предоставленном предыдущим ответом.

Ответ 4

Есть еще один способ нарисовать дугу. Использование API проекции карт Google для рисования полилиний в режиме наложения позволяет нам многое делать. Проверьте это репо, в котором есть пример.

enter image description here