Как найти зону в круге, проходя через массив

У меня есть массив планет и их долготы:

$planets['Sun']['longitude']=9
$planets['Moon']['longitude']=341
$planets['Mercury']['longitude']=27
$planets['Venus']['longitude']=349

И у меня есть множество планетарных зон, называемых «домами», каждая из которых имеет долготу, чтобы разделить круг 360 на 12 неравных «домов». Номер долготы представляет начальную границу этой зоны.

$houses[1]['longitude']=144
$houses[2]['longitude']=164
$houses[3]['longitude']=190
$houses[4]['longitude']=223
$houses[5]['longitude']=261
$houses[6]['longitude']=296
$houses[7]['longitude']=324
$houses[8]['longitude']=344
$houses[9]['longitude']=10
$houses[10]['longitude']=43
$houses[11]['longitude']=81
$houses[12]['longitude']=116

Я хочу создать функцию для возвращения дома определенной планеты на основе долготы планеты. Так, например, если планета имеет долготу 170, то она будет находиться в доме 2, потому что она больше, чем долгота дома 2, и меньше, чем долгота дома 3, как показано в приведенном выше массиве.

У меня есть следующая функция, чтобы получить дом планеты, основываясь на его долготе. Из приведенного выше примера, он отлично работает с Луной и Меркурием, но не работает с Солнцем и Венерой. Это потому, что следующий дом меньше предыдущего, потому что это конец круга 360.

function get_planet_house($houses,$in_long){
for ($i=1;$i<12;$i++){
if ($i<11){
$next_long=$houses[$i+1]['longitude'];
}
else {
$next_long=$houses[1]['longitude'];
}
if ($in_long>$houses[$i]['longitude']){
if ($in_long<$next_long){
$house=$i;
}
}
}
return $house;
}

Так что, если я сделаю: get_planet_house($houses,$planets['Moon']['longitude']) он возвращает 7. Но если я сделаю то же самое для $planets['Sun']['longitude'] он вернется пустым.

Как я могу изменить функцию для работы с кругом, чтобы Солнце и Венера могли показать, что они находятся в 8-м доме?

0

Решение

Если твой $houses не может быть отсортировано по какой-либо причине, вы можете просто добавить немного сложности к вашей логике:

function get_planet_house(array $houses,$in_long)
{
for($i=1;$i<=12;$i++)
{
$left=$houses[$i]["longitude"];
$right=($i==12?$houses[1]["longitude"]:$houses[$i+1]["longitude"]);
if(($left<=$right && $in_long>=$left && $in_long<$right) || ($left>$right && ($in_long>=$left || $in_long<$right)))
{
return $i;
}
}
return 0;
}

3v4l скрипка

Если левая граница меньше, чем правая, то вы проверяете, находится ли входная долгота между этими двумя границами; Если левая граница больше, чем правая, то вы проверяете, падает ли входная долгота вне эти две границы.

0

Другие решения

Я бы отсортировал массив, и тогда это очень простая задача. Это решение работает для Солнца, Луны, Венеры и всех других планет:

function get_planet_house( $houses, $in_long )
{
asort( $houses );
foreach ( array_keys( $houses ) as $key )
{
if ( $in_long < $houses [$key]["longitude"] )
{
return $key - 1;
}
}
return $key;
}
1