Find the closest point on polygon to user location

前端 未结 1 1153
有刺的猬
有刺的猬 2020-12-18 08:48

I have an app that find the shortest distance between my user to a polygon.

I want to convert the polygon to Geofence to check the distance between the user to the a

相关标签:
1条回答
  • 2020-12-18 09:15

    You can use a function like the following to calculate the nearest point from polygon defined by a List<LatLng> and a given LatLng.

    It uses the PolyUtil.distanceToLine from the Google Maps Android API Utility Library to compute the distance between the test LatLng and every segment of the list, and a method based on the distanceToLine method from https://github.com/googlemaps/android-maps-utils/blob/master/library/src/com/google/maps/android/PolyUtil.java to compute the projection of a point on a segment.

    private LatLng findNearestPoint(LatLng test, List<LatLng> target) {
        double distance = -1;
        LatLng minimumDistancePoint = test;
    
        if (test == null || target == null) {
            return minimumDistancePoint;
        }
    
        for (int i = 0; i < target.size(); i++) {
            LatLng point = target.get(i);
    
            int segmentPoint = i + 1;
            if (segmentPoint >= target.size()) {
                segmentPoint = 0;
            }
    
            double currentDistance = PolyUtil.distanceToLine(test, point, target.get(segmentPoint));
            if (distance == -1 || currentDistance < distance) {
                distance = currentDistance;
                minimumDistancePoint = findNearestPoint(test, point, target.get(segmentPoint));
            }
        }
    
        return minimumDistancePoint;
    }
    
    /**
     * Based on `distanceToLine` method from
     * https://github.com/googlemaps/android-maps-utils/blob/master/library/src/com/google/maps/android/PolyUtil.java
     */
    private LatLng findNearestPoint(final LatLng p, final LatLng start, final LatLng end) {
        if (start.equals(end)) {
            return start;
        }
    
        final double s0lat = Math.toRadians(p.latitude);
        final double s0lng = Math.toRadians(p.longitude);
        final double s1lat = Math.toRadians(start.latitude);
        final double s1lng = Math.toRadians(start.longitude);
        final double s2lat = Math.toRadians(end.latitude);
        final double s2lng = Math.toRadians(end.longitude);
    
        double s2s1lat = s2lat - s1lat;
        double s2s1lng = s2lng - s1lng;
        final double u = ((s0lat - s1lat) * s2s1lat + (s0lng - s1lng) * s2s1lng)
                / (s2s1lat * s2s1lat + s2s1lng * s2s1lng);
        if (u <= 0) {
            return start;
        }
        if (u >= 1) {
            return end;
        }
    
        return new LatLng(start.latitude + (u * (end.latitude - start.latitude)),
                start.longitude + (u * (end.longitude - start.longitude)));
    
    
    }
    

    You can test it with the following code:

    List<LatLng> points = new ArrayList<>();
    points.add(new LatLng(2, 2));
    points.add(new LatLng(4, 2));
    points.add(new LatLng(4, 4));
    points.add(new LatLng(2, 4));
    points.add(new LatLng(2, 2));
    
    LatLng testPoint = new LatLng(3, 0);
    
    LatLng nearestPoint = findNearestPoint(testPoint, points);
    Log.e("NEAREST POINT: ", "" + nearestPoint); // lat/lng: (3.0,2.0)
    Log.e("DISTANCE: ", "" + SphericalUtil.computeDistanceBetween(testPoint, nearestPoint)); // 222085.35856591124
    
    0 讨论(0)
提交回复
热议问题