Как рассчитать квадратный многоугольник с определенным центром?

# #python #google-bigquery #geospatial #geo #spatial-query

Вопрос:

У меня есть координаты точки WGS 84, и мне нужно создать «квадратный» многоугольник с центром в указанной выше точке. Вершины, определенные следующим образом:

        a    N    a
W *--------- ---------* E
            |
            |a
            |
            X
            |
            |a
            |
W *--------- ---------* E
       a    S    a
 

X является отправной точкой и a представляет собой заданное расстояние в метрах.

  1. Поскольку координаты точек хранятся в BigQuery вместе с другими географическими данными, предпочтительно вычислять эти полигоны в запросе. Могу ли я сгенерировать их с помощью функций географии BigQuery? (Я не нашел способа вычислить координаты точки X метров до N/E/S/W от начальной точки).
  2. Если #1 невозможно, какие библиотеки и методы Python я могу использовать для этого?

Ответ №1:

Ну, это не совсем квадрат, из-за сферического искажения расстояние между двумя верхними углами будет короче 2a и отличаться от расстояния между двумя нижними углами, а также отличаться от расстояния между боковыми углами. Но если a он достаточно мал, он достаточно близок к квадрату, и с разумной погрешностью вы можете это сделать. Я думаю, что самый простой способ сделать это в BigQuery и избежать явной тригонометрии-сделать небольшое смещение, измерить расстояние и пропорционально увеличить смещение:

 -- computes distance in degrees along parallel at specified latitude
create temp function _to_lng_degrees(lat FLOAT64, a FLOAT64) AS
(
    a / ST_Distance(ST_GeogPoint(0, lat), ST_GeogPoint(1, lat))
);

-- computes distance in degrees along meridian
create temp function _to_lat_degrees(a FLOAT64) AS
(
    a / ST_Distance(ST_GeogPoint(0, 0), ST_GeogPoint(0, 1))
);

create temp function rect(point GEOGRAPHY, a FLOAT64) AS
((
    SELECT ST_MakePolygon(ST_MakeLine(
        [ST_GeogPoint(x - dx, y - dy), ST_GeogPoint(x   dx, y - dy),
         ST_GeogPoint(x   dx, y   dy), ST_GeogPoint(x - dx, y   dy),
         ST_GeogPoint(x - dx, y - dy)]))
    FROM (
      SELECT ST_X(point) x, _to_lng_degrees(ST_Y(point), a) dx, 
             ST_Y(point) y, _to_lat_degrees(a) dy)
));

select rect(ST_GeogPoint(-122.1555771, 47.6858382), 1000)
 

Комментарии:

1. О, это очень умно. Я сделал это вручную, рассчитав отношение метра к градусу, но теперь я вижу, как я мог бы рассчитать его с помощью ST_Distance() . Кстати, _to_lat_degrees() кажется, это постоянно.