Как получить правильный центроид большого полигона с помощью st_centroid - PullRequest
1 голос
/ 07 января 2020

У меня возникли проблемы с функцией ST_CENTROID в bigquery. Существует разница между получением центроида столбца GEOGRAPHY и из той же версии WKT столбца. Таблица генерируется с использованием bq load со столбцом географии и файла newline_delimited_ json, содержащего многоугольник в виде текста wkt.

Пример:

select st_centroid(polygon) loc, st_centroid(ST_GEOGFROMTEXT(st_astext(polygon))) loc2,polygon from table_with_polygon

Результат:

POINT(-174.333247842246 -51.6549479435566)
POINT(5.66675215775447 51.6549479435566)
POLYGON((5.666771 51.654721, 5.666679 51.655027, 5.666597 51.655017, 5.666556 51.655154, 5.666702 51.655171, 5.666742 51.655037, 5.666824 51.655046, 5.666917 51.654737, 5.666771 51.654721))

POINT(-174.367214581541 -51.645030856473)
POINT(5.63278541845948 51.645030856473)
POLYGON((5.632691 51.644997, 5.63269 51.644999, 5.63273 51.645003, 5.632718 51.645049, 5.632843 51.645061, 5.632855 51.645014, 5.632691 51.644997))

POINT(-174.37100400049 -51.6434992715399)
POINT(5.62899599950984 51.6434992715399)
POLYGON((5.629063 51.643523, 5.629084 51.643465, 5.629088 51.643454, 5.628957 51.643436, 5.628915 51.643558, 5.629003 51.64357, 5.629021 51.643518, 5.629063 51.643523))

POINT(-174.293340001044 -51.6424190026157)
POINT(5.70665999895557 51.6424190026157)
POLYGON((5.706608 51.642414, 5.706624 51.642443, 5.706712 51.642424, 5.706696 51.642395, 5.706608 51.642414))

POINT(-174.306209997018 -51.6603530009923)
POINT(5.69379000298176 51.6603530009923)
POLYGON((5.693801 51.660361, 5.693802 51.660346, 5.693779 51.660345, 5.693778 51.66036, 5.693801 51.660361))

POINT(-174.291766437718 -51.6499633041183)
POINT(5.70823356228228 51.6499633041183)
POLYGON((5.708187 51.649858, 5.708091 51.650027, 5.70828 51.650069, 5.708376 51.649899, 5.708187 51.649858))

POINT(-174.369405698681 -51.653769846544)
POINT(5.63059430131924 51.653769846544)
POLYGON((5.630653 51.653531, 5.630462 51.653605, 5.630579 51.653722, 5.630574 51.65373, 5.630566 51.653729, 5.630551 51.653759, 5.630559 51.65376, 5.630555 51.653769, 5.630273 51.653846, 5.630364 51.653974, 5.630787 51.653858, 5.630852 51.653728, 5.630653 51.653531))

...etc

Это ошибка или я что-то не так делаю?

Обновление Дальнейшие раскопки с использованием ответа Майкла Энтина в качестве подсказки. Оказывается, что bq load с WKT НЕ использует наименьший многоугольник по умолчанию. И с bq load нет возможности изменить это поведение. Импортированный json очень большой (данные openstreetmap), поэтому нет простого способа изменить его на geo Json.

Чтобы глубже изучить фактическое значение, хранящееся в столбце, я сделал

select st_asgeojson(polygon) from ...

, что привело к

{ "type": "Polygon", "coordinates": [ [ [5.598659, 51.65927], [5.598651, 51.659295], [5.598638, 51.659293], [5.598626, 51.65933], [5.598788, 51.659353], [5.598799, 51.659319], [5.598855, 51.659139], [5.598692, 51.65912], [5.598643, 51.659268], [5.598659, 51.65927] ], [ [180, 90], [180, 0], [180, -90], [-180, -90], [-180, 0], [-180, 90], [180, 90] ] ] } 

Так что здесь можно увидеть неправильную ориентацию.

1 Ответ

2 голосов
/ 07 января 2020

Похоже, что некоторые или все эти многоугольники могли быть перевернуты, и это приводит к появлению центроидов-антиподов: POINT(-174.333247842246 -51.6549479435566) противоположно POINT(5.66675215775447 51.6549479435566) et c.

См. BigQuery do c для получения подробной информации. что это значит: https://cloud.google.com/bigquery/docs/gis-data#polygon_orientation

Есть две возможные причины и способы решения этой проблемы (моя ставка - случай 1):

  1. Полигоны должны быть маленькими, но были загружены с неправильной ориентацией и, таким образом, стали перевернутыми - теперь они дополняют предполагаемую форму и больше полушария. Поскольку вы не передаете параметр oriented в ST_GEOGFROMTEXT, эта функция исправляет их, игнорируя ориентацию.

Обычно правильное решение - загрузить их как Geo Json (это также позволяет избежать другой проблемы с загрузкой строк WKT - geodesi c против плоских ребер). Или, если все ребра маленькие и геодезические c против плоских не имеют значения - замените географию таблицы на ST_GEOGFROMTEXT(st_astext(polygon)).

Полигоны должны быть действительно большими и загружаться с правильной ориентацией. Затем, когда вы не передаете параметр oriented в ST_GEOGFROMTEXT, эта функция разбивает их, игнорируя ориентацию.

Если это так, вы должны передать TRUE в качестве второго параметра ST_GEOGFROMTEXT.

...