Estoy trabajando con Postgres 9.6 y PostGIS 2.2.2. Estas son mis tablas:
Table "public.allparcels"
Column | Type | Modifiers
----------+-----------------------------+----------------------------------------------------------
gid | integer | not null default nextval('allparcels_gid_seq'::regclass)
the_geog | geometry(MultiPolygon,4326) |
county | character varying |
Table "public.parcels"
Column | Type | Modifiers
--------------+-------------------------+------------------------------------------------------------------
ogc_fid | integer | not null default nextval('parcels_ogc_fid_seq'::regclass)
wkb_geometry | geometry(Polygon,4326) |
county | character varying |
Cuando ejecuto esto (a través de psycopg2):
INSERT INTO allparcels(county, the_geog)
SELECT 'Leeds', ST_MakeValid(ST_Union(wkb_geometry)) FROM parcels WHERE county='Leeds'
Me sale este error:
Traceback (most recent call last):
File "combine.py", line 21, in <module>
cursor.execute(q, (county, county))
psycopg2.InternalError: GEOSUnaryUnion: TopologyException: Input geom 1 is invalid: Self-intersection at or near point -1.394465365015132 53.741246412906918 at -1.394465365015132 53.741246412906918
Pensé que debía tener geometrías subyacentes no válidas, pero no veo ninguna:
SELECT * from parcels WHERE NOT ST_isvalid(wkb_geometry);
no produce ningún resultado. Como muestra la consulta, ya estoy ejecutando ST_MakeValid
para asegurarse de que el polígono unido es válido antes de insertarlo.
¿Qué estoy haciendo mal?
ACTUALIZACIÓN:
Esta es la última consulta que he probado. La depuración de la consulta indica que es la ST_Union la que falla. Disminuir la precisión (incluso a 0,01) no ayuda:
INSERT INTO allparcels(county, the_geog)
SELECT 'Leeds', ST_MakeValid(ST_Union(ST_SnapToGrid(wkb_geometry, .000001)))
FROM parcels WHERE county='Leeds'
0 votos
Si no estás mapeando las máscaras de la CPU en WGS84 podrías intentar usar
ST_SnapToGrid()
para imponer un factor de escala razonable a las coordenadas (0,0000001 es ~1cm). Puede que encuentres más errores de esta manera.0 votos
@Vince gracias. La precisión de 1m debería estar bien. Para que entienda la sintaxis, ¿podrías hacer
ST_Union(ST_SnapToGrid(wkb_geometry, .00001))
?0 votos
Yo probaría primero con 1/1000000 (~11cm). Tenga en cuenta que esto es precisión que se está modificando, no precisión .
0 votos
Sigue apareciendo el mismo mensaje de error. Mi consulta completa es
INSERT INTO allparcels(county, the_geog) SELECT 'Leeds', ST_MakeValid(ST_Union(ST_SnapToGrid(wkb_geometry, .000001))) FROM parcels WHERE county='Leeds'
. La depuración de la consulta indica que es elST_Union
que falla. Disminuir la precisión (incluso a 0,01) no ayuda.0 votos
¡El ST_MakeValid debe ser la función interna, de lo contrario no puede ayudarle aquí!
ST_Union(ST_MakeValid(wkb_geometry))
. Pero lo que me maravilla, es quest_isvalid()
no produce ningún resultado. Siempre he utilizado con éxitoST_Union(ST_Buffer(wkb_geometry, 0))
.1 votos
Podría subir esta tabla a algún sitio, o un subconjunto suficiente para producir el error. Estoy razonablemente seguro de que la respuesta a continuación funcionará, pero si no lo hace, hay otro enfoque posible, pero sería más fácil experimentar localmente, que especular.
2 votos
@RoVo. ST_Buffer(geom, 0) funciona para arreglar las auto-intersecciones en las geometrías de entrada (a menudo procedentes de archivos shp), pero no creo que te ayude cuando las geometrías de entrada son todas reportadas como válidas, y la auto-intersección proviene de la propia intersección.
1 votos
Richard, estoy muy interesado en ayudar a llegar al fondo de esto. Si el siguiente no funciona, estaría muy feliz de trabajar en sus datos este fin de semana, si usted podría subir en algún lugar.