首页 文章

在Google Map中绘制ARC折线

提问于
浏览
11

How Can I Draw Arc Polyline in Google Map ?

我已经使用this代码来创建 curved Polyline .

这是绘制弯曲折线的 method

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));
}

OUTPUT

1.如果我正在使用this.showCurvedPolyline(latLng1,latLng2,0.1);然后得到:

enter image description here

正如您在上面的图像中看到的那样,我们非常接近我们的目标,但不知道为什么它没有与另一个终点连接

2.如果我正在使用this.showCurvedPolyline(latLng1,latLng2,1);然后得到:

enter image description here

3.如果我使用的是LatLng c = SphericalUtil.computeOffset(p,x,h - 90.0);然后得到:

enter image description here

Note: 我不想要这么大的圆形,真的很高 .

这是 I want an ARC Shape ,如下图所示

enter image description here

这是 CODE 我用来在两个_1275675之间添加曲线折线:

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);

    }

3 回答

  • 1

    我在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);
    }
    

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

    enter image description here

    我希望这有帮助!

  • 4

    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 . 它是由上一个答案提供的文件中提供的 .

  • 1

    这是我在使用@xomena的一些改进后使用的Route对象

    Route.java

    我的变化:

    • 使用 heading - 90.0 而不是 heading + 90.0

    • 重命名变量,制作常量(仍在弄清楚代码的某些部分正在做什么......)

    • 用我的新逻辑重写

    基本上,如果原点和dest之间的距离小于1000km,我只画一条曲线路线 . 对于更长的距离,正如我在_1275685中提到的那样,我发现循环内的部分 h1 + i * step 由于每个迭代器中的 double calculation error 而产生一个小错误,并使最终路径没有正确放置 .

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

    我将来会尝试回到这个长曲线路径问题,现在,这个解决方案仍然适合我的问题 .

    编辑:

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

    • 更改 heading + 90heading - 90 didn 't fix the problem, so don' t

    • 而是,更改 step 变量计算,如下所示:

    double step = Math.toDegrees(Math.atan(distance / 2 / midPerpendicularLength))* 2 / DEFAULT_CURVE_POINTS;

相关问题