Draw ARC Polyline in Google Map

后端 未结 4 1764
执念已碎
执念已碎 2021-01-04 11:08

How Can I Draw Arc Polyline in Google Map ?

I already used this code to create curved Polyline.

Here is the method

相关标签:
4条回答
  • 2021-01-04 11:21

    Hy , you need to change your showCurvePolyline method with this method.

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

    then you can draw the arcPolyLine.It was provided in the File Provided by previous answer.

    0 讨论(0)
  • 2021-01-04 11:24

    Here is Route object I am using after some improvement from @xomena

    Route.java

    My changes:

    • Use heading - 90.0 instead of heading + 90.0
    • Rename variables, make constants (Still figuring out what is some part of the code is doing...)
    • Rewrite with my new logic

    Basically, I only draw a curve route if the distance between origin and dest is less than 1000km. For longer distance, as I mentioned in here, I found out the part h1 + i * step inside the loop make a small error due to double calculation error in every iterator and make the final route not being placed correctly.

    My safe choice is to draw a crow flight route instead, but my suggestion is not to use k = 1 for this, it's not performance efficiency. I wrote another method which just adds origin and dest points to the Route, skips all other complex calculation.

    I will try to come back with this long-curve route problem in the future, for now, this solution still suitable for my problem.

    EDIT:

    Here is my solution for the second problem so far:

    • Change heading + 90 or heading - 90 didn't fix the problem, so don't
    • Instead, change the step variable calculation like this:

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

    0 讨论(0)
  • 2021-01-04 11:28

    The solution that I proposed in another question was focused on curved polylines for really small distances. For example, when you have a Directions API route where the start and end points are snapped to road, but the real start and end points in original request were the positions of buildings, so you can connect the road and building with this curved dashed polyline.

    In case of big distances like in your example, I believe you can just use a geodesic polylines that are available in the API. You can set geodesic property of polyline options to 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);
    }  
    

    The resulting polyline is shown in my screenshot

    I hope this helps!

    0 讨论(0)
  • 2021-01-04 11:38

    There is another way to draw an arc. Using the google maps projection API to draw the polylines on an overlay view enables us to do a lot of things. Check this repo that has an example.

    0 讨论(0)
提交回复
热议问题