查找最近的lat/lng-循环使用subArray作为$key



根据此处的指南https://www.intelliwolf.com/find-nearest-location-from-array-of-coordinates-php/

我正试图写一个版本,找到最接近的";ID";从位于的JSON提要https://easytide.admiralty.co.uk/Home/GetStations

到目前为止,我已经构建了以下沙盒https://3v4l.org/JX0i5#v7.3.1

<?PHP
// json will eventually be obtained via json_decode(file_get_contents('https://easytide.admiralty.co.uk/Home/GetStations')
$json = '
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-4.702540,
51.672791
]
},
"properties": {
"Id": "1603",
"Name": "TENBY",
"Country": "Channel Islands",
"ContinuousHeightsAvailable": true
}
}, {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-1.878530,
50.721680
]
},
"properties": {
"Id": "1603A",
"Name": "Bournmouth",
"Country": "Channel Islands",
"ContinuousHeightsAvailable": true
}
}, {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-2.35,
49.433333
]
},
"properties": {
"Id": "1603A",
"Name": "Maseline Pier",
"Country": "Channel Islands",
"ContinuousHeightsAvailable": true
}
}]
}';

$locations = json_decode($json, true);
#print_r($locations); //check json decoded
// set the base location will eventually be passed via $_GET
$base_location = array(
'lat' => "51.672791",  
'lng' => "-4.702540"
);
//create the array for recording the calculated distances
$distances = array();
//sure this count is not needed but used it to check the array was being read
for ($c = 0; $c < count($locations["features"]); $c++) {
// this is where I go wrong 
foreach($locations as $i){
foreach ($i as $z) { 
foreach ($z['geometry'] as $key => $location) {
if ($key == "coordinates"){
#    print_r($z);
//work out the distance Pythagorean Theorem calculating how far it is from $base_location is
$a = $base_location['lat'] - $location[1];
$b = $base_location['lng'] - $location[0];
$distance = sqrt(($a**2) + ($b**2));
$distances[$c] = $distance;

//nonsense used to test I was getting the correct output
echo "The value of key '$key' is '$location'", PHP_EOL;
}
}
}
}
}
#print_r($base_location);
//sort distances to get the closest first 
asort($distances);
print_r($distances);
//not really got to this part yet but want to return the "properties=>ID"
$closest = $location[key($distances)];
#print_r($closest);
#echo "<br>Closest port from ARRAY is: " . $closest['features'][1]['properties']['Id'];

我希望有人能简单地解释我是如何做到这一点的:-

  1. 搜索在https://easytide.admiralty.co.uk/Home/GetStations
  2. 根据提供的纬度/经度查找最近的位置
  3. 打印";属性=>ID";来自相应的数组(稍后将在另一个file_get_contents请求中使用(

我已经花了很多小时,并发布了这个问题的其他版本,这些版本被自动关闭。

我想把它作为一个学习项目来创建,但我一直坚持这个元素。如果这里不是寻求此类帮助的地方,请告知在哪里。

非常感谢

这似乎是一个有趣的练习,有点随意,您需要的所有代码都在那里供您使用

function getDistance($from_lat, $from_long, $to_lat, $to_long, $unit = 'nmi', $decimals = 2) {
// Calculate the distance in degrees
$degrees = rad2deg(acos((sin(deg2rad($from_lat))*sin(deg2rad($to_lat))) + (cos(deg2rad($from_lat))*cos(deg2rad($to_lat))*cos(deg2rad($from_long-$to_long)))));
// Convert the distance in degrees to the chosen unit (kilometres, miles or nautical miles)
switch($unit) {
case 'km':
$distance = $degrees * 111.13384; // 1 degree = 111.13384 km, based on the average diameter of the Earth (12,735 km)
break;
case 'mi':
$distance = $degrees * 69.05482; // 1 degree = 69.05482 miles, based on the average diameter of the Earth (7,913.1 miles)
break;
case 'nmi':
$distance =  $degrees * 59.97662; // 1 degree = 59.97662 nautic miles, based on the average diameter of the Earth (6,876.3 nautical miles)
}
return round($distance, $decimals);
}
$json_stations = file_get_contents('https://easytide.admiralty.co.uk/Home/GetStations');
$stations = json_decode($json_stations);
$i_am_here = ['lat' => 50.77842324616663,  'lng' => -1.087804949548603];    // Castle Field Portsmouth
$closest = [];       // index into stations
$distance = null;
foreach ($stations->features as $index => $feature){
$lng = $feature->geometry->coordinates[0];
$lat = $feature->geometry->coordinates[1];

$dist = getDistance($i_am_here['lat'], $i_am_here['lng'], $lat, $lng, $unit = 'nmi', $decimals = 4);
if ( $distance == NULL || $dist < $distance ){
$distance = $dist;
$closest = ['distance' => $dist, 'index' => $index, 'properties' => $feature->properties];
}
}
print_r($closest);
echo 'Distance = ' . $distance;

结果

Array
(
[distance] => 1.6947
[index] => 85
[properties] => stdClass Object
(
[Id] => 0065
[Name] => PORTSMOUTH
[Country] => England
[ContinuousHeightsAvailable] => 1
)
)
Distance = 1.6947

我设法找到了一个"解决方案",但可能不是最优雅的?

foreach($locations as $i){
if (is_array($i) || is_object($i)) {
foreach ($i as $z) { 
foreach ($z['geometry'] as $key => $location) {
if ($key == "coordinates"){
#  print_r($z);
$a = $base_location['lat'] - $location[1];
$b = $base_location['lng'] - $location[0];
$distance = sqrt(($a**2) + ($b**2));
$distances[$c++] = $distance;
# echo "The value of key '$key' is '$location'", PHP_EOL;
}
}
}
}
}
asort($distances);
$closest = $i[key($distances)];
print_r($closest); 
echo "Closest Id: " . $closest['properties']['Id']. " name: " . $closest['properties']['Name'];

最新更新