Я ищу элегантное решение, которое вычисляет center
между несколькими координатами долготы и долготы (например, чтобы просто центрировать карту в центр google-maps polygon).
Таблица: locations
:
id | city | latitude | longitude ----------------------------------------------- 1 | Berlin | 52.524268 | 13.406290 ----------------------------------------------- 2 | London | 51.508129 | -0.1280050 ----------------------------------------------- 3 | Hamburg | 53.551084 | 9.9936817 ----------------------------------------------- 4 | Amsterdam | 52.370215 | 4.8951678 -----------------------------------------------
Текущий расчет:
function calculateCenter($array_locations) { $minlat = false; $minlng = false; $maxlat = false; $maxlng = false; foreach ($array_locations as $geolocation) { if ($minlat === false) { $minlat = $geolocation['lat']; } else { $minlat = ($geolocation['lat'] < $minlat) ? $geolocation['lat'] : $minlat; } if ($maxlat === false) { $maxlat = $geolocation['lat']; } else { $maxlat = ($geolocation['lat'] > $maxlat) ? $geolocation['lat'] : $maxlat; } if ($minlng === false) { $minlng = $geolocation['lon']; } else { $minlng = ($geolocation['lon'] < $minlng) ? $geolocation['lon'] : $minlng; } if ($maxlng === false) { $maxlng = $geolocation['lon']; } else { $maxlng = ($geolocation['lon'] > $maxlng) ? $geolocation['lon'] : $maxlng; } } // Calculate the center $lat = $maxlat - (($maxlat - $minlat) / 2); $lon = $maxlng - (($maxlng - $minlng) / 2); return array($lat, $lon); }
При использовании Карт Google вы можете использовать метод getBounds () и метод getCenter () .
Я перестроил ваши координаты, чтобы сформировать выпуклый многоугольник (все вершины точки «наружу», вдали от центра). Полигон закрывается, если первая координата является первым и последним значением в массиве polygonCoords
.
См. Jsfiddle
var map; var polygon; var bounds = new google.maps.LatLngBounds(); var i; var myLatLng = new google.maps.LatLng(52.5,6.6); var myOptions = { zoom: 5, center: myLatLng, mapTypeId: google.maps.MapTypeId.TERRAIN }; map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); var polygonCoords = [ new google.maps.LatLng(52.524268,13.406290), new google.maps.LatLng(53.551084,9.9936817), new google.maps.LatLng(51.508129,-0.1280050), new google.maps.LatLng(52.370215,4.8951678), new google.maps.LatLng(52.524268,13.406290)//Start & end point ]; polygon = new google.maps.Polygon({ paths: polygonCoords, strokeColor: "#FF0000", strokeOpacity: 0.8, strokeWeight: 3, fillColor: "#FF0000", fillOpacity: 0.05 }); polygon.setMap(map); for (i = 0; i < polygonCoords.length; i++) { bounds.extend(polygonCoords[i]); } // The Center of the polygon var latlng = bounds.getCenter(); var marker = new google.maps.Marker({ position: latlng, map: map, title:latlng.toString() });
Усреднение ваших широт и долгот работает во многих случаях, но в ряде случаев есть проблемы. Например, у вас есть 2 цитаты, Токио (long = 140) и Сиэтл (long -122), средняя долгота – 18, где-то в Европе. Вы ожидали бы чего-то ближе к международной линии дат, на 180 градусов.
Самый прямой, без проблем метод – это усреднение векторов, как если бы каждый из них происходил из центра Земли.
Псевдокод (предполагает радианы)
for each lat,long // assume 1 radii from the earth's center. // covert lat, long, and radii into x,y,z (spherical to cartesian coordinates) r=1, theta=pi/2 - lat, phi=long x = r*sin(theta)*cos(phi) y = r*sin(theta)*sin(phi) z = r*cos(theta) N++; // accumulate x,y,z sum_x += x, etc. // average x,y,z avg_x = sum_x/N, etc. // convert x,y,z back to spherical co-ordinates to get the lat/long center. rho = sqrt(avg_x*avg_x + avg_y*avg_y + avg_z*avg_z) lat = pi/2 - acos(avg_z/rho) // acos() results are 0 to pi long = atan2(avg_y, avg_x) // 4 quadrant arctangent
[Редактировать исправленные сферические координаты на картезианские]
Google использует проекцию Меркатора, рассматривая землю как удлиненный цилиндр. Таким образом, задача найти центр этой проекции.
Для каждой пары lat / long преобразуйте в карту масштабные координаты x, y (используя радианы):
x = long y = ln(tan(pi/4 + lat/2)) // Mercator projection
Затем для x & y найдите среднее значение минимума и максимума, чтобы получить ваш центр. Преобразуйте обратно в lat / long, как показано ниже.
Pseudo code center_long = average(minimum_x, maximum_x) center_lat = (atan(exp(average(minimum_y, maximum_y))) - pi/4)*2
Расчет центральной долготы отлично работает, если бы не круговой характер цилиндрической проекции Земли. Если долготы находятся как в восточном, так и в западном полушариях (некоторые отрицательные, некоторые положительные), может потребоваться дополнительная работа.
Pseudo code sort the longitudes into ascending order for each longitude difference = longitude(i-1) - longitude(i) // for first, use longitude(0) - longitude(last) if (difference < 0) add 2*pi (360 degrees) Keep track of index of minimal difference The pair with the minimal difference represents the pair that most tightly contains all longitudes. Average this pair for the center longitude. If this pair was index 0 & last, add pi (180 degrees)
Результат OP 4 города: (52,4 N, 7,0 E)
Это мой второй ответ, потому что первый не получает суть сообщения OP. Поскольку он имеет некоторую ценность, он остается.