PHP вычисляет широту / долготу квадрата вокруг заданной точки на поверхности?

Учитывая широту / долготу точки земной поверхности (и расстояние, скажем, в километрах), мне нужно вычислить координаты верхнего левого, верхнего правого, нижнего правого и нижнего левого координат. Независимо от ориентации квадрата.

Я нашел хороший PHP-класс для вычисления расстояния между двумя точками на поверхности, но, к сожалению, нет функции для квадрата (или даже круга) вокруг точки.


person gremo    schedule 10.10.2011    source источник
comment
На поверхности земли нет квадрата, если только вы не говорите о совсем небольших расстояниях.   -  person Alnitak    schedule 10.10.2011
comment
На самом деле, поверхность Земли полярная, квадрат и круг - оба декартовы. Думайте о квадрате, как о системе координат, выровняйте его так, чтобы левый нижний угол совпадал с нулем (0; 0). Оттуда было бы легче пройти через это. Однако, если вы хотите сделать это с помощью круга, это намного сложнее. Учитывая круг, я бы начал с позиционирования середины круга на ноль (0; 0), и теперь каждая точка круга должна находиться на расстоянии r от (0; 0), чтобы вы могли легко вычислить желаемые значения. ..   -  person 19h    schedule 10.10.2011
comment
@kenansulayman, чтобы просто сказать, мне это нужно для Panoramio rest api: требуется отправить запрос с min lat, max lat, min lng, max lng, то есть определить квадрат. Идея состоит в том, чтобы показать фотографии вокруг заданной точки на расстоянии, скажем, 5 километров. Я знаком с полярными / линейными и прочими вещами.   -  person gremo    schedule 10.10.2011
comment
возможно, он принадлежит к обществу плоской Земли.   -  person    schedule 10.10.2011
comment
@ Дагон, я лолбил, но давай серьезно!   -  person gremo    schedule 10.10.2011


Ответы (1)


Это может сработать для вас. Подход здесь состоит в том, чтобы найти точки назначения из заданной точки с севера, с востока, с запада и с юга. Функция getSquareAroundPoint возвращает массив, определяющий эти четыре точки, а функция getMinMaxCoords возвращает минимальные и максимальные координаты этих точек, как того требует упомянутый вами REST API (он возвращается как массив массива, если входная координата близка к 180-градусный меридиан.) Это общественное достояние.

Подход включает в себя поиск точки назначения по координатам, расстоянию и азимуту. Этот расчет называется решением прямой геодезической задачи, и он обсуждается в C.F.F. Статья Карни Алгоритмы для геодезических, 2012. Метод getDestinationPoint ниже использует метод, который менее точен, чем алгоритмы, представленные в статье Карни, особенно потому, что этот метод предполагает, что Земля является идеальной сферой.

// Distance is in km, alat and alon are in degrees
function getDestinationPoint($alat, $alon, $distance, $bearing){
 $pi=3.14159265358979;
 $alatRad=$alat*$pi/180;
 $alonRad=$alon*$pi/180;
 $bearing=$bearing*$pi/180;
 $alatRadSin=sin($alatRad);
 $alatRadCos=cos($alatRad);
 // Ratio of distance to earth's radius
 $angularDistance=$distance/6370.997;
 $angDistSin=sin($angularDistance);
 $angDistCos=cos($angularDistance);
 $xlatRad = asin( $alatRadSin*$angDistCos +
                                   $alatRadCos*$angDistSin*cos($bearing) );
 $xlonRad = $alonRad + atan2(
            sin($bearing)*$angDistSin*$alatRadCos,
            $angDistCos-$alatRadSin*sin($xlatRad));
 // Return latitude and longitude as two element array in degrees
 $xlat=$xlatRad*180/$pi;
 $xlon=$xlonRad*180/$pi;
 if($xlat>90)$xlat=90;
 if($xlat<-90)$xlat=-90;
 while($xlat>180)$xlat-=360;
 while($xlat<=-180)$xlat+=360;
 while($xlon>180)$xlon-=360;
 while($xlon<=-180)$xlon+=360;
 return array($xlat,$xlon);
}

// Distance is in km, lat and lon are in degrees
function getSquareAroundPoint($lat,$lon,$distance){
 return array(
  getDestinationPoint($lat,$lon,$distance,0), // Get north point
  getDestinationPoint($lat,$lon,$distance,90), // Get east point
  getDestinationPoint($lat,$lon,$distance,180), // Get south point
  getDestinationPoint($lat,$lon,$distance,270) // Get west point
 );
}

// Returns array containing an array with min lat, max lat, min lon, max lon
// If the square defining these points crosses the 180-degree meridian, two
// such arrays are returned.  Otherwise, one such array (within another array)
// is returned.
function getMinMaxCoords($lat,$lon,$distance){
 $s=getSquareAroundPoint($lat,$lon,$distance);
 if($s[3][1]>$s[1][1]){// if west longitude is greater than south longitude
  // Crossed the 180-degree meridian
  return array(
    array($s[2][0],$s[0][0],$s[3][1],180),
    array($s[2][0],$s[0][0],-180,$s[1][1])
  );
 } else {
  // Didn't cross the 180-degree meridian (usual case)
  return array(
    array($s[2][0],$s[0][0],$s[3][1],$s[1][1])
  );
 }
}

// Example: Gets extreme coordinates around point at (10.0,20.0)
print_r(getSquareAroundPoint(10.0,180,100));
print_r(getMinMaxCoords(10.0,180,100));
person Peter O.    schedule 10.10.2011
comment
Он говорил о плоском квадрате. Ваше уравнение касается квадрата на полярной сфере .. или вы правы? Его вопрос неясен. - person 19h; 10.10.2011
comment
@kenansulayman: Если вы читаете, как Gremo будет использовать эту информацию: требуется отправить запрос с минимальной широтой, максимальной широтой, минимальным долгим, максимальным долгом, то есть определить квадрат, и ввод: точка поверхности земли, это ясно что выходные координаты полярны. Тем более, что на расстоянии, скажем, 5 километров, разница все равно может быть незначительной. Однако предположим, что вход находится около 180-градусного меридиана или около любого полюса. Если API Panoramio rest не может принимать такие частные случаи, использование приближения с помощью декартовых методов может привести к несколько ужасным результатам. - person Peter O.; 10.10.2011