【问题标题】:Draw ARC Polyline in Google Map在谷歌地图中绘制弧折线
【发布时间】:2018-03-06 18:44:24
【问题描述】:

如何在谷歌地图中绘制弧折线?

我已经使用this 代码创建了曲线折线。

这里是绘制曲线折线的方法

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);然后得到:

注意:我不想要这么大的圆形,真的我不想要那么高度。

这是我想要一个弧形,如下图所示

这是我用来在两个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);

    }

【问题讨论】:

  • 他提供了一个解决方案,使用 k=1 而不是 k==1,请参阅他的第二个问题快速修复here
  • @LalitSinghFauzdar 我在上述方法的任何地方都没有找到 k==1,你能告诉我我需要在哪里进行更改吗?
  • 看到这个函数调用 this.showCurvedPolyline(sydney1,sydney2, 0.5);这里 0.5 是 k 的值,这里尝试传递 1。
  • 对不起,我忘了告诉你我已经尝试过 1.0 和 1 但同样的问题:this.showCurvedPolyline(latLng2, latLng1, 1);
  • 正如他们所提到的“最后一个参数 k 定义了折线的曲率,它可以是 >0 和

标签: android google-maps google-maps-android-api-2 android-custom-view polyline


【解决方案1】:

这是经过 @xomena 改进后我正在使用的 Route 对象

Route.java

我的改变:

  • 使用heading - 90.0 而不是heading + 90.0
  • 重命名变量,制作常量(仍在弄清楚代码的某些部分在做什么......)
  • 用我的新逻辑重写

基本上,如果起点和终点之间的距离小于1000公里,我只会绘制曲线路线。对于更长的距离,正如我在here 中提到的,我发现循环内的h1 + i * step 部分会由于每个迭代器中的double calculation error 而产生一个小错误,并导致最终路由没有正确放置。

我的安全选择是画一条乌鸦飞行路线,但我的建议是不要为此使用 k = 1,这不是性能效率。我写了另一种方法,它只是将起点和终点添加到路线中,跳过所有其他复杂的计算。

我以后会尝试解决这个长曲线路线问题,目前,这个解决方案仍然适合我的问题。

编辑:

到目前为止,这是我对第二个问题的解决方案:

  • 更改heading + 90heading - 90 并没有解决问题,所以不要
  • 改为像这样更改step 变量计算:

    双步 = Math.toDegrees(Math.atan(distance / 2 / midPerpendicularLength)) * 2 / DEFAULT_CURVE_POINTS;

【讨论】:

  • 感谢分享,您能否分享 Activity 类的代码以及我们需要在 build.gradle 中添加的内容:无法解析符号“DirectionApiResponse”...如果可能的话,请正如@xomena 为我们所做的那样,在 Github 上上传演示源代码......因此,今天我们能够就它进行讨论,而您是第二个帮助继续讨论的人 - 非常感谢。
  • 实际上我想回答这个问题以获得 100 赏金积分 :) stackoverflow.com/questions/46103680/… (因此我使用纽约和伦敦作为两个地理位置)并且我想实现我所实现的相同目标已经,但弧形
  • 我刚用了-90,上传了上面截图,请检查还没解决
  • 您可以忽略DirectionApiResponse 部分并将其删除。你确定你只改变 -90 而没有别的,因为它看起来很奇怪?
  • 是的,您可以在最后尝试一下,我只想使用这些地理位置:LatLng latLng1 = new LatLng(40.7128, 74.0059); // 纽约纬度 latLng2 = new LatLng(51.5074, 0.1278); // 伦敦 请分享您更新后的代码...如您所知,我已尽力...
【解决方案2】:

你好,你需要用这个方法改变你的 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));
}

然后你就可以画弧线了。它是在之前答案提供的文件中提供的。

【讨论】:

  • Hy Sonali 看看这个答案。
  • 您的代码中有一些未定义的变量,例如 DEFAULT_CURVE_ROUTE_CURVATURE。
【解决方案3】:

我在another question 中提出的解决方案专注于非常短距离的弯曲折线。例如,当您有一个 Directions API 路线的起点和终点捕捉到道路时,但原始请求中的真正起点和终点是建筑物的位置,因此您可以使用这条弯曲的虚线多段线连接道路和建筑物.

在您的示例中距离较大的情况下,我相信您可以使用 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);
}  

生成的折线显示在我的屏幕截图中

我希望这会有所帮助!

【讨论】:

  • 嘿,我做了和你说的一样的事情,但是没有用,它仍然显示一条直线。
【解决方案4】:

还有另一种绘制圆弧的方法。使用谷歌地图投影 API 在覆盖视图上绘制折线使我们能够做很多事情。检查这个有例子的repo

【讨论】:

  • 我们如何使用 Flutter 做到这一点?有人知道请告诉我。
猜你喜欢
  • 2016-05-14
  • 1970-01-01
  • 1970-01-01
  • 2013-07-02
  • 2023-04-06
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
  • 2015-10-17
相关资源
最近更新 更多