ST_EXTENT или ST_ENVELOPE в BigQuery? - PullRequest
       18

ST_EXTENT или ST_ENVELOPE в BigQuery?

0 голосов
/ 05 февраля 2020

Мне нужен эквивалент ST_EXTENT или ST_ENVELOPE в BigQuery, но я не могу найти способ выполнить этот запрос:

SELECT REGEXP_EXTRACT(name, ', (..)') state
  , ST_EXTENT(ARRAY_AGG(urban_area_geom)) corners
  , COUNT(*) cities
FROM `bigquery-public-data.geo_us_boundaries.urban_areas`
GROUP BY state

Желаемым результатом этого запроса является список ограничительных рамок, чтобы охватить все городские районы вокруг США, сгруппированные по штатам.

1 Ответ

3 голосов
/ 05 февраля 2020

Я создал запрос функции, чтобы получить собственную реализацию ST_EXTENT (). Пожалуйста, добавьте ваши голоса и доказательства, почему вам нужна эта функция, чтобы команда могла расставить приоритеты и держать вас в курсе любых событий:

А пока лучшее решение, которое я могу предложить:

  • fhoffa.x.st_bounding_box(): наивный ограничивающий прямоугольник UDF.

Используйте его так:

SELECT REGEXP_EXTRACT(name, ', (..)') state
  , fhoffa.x.st_bounding_box(ARRAY_AGG(urban_area_geom)).polygon 
  , COUNT(*) urban_areas
FROM `bigquery-public-data.geo_us_boundaries.urban_areas`
GROUP BY state

enter image description here

enter image description here Код, стоящий за ним:

CREATE OR REPLACE FUNCTION fhoffa.x.st_bounding_box(arr ANY TYPE) AS ((
  SELECT AS STRUCT *
    , ST_MakePolygon(ST_GeogFromText(FORMAT('LINESTRING(%f %f,%f %f,%f %f,%f %f)',minlon,minlat,maxlon,minlat,maxlon,maxlat,minlon, maxlat))) polygon
  FROM (
    SELECT MIN(m.min_x) minlon, MAX(m.max_x) maxlon , MIN(m.min_y) minlat, MAX(m.max_y) maxlat
    FROM (
      SELECT 
        (SELECT AS STRUCT MIN(x) min_x, MAX(x) max_x, MIN(y) min_y, MAX(y) max_y FROM UNNEST(coords)) m
      FROM (
        SELECT ARRAY(
          SELECT STRUCT(
            CAST(SPLIT(c, ', ')[OFFSET(0)] AS FLOAT64) AS x, 
            CAST(SPLIT(c, ', ')[OFFSET(1)] AS FLOAT64) AS y
          )
          FROM UNNEST(REGEXP_EXTRACT_ALL(ST_ASGEOJSON(geog), r'\[([^[\]]*)\]')) c
        ) coords
        FROM UNNEST(arr) geog
      )
    )
  )
))

Примечания:

  • Требуются дополнительные усилия, чтобы он работал с геометриями, которые пересекают линию -180.

  • Из-за геодезических c ребер результат функции не является истинным ограничивающим прямоугольником, т.е. ST_Covers (box, geom) может возвращать FALSE.

  • На картинке выше я не ожидаю, что каждый штат будет полностью покрыт, только его городские районы. Таким образом, ограничивающая рамка будет правильной, если в этих непокрытых углах нет городской зоны.

  • Следующая конструкция многоугольника даст вам точные "прямоугольники", но они станут гораздо более сложными структурами для работы .

ST_GEOGFROMGEOJSON(
  FORMAT('{"type": "Polygon", "coordinates": [[[%f,%f],[%f,%f],[%f,%f],[%f,%f],[%f, %f]]]}'
  , minlon,minlat,maxlon,minlat,maxlon,maxlat,minlon,maxlat,minlon,minlat)
)

enter image description here

С нетерпением буду ждать ваших комментариев и предложений.

...