在谷歌地图android上绘制两个lat长点之间的曲线(bezier曲线)

时间:2017-12-23 07:26:46

标签: android google-maps google-maps-android-api-2 bezier polyline

我想在两个纬度点之间绘制一条曲线(Beizer曲线)。目前我指的是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 - Chennai case 1

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

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

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

问题:

1)为什么算法只能在情况1中绘制相当不错的曲线?

2)为什么在案例2的一侧有bezier曲线弯曲?

3)为什么贝塞尔曲线在情况3和4中看起来不同(P1(情况3)和P2(情况4)处的奇怪尖点)。反正有没有避免它?

4)为什么在情况4中绘制折线(方向?)为什么?

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

1 个答案:

答案 0 :(得分:2)

这个答案有点具体,但我建议你所看到的一切都是错误的,甚至是意外的。如你所知,地球是圆形的,但谷歌地图(和电脑屏幕)本质上是平面和二维的。我们开始创建地球平面2D地图的方式是将这样的地球划分为:

enter image description here

在创建我们都习惯看到的世界的2D地图的过程中,事情变得有些扭曲和扭曲。我没有数学支持它,但很明显连接两个城市的3D曲线在将它们投影到2D地图上后也会变形和扭曲。我希望曲线越长,扭曲越明显。

这也可以解释为什么从孟买到钦奈的曲线看起来很正常。它距离相对较短,由于地球曲率引起的扭曲很小。