Автоматическая фиксация кольцевых самопересечений в shp2pgsql
Мы импортируем целую кучу шейп-файлов ArcGIS в PostGIS, конвертируемых на лету с shp2pgsql
, Проблема в том, что если у шейп-файлов есть самопересечения кольца, импортные дроссели:
NOTICE: Ring Self-intersection at or near point -80.1338 25.8102
ERROR: new row for relation "place_shapes" violates
check constraint "shape_is_valid"
Как мы можем это исправить?
3 ответа
Хотя буферизация объекта по нулю является известным исправлением для самопересекающихся полигонов, которые слишком часто встречаются в файлах shp, как это было предложено Марсело, для этой цели также существует функция ST_MakeValid. Существует также связанная функция, ST_IsValidReason, которая будет информировать о том, где находится проблема, а не просто попытаться устранить ее вслепую.
На практике использование ST_MakeValid(geom) или ST_Buffer(geom, 0) может создать смесь типов геометрии, включая потерянные точки и линии линий. Следовательно, дальнейшее уточнение может заключаться в проверке возвращаемого типа геометрии и включении, например, только тех многоугольников, которые являются результатом ST_MakeValid.
create table valid_geoms as
with make_valid (id, geom) as
(select
row_number() over() as id,
(ST_Dump(ST_MakeValid(geom))).geom as geom from invalid_table
)
select id, geom from make_valid where ST_GeometryType(geom)='ST_Polygon';
где invalid_table - таблица, полученная в результате первоначального импорта shp2pgsql.
Я включил сгенерированный идентификатор здесь, так как ST_MakeValid будет потенциально генерировать более одного полигона из входных геометрий. Запрос можно переписать, включив в него исходное поле id, но он больше не будет гарантированно уникальным.
Этот запрос часто исправляет это для меня:
UPDATE place_shapes
SET geometry=ST_Buffer(geometry, 0.0);
Оказывается, что выполнение этого шага постобработки делает свое дело:
UPDATE place_shapes
SET geometry=ST_SimplifyPreserveTopology(geometry, 0.0001)
WHERE ST_IsValid(geometry) = false;
0.0001
Это допустимое отклонение в градусах, возможно, вам придется настроить его по своему вкусу, но для данных карты улиц это кажется правильным.
Кроме того, если ваша таблица форм обеспечивает достоверность (что и должно быть), вам необходимо использовать shp2pgsql
чтобы создать временную непроверенную таблицу, исправьте там свои полигоны и только затем скопируйте их в основную таблицу.