【问题标题】:Draw a curve (bezier curve) between two lat long points on google maps android在谷歌地图android上的两个纬度点之间绘制曲线(贝塞尔曲线)
【发布时间】:2017-12-23 07:26:45
【问题描述】:

我想在两个经纬度点之间画一条曲线(贝泽曲线)。目前我指的是this post(代码在javascript中)。

使用三次贝塞尔方程获取曲线点的代码

private void drawElementsOnMap(LatLng init, LatLng end) {

    mMap.addMarker(new MarkerOptions().position(init));
    mMap.addMarker(new MarkerOptions().position(end));

    LatLngBounds.Builder bc = new LatLngBounds.Builder();
    bc.include(init);
    bc.include(end);

    mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bc.build(), 100));

    PolylineOptions line = new PolylineOptions();
    line.add(init);
    line.add(end);
    mMap.addPolyline(line);

    double distanceBetween = SphericalUtil.computeDistanceBetween(init, end);
    double lineHeadingInit = SphericalUtil.computeHeading(init, end);  
    double lineHeadingEnd = bearing(end, init);*/

    double lineHeading1, lineHeading2;
    if (lineHeadingInit < 0) {
        lineHeading1 = lineHeadingInit + 45;
        lineHeading2 = lineHeadingInit + 135;
    } else {
        lineHeading1 = lineHeadingInit + -45;
        lineHeading2 = lineHeadingInit + -135;
    }

    LatLng pA = SphericalUtil.computeOffset(init, distanceBetween / 2.5, lineHeading1);
    LatLng pB = SphericalUtil.computeOffset(end, distanceBetween / 2.5, lineHeading2);

    // Beizer curves with 4 points
    gmapsCubicBezier(init, end, pA, pB);
}

private void gmapsCubicBezier(LatLng p1, LatLng p2, LatLng pA, LatLng pB) {

    //Polyline options
    PolylineOptions options = new PolylineOptions();

    LatLng curveLatLng = null;
    for (double t = 0.0; t < 1.01; t += 0.01) {
        // P = (1−t)3P1 + 3(1−t)2tP2 +3(1−t)t2P3 + t3P4; for 4 points
        double arcX = (1 - t) * (1 - t) * (1 - t) * p1.latitude
                + 3 * (1 - t) * (1 - t) * t * pA.latitude
                + 3 * (1 - t) * t * t * pB.latitude
                + t * t * t * p2.latitude;
        double arcY = (1 - t) * (1 - t) * (1 - t) * p1.longitude
                + 3 * (1 - t) * (1 - t) * t * pA.longitude
                + 3 * (1 - t) * t * t * pB.longitude
                + t * t * t * p2.longitude;

        curveLatLng = new LatLng(arcX, arcY);
        options.add(curveLatLng);
        //Draw polyline
        mMap.addPolyline(options.width(5).color(Color.DKGRAY).geodesic(false));
    }
    mMap.addMarker(new MarkerOptions().position(curveLatLng));
}

以下是我尝试过的不同测试用例的图片。

案例 1:P1 - 孟买,P2 - 钦奈

案例 2:P1 - 法国,P2 - 新加坡

案例 3:P1 - 美国,P2 - 班加罗尔

案例 4:P1 - 美国,P2 - 新加坡

问题:

1) 为什么算法只有在案例 1 中才能画出相当不错的曲线?

2) 为什么在案例 2 中贝塞尔曲线在一侧弯曲?

3) 为什么在案例 3 和案例 4 中贝塞尔曲线看起来不同(P1(案例 3)和 P2(案例 4)的奇怪尖点)。有没有办法避免呢?

4) 为什么在案例 4 中多段线的绘制方式不同(方向?)?

我无法理解绘制曲线的模式。如果我做错了什么,请告诉我。

【问题讨论】:

  • @pskink 谢谢,我会试试的。
  • 需要考虑的一点:为什么那些弯曲的曲线是错误的?第 1 步是得到一个上面有地球的 sphere,看看你的曲线是否真的是错误的,或者你是否只是在看世界地图投影对大圆不变的影响在地球仪上。抓取 google earth(应用程序),让它在你的测试点之间画出大圆圈,看看它是否穿过你自己的曲线穿过的相同点。
  • 上帝保佑你,伙计)你救了我的命!)
  • @SarweshkumarCR 你是怎么解决的?
  • @shinzou 使用上述方法,远距离失真是正常的(至少很难避免)。所以,我想出了一个不同的方法。我使用屏幕像素点来绘制曲线,而不是经纬度点。它对我来说效果很好,我也做了一个Android library (Curve-Fit)。请检查它以了解更多信息。

标签: android google-maps bezier curve polyline


【解决方案1】:

这个答案有些投机,但我建议您所看到的一切实际上都不是错误的,甚至是意外的。如您所知,地球是圆形的,但谷歌地图(和电脑屏幕)本质上是平面和二维的。我们开始创建地球平面 2D 地图的方法是像这样分割一个地球:

在创建我们都习惯于看到的世界的 2D 地图的过程中,事情变得有些扭曲和扭曲。我没有数学支持它,但很明显,连接全球大部分地区的两个城市的 3D 曲线在将它们投影到 2D 地图上后也会发生扭曲和倾斜。我预计曲线越长,扭曲越明显。

这也可以解释为什么从孟买到钦奈的曲线在您看来是正常的。它位于相对较短的距离内,由于地球曲率造成的变形最小。

【讨论】:

  • 你认为在测地坐标系中可以画出贝塞尔曲线吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-30
  • 2017-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
相关资源
最近更新 更多