Calculate the center point of multiple latitude/longitude coordinate pairs

后端 未结 21 1337
暖寄归人
暖寄归人 2020-11-27 09:27

Given a set of latitude and longitude points, how can I calculate the latitude and longitude of the center point of that set (aka a point that would center a view on all poi

相关标签:
21条回答
  • 2020-11-27 09:47

    This is is the same as a weighted average problem where all the weights are the same, and there are two dimensions.

    Find the average of all latitudes for your center latitude and the average of all longitudes for the center longitude.

    Caveat Emptor: This is a close distance approximation and the error will become unruly when the deviations from the mean are more than a few miles due to the curvature of the Earth. Remember that latitudes and longitudes are degrees (not really a grid).

    0 讨论(0)
  • 2020-11-27 09:48

    Thanks! Here is a C# version of OP's solutions using degrees. It utilises the System.Device.Location.GeoCoordinate class

        public static GeoCoordinate GetCentralGeoCoordinate(
            IList<GeoCoordinate> geoCoordinates)
        {
            if (geoCoordinates.Count == 1)
            {
                return geoCoordinates.Single();
            }
    
            double x = 0;
            double y = 0;
            double z = 0;
    
            foreach (var geoCoordinate in geoCoordinates)
            {
                var latitude = geoCoordinate.Latitude * Math.PI / 180;
                var longitude = geoCoordinate.Longitude * Math.PI / 180;
    
                x += Math.Cos(latitude) * Math.Cos(longitude);
                y += Math.Cos(latitude) * Math.Sin(longitude);
                z += Math.Sin(latitude);
            }
    
            var total = geoCoordinates.Count;
    
            x = x / total;
            y = y / total;
            z = z / total;
    
            var centralLongitude = Math.Atan2(y, x);
            var centralSquareRoot = Math.Sqrt(x * x + y * y);
            var centralLatitude = Math.Atan2(z, centralSquareRoot);
    
            return new GeoCoordinate(centralLatitude * 180 / Math.PI, centralLongitude * 180 / Math.PI);
        }
    
    0 讨论(0)
  • 2020-11-27 09:49

    I found this post very useful so here is the solution in PHP. I've been using this successfully and just wanted to save another dev some time.

    /**
     * Get a center latitude,longitude from an array of like geopoints
     *
     * @param array data 2 dimensional array of latitudes and longitudes
     * For Example:
     * $data = array
     * (
     *   0 = > array(45.849382, 76.322333),
     *   1 = > array(45.843543, 75.324143),
     *   2 = > array(45.765744, 76.543223),
     *   3 = > array(45.784234, 74.542335)
     * );
    */
    function GetCenterFromDegrees($data)
    {
        if (!is_array($data)) return FALSE;
    
        $num_coords = count($data);
    
        $X = 0.0;
        $Y = 0.0;
        $Z = 0.0;
    
        foreach ($data as $coord)
        {
            $lat = $coord[0] * pi() / 180;
            $lon = $coord[1] * pi() / 180;
    
            $a = cos($lat) * cos($lon);
            $b = cos($lat) * sin($lon);
            $c = sin($lat);
    
            $X += $a;
            $Y += $b;
            $Z += $c;
        }
    
        $X /= $num_coords;
        $Y /= $num_coords;
        $Z /= $num_coords;
    
        $lon = atan2($Y, $X);
        $hyp = sqrt($X * $X + $Y * $Y);
        $lat = atan2($Z, $hyp);
    
        return array($lat * 180 / pi(), $lon * 180 / pi());
    }
    
    0 讨论(0)
  • 2020-11-27 09:49

    Out of object in PHP. Given array of coordinate pairs, returns center.

    /**
     * Calculate center of given coordinates
     * @param  array    $coordinates    Each array of coordinate pairs
     * @return array                    Center of coordinates
     */
    function getCoordsCenter($coordinates) {    
        $lats = $lons = array();
        foreach ($coordinates as $key => $value) {
            array_push($lats, $value[0]);
            array_push($lons, $value[1]);
        }
        $minlat = min($lats);
        $maxlat = max($lats);
        $minlon = min($lons);
        $maxlon = max($lons);
        $lat = $maxlat - (($maxlat - $minlat) / 2);
        $lng = $maxlon - (($maxlon - $minlon) / 2);
        return array("lat" => $lat, "lon" => $lng);
    }
    

    Taken idea from #4

    0 讨论(0)
  • 2020-11-27 09:50

    As an appreciation for this thread, here is my little contribution with the implementation in Ruby, hoping that I will save someone a few minutes from their precious time:

    def self.find_center(locations)
    
     number_of_locations = locations.length
    
     return locations.first if number_of_locations == 1
    
     x = y = z = 0.0
     locations.each do |station|
       latitude = station.latitude * Math::PI / 180
       longitude = station.longitude * Math::PI / 180
    
       x += Math.cos(latitude) * Math.cos(longitude)
       y += Math.cos(latitude) * Math.sin(longitude)
       z += Math.sin(latitude)
     end
    
     x = x/number_of_locations
     y = y/number_of_locations
     z = z/number_of_locations
    
     central_longitude =  Math.atan2(y, x)
     central_square_root = Math.sqrt(x * x + y * y)
     central_latitude = Math.atan2(z, central_square_root)
    
     [latitude: central_latitude * 180 / Math::PI, 
     longitude: central_longitude * 180 / Math::PI]
    end
    
    0 讨论(0)
  • 2020-11-27 09:51

    Here is the Android version based on @Yodacheese's C# answer using Google Maps api:

    public static LatLng GetCentralGeoCoordinate(List<LatLng> geoCoordinates) {        
        if (geoCoordinates.size() == 1)
        {
            return geoCoordinates.get(0);
        }
    
        double x = 0;
        double y = 0;
        double z = 0;
    
        for(LatLng geoCoordinate : geoCoordinates)
        {
            double  latitude = geoCoordinate.latitude * Math.PI / 180;
            double longitude = geoCoordinate.longitude * Math.PI / 180;
    
            x += Math.cos(latitude) * Math.cos(longitude);
            y += Math.cos(latitude) * Math.sin(longitude);
            z += Math.sin(latitude);
        }
    
        int total = geoCoordinates.size();
    
        x = x / total;
        y = y / total;
        z = z / total;
    
        double centralLongitude = Math.atan2(y, x);
        double centralSquareRoot = Math.sqrt(x * x + y * y);
        double centralLatitude = Math.atan2(z, centralSquareRoot);
    
        return new LatLng(centralLatitude * 180 / Math.PI, centralLongitude * 180 / Math.PI);
    
    }
    

    in app build.gradle add:

    implementation 'com.google.android.gms:play-services-maps:17.0.0'
    
    0 讨论(0)
提交回复
热议问题