Discussion:
problems cleaning geometry - other options?
William Kyngesburye
2008-12-04 00:08:45 UTC
Permalink
I'm trying to fix some polygons-with-holes imported from shapefiles
where the main polygon is not the first in the list, one of the hole
polygons is, making them invalid.

These are 3D multipolygons - imported from the SRTM SWBD shapefiles
(with GDAL). (file w162n55n if anyone wants to try)

The cleanGeometry funtion at:

http://postgis.refractions.net/support/wiki/index.php?CleanPolygons

isn't working, I get an error:

=>select astext(cleangeometry(wkb_geometry)) from swbd where cell =
145018 and wb = 353;
NOTICE: Hole lies outside shell at or near point -161.201 55.9992 0
CONTEXT: PL/pgSQL function "cleangeometry" line 15 at IF
ERROR: Dimensions mismatch in lwcurve
CONTEXT: PL/pgSQL function "cleangeometry" line 19 at assignment

I tried forcing the geometry to 2D (st_force_2d()) and I get a
different error:

NOTICE: Hole lies outside shell at or near point -161.201 55.9992
CONTEXT: PL/pgSQL function "cleangeometry" line 15 at IF
ERROR: Exception in LWGEOM2GEOS: curved geometry not supported.
CONTEXT: PL/pgSQL function "cleangeometry" line 19 at assignment

These shapefiles don't have curved geometry (I'm not sure it's
supported in shapefiles).


I wonder if there is a simpler operation that could reorder sub-
polygons to put the one that contains all the others first? And would
it be faster or slower?

-----
William Kyngesburye <kyngchaos*at*kyngchaos*dot*com>
http://www.kyngchaos.com/

"History is an illusion caused by the passage of time, and time is an
illusion caused by the passage of history."

- Hitchhiker's Guide to the Galaxy
Mark Cave-Ayland
2008-12-04 10:44:17 UTC
Permalink
Post by William Kyngesburye
I'm trying to fix some polygons-with-holes imported from shapefiles
where the main polygon is not the first in the list, one of the hole
polygons is, making them invalid.
These are 3D multipolygons - imported from the SRTM SWBD shapefiles
(with GDAL). (file w162n55n if anyone wants to try)
http://postgis.refractions.net/support/wiki/index.php?CleanPolygons
=>select astext(cleangeometry(wkb_geometry)) from swbd where cell =
145018 and wb = 353;
NOTICE: Hole lies outside shell at or near point -161.201 55.9992 0
CONTEXT: PL/pgSQL function "cleangeometry" line 15 at IF
ERROR: Dimensions mismatch in lwcurve
CONTEXT: PL/pgSQL function "cleangeometry" line 19 at assignment
I tried forcing the geometry to 2D (st_force_2d()) and I get a different
NOTICE: Hole lies outside shell at or near point -161.201 55.9992
CONTEXT: PL/pgSQL function "cleangeometry" line 15 at IF
ERROR: Exception in LWGEOM2GEOS: curved geometry not supported.
CONTEXT: PL/pgSQL function "cleangeometry" line 19 at assignment
These shapefiles don't have curved geometry (I'm not sure it's supported
in shapefiles).
I wonder if there is a simpler operation that could reorder sub-polygons
to put the one that contains all the others first? And would it be
faster or slower?
Hi William,

Which versions of PostgreSQL/PostGIS is this? Since the error message in
question is only in the lwcurve curve, it sounds like an internal error.
If you can extract a standalone test case and post it on the bug
tracker, I'll take a look at it.


ATB,

Mark.
--
Mark Cave-Ayland
Sirius Corporation - The Open Source Experts
http://www.siriusit.co.uk
T: +44 870 608 0063
Kevin Neufeld
2008-12-04 16:53:08 UTC
Permalink
Correct. I assumed in your case that the rings do not need to be noded against eachother (that's what st_union is for),
they just need to be sorted to determine the outer and inner rings (that's a task for BuildArea).
Glad it works.
-- Kevin
That works. It looks essentially the same as what's in the
cleangeometry function from the wiki, but much simpler. There's
st_union and st_multi in there betwen the buildarea and boundary
functions, probably to handle other invalid stuff.
Have you tried updating the geometry with a new polygonized polygon
constructed from the linework?
UPDATE swbd
SET wkb_geometry = ST_BuildArea(ST_Boundary(wkb_geometry))
WHERE cell = 145018 AND wb = 353;
Cheers,
-- Kevin
-----
William Kyngesburye <kyngchaos*at*kyngchaos*dot*com>
http://www.kyngchaos.com/
First Pogril: Why is life like sticking your head in a bucket filled
with hyena offal?
Second Pogril: I don't know. Why IS life like sticking your head in a
bucket filled with hyena offal?
First Pogril: I don't know either. Wretched, isn't it?
-HitchHiker's Guide to the Galaxy
Kevin Neufeld
2008-12-04 20:33:12 UTC
Permalink
I wonder if there is a way for a postgres function to see what the
actual kind of validity error is (it just comes up as a NOTICE: in the
sql output)?
Yes, very new and still in discussion amongst the development team, but it's possible to do this with the development
branch (svn head) of PostGIS.

postgis=# SELECT ST_IsValidReason(
'POLYGON (( 0 0, 0 4, 4 4, 4 0, 0 0 ),
( 3 5, 2 5, 2 6, 3 6, 3 5 ))'::geometry);
st_isvalidreason
-------------------------------
Hole lies outside shell [3 5]
(1 row)


test=# SELECT ST_IsValidReason(
'POLYGON (( 0 0, 0 4, 4 4, 4 0, 0 0 ),
( 2 2, 2 3, 3 3, 5 2, 2 2 ))'::geometry);
st_isvalidreason
---------------------------
Self-intersection [4 2.5]
(1 row)


Cheers,
Kevin
William Kyngesburye
2008-12-04 18:46:52 UTC
Permalink
Post by Kevin Neufeld
Correct. I assumed in your case that the rings do not need to be
noded against eachother (that's what st_union is for), they just
need to be sorted to determine the outer and inner rings (that's a
task for BuildArea).
Glad it works.
-- Kevin
That works. It looks essentially the same as what's in the
cleangeometry function from the wiki, but much simpler. There's
st_union and st_multi in there betwen the buildarea and boundary
functions, probably to handle other invalid stuff.
Have you tried updating the geometry with a new polygonized
polygon constructed from the linework?
UPDATE swbd
SET wkb_geometry = ST_BuildArea(ST_Boundary(wkb_geometry))
WHERE cell = 145018 AND wb = 353;
Cheers,
-- Kevin
I wonder if there is a way for a postgres function to see what the
actual kind of validity error is (it just comes up as a NOTICE: in the
sql output)? I ran thru the whole database to see how many invalid
polys there are (10700 of 625000) and what they are (and how long it
will take just to test validity... 5m, not bad), and I see more than
just this one case I first ran into (hole outside shell):

NOTICE: Hole lies outside shell at or near point x y [not many of
these]
NOTICE: Nested shells at or near point x y [lots of these]
NOTICE: Holes are nested at or near point x y [lots of these]
NOTICE: Self-intersection at or near point x y
NOTICE: Ring Self-intersection at or near point x y
NOTICE: Interior is disconnected at or near point x y [a few of these]

It would be nice if the cleangeometry function could use the right
combination of geometry operations depending on the type of geometry
error.

-----
William Kyngesburye <kyngchaos*at*kyngchaos*dot*com>
http://www.kyngchaos.com/

"Those people who most want to rule people are, ipso-facto, those
least suited to do it."

- A rule of the universe, from the HitchHiker's Guide to the Galaxy
William Kyngesburye
2008-12-04 14:56:19 UTC
Permalink
That works. It looks essentially the same as what's in the
cleangeometry function from the wiki, but much simpler. There's
st_union and st_multi in there betwen the buildarea and boundary
functions, probably to handle other invalid stuff.
Have you tried updating the geometry with a new polygonized polygon
constructed from the linework?
UPDATE swbd
SET wkb_geometry = ST_BuildArea(ST_Boundary(wkb_geometry))
WHERE cell = 145018 AND wb = 353;
Cheers,
-- Kevin
-----
William Kyngesburye <kyngchaos*at*kyngchaos*dot*com>
http://www.kyngchaos.com/

First Pogril: Why is life like sticking your head in a bucket filled
with hyena offal?
Second Pogril: I don't know. Why IS life like sticking your head in a
bucket filled with hyena offal?
First Pogril: I don't know either. Wretched, isn't it?

-HitchHiker's Guide to the Galaxy
Kevin Neufeld
2008-12-04 07:02:02 UTC
Permalink
Have you tried updating the geometry with a new polygonized polygon
constructed from the linework?

UPDATE swbd
SET wkb_geometry = ST_BuildArea(ST_Boundary(wkb_geometry))
WHERE cell = 145018 AND wb = 353;

Cheers,
-- Kevin
Post by William Kyngesburye
I'm trying to fix some polygons-with-holes imported from shapefiles
where the main polygon is not the first in the list, one of the hole
polygons is, making them invalid.
These are 3D multipolygons - imported from the SRTM SWBD shapefiles
(with GDAL). (file w162n55n if anyone wants to try)
http://postgis.refractions.net/support/wiki/index.php?CleanPolygons
=>select astext(cleangeometry(wkb_geometry)) from swbd where cell =
145018 and wb = 353;
NOTICE: Hole lies outside shell at or near point -161.201 55.9992 0
CONTEXT: PL/pgSQL function "cleangeometry" line 15 at IF
ERROR: Dimensions mismatch in lwcurve
CONTEXT: PL/pgSQL function "cleangeometry" line 19 at assignment
I tried forcing the geometry to 2D (st_force_2d()) and I get a
NOTICE: Hole lies outside shell at or near point -161.201 55.9992
CONTEXT: PL/pgSQL function "cleangeometry" line 15 at IF
ERROR: Exception in LWGEOM2GEOS: curved geometry not supported.
CONTEXT: PL/pgSQL function "cleangeometry" line 19 at assignment
These shapefiles don't have curved geometry (I'm not sure it's
supported in shapefiles).
I wonder if there is a simpler operation that could reorder
sub-polygons to put the one that contains all the others first? And
would it be faster or slower?
-----
William Kyngesburye <kyngchaos*at*kyngchaos*dot*com>
http://www.kyngchaos.com/
"History is an illusion caused by the passage of time, and time is an
illusion caused by the passage of history."
- Hitchhiker's Guide to the Galaxy
_______________________________________________
postgis-users mailing list
http://postgis.refractions.net/mailman/listinfo/postgis-users
Continue reading on narkive:
Loading...