From: Sandro Santilli Date: Thu, 26 May 2011 07:26:56 +0000 (+0000) Subject: Error handling refinements in topology.ST_AddEdgeNewFaces (#988) X-Git-Tag: 2.0.0alpha1~1561 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fe9e336ea9a245225ca4f64452ddc15342e03d4b;p=postgis Error handling refinements in topology.ST_AddEdgeNewFaces (#988) Check for given edge having two distinct vertices before getting a new edge id from sequence, and before testing it for crossing nodes (or it'd give a confusing error message). Refine error message about no-segment edges to not talk about nodes. [RT-SIGTA] git-svn-id: http://svn.osgeo.org/postgis/trunk@7253 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/topology/sql/sqlmm.sql b/topology/sql/sqlmm.sql index d00b31767..cb83709db 100644 --- a/topology/sql/sqlmm.sql +++ b/topology/sql/sqlmm.sql @@ -1905,7 +1905,6 @@ DECLARE sql TEXT; newfaces INTEGER[]; newface INTEGER; - cleangeom GEOMETRY; BEGIN -- @@ -1952,9 +1951,34 @@ BEGIN NULL::int as prev_left_edge, NULL::int as prev_right_edge, -- convenience anode = anothernode as isclosed, -- convenience false as start_node_isolated, -- convenience - false as end_node_isolated -- convenience + false as end_node_isolated, -- convenience + ST_RemoveRepeatedPoints(acurve) as cleangeom -- convenience INTO newedge; + -- Compute azimut of first edge end on start node + SELECT null::int AS nextCW, null::int AS nextCCW, + null::float8 AS minaz, null::float8 AS maxaz, + false AS was_isolated, + ST_Azimuth(ST_StartPoint(newedge.cleangeom), + ST_PointN(newedge.cleangeom, 2)) AS myaz + INTO span; + IF span.myaz IS NULL THEN + RAISE EXCEPTION 'Invalid edge (no two distinct vertices exist)'; + END IF; + + -- Compute azimuth of last edge end on end node + SELECT null::int AS nextCW, null::int AS nextCCW, + null::float8 AS minaz, null::float8 AS maxaz, + false AS was_isolated, + ST_Azimuth(ST_EndPoint(newedge.cleangeom), + ST_PointN(newedge.cleangeom, + ST_NumPoints(newedge.cleangeom)-1)) AS myaz + INTO epan; + IF epan.myaz IS NULL THEN + RAISE EXCEPTION 'Invalid edge (no two distinct vertices exist)'; + END IF; + + -- -- Check endpoints existance, match with Curve geometry -- and get face information (if any) @@ -2074,48 +2098,25 @@ BEGIN quote_ident(atopology) || '.edge_data_edge_id_seq') || ')' INTO STRICT newedge.edge_id; - cleangeom := ST_RemoveRepeatedPoints(acurve); - - -- Compute azimut of first edge end on start node - SELECT null::int AS nextCW, null::int AS nextCCW, - null::float8 AS minaz, null::float8 AS maxaz, - false AS was_isolated, - ST_Azimuth(ST_StartPoint(cleangeom), - ST_PointN(cleangeom, 2)) AS myaz - INTO span; - IF span.myaz IS NULL THEN - RAISE EXCEPTION 'Invalid edge (no two distinct nodes exist)'; - END IF; - - -- Compute azimuth of last edge end on end node - SELECT null::int AS nextCW, null::int AS nextCCW, - null::float8 AS minaz, null::float8 AS maxaz, - false AS was_isolated, - ST_Azimuth(ST_EndPoint(cleangeom), - ST_PointN(cleangeom, ST_NumPoints(cleangeom)-1)) AS myaz - INTO epan; - IF epan.myaz IS NULL THEN - RAISE EXCEPTION 'Invalid edge (no two distinct nodes exist)'; - END IF; - -- Find links on start node -- { RAISE DEBUG 'My start-segment azimuth: %', span.myaz; sql := - 'SELECT edge_id, -1 AS end_node, start_node, left_face, right_face, geom' - || ' FROM ' + 'SELECT edge_id, -1 AS end_node, start_node, left_face, right_face, ' + || 'ST_RemoveRepeatedPoints(geom) as geom FROM ' || quote_ident(atopology) || '.edge_data WHERE start_node = ' || anode - || ' UNION SELECT edge_id, end_node, -1, left_face, right_face, geom FROM ' + || ' UNION SELECT edge_id, end_node, -1, left_face, right_face, ' + || 'ST_RemoveRepeatedPoints(geom) FROM ' || quote_ident(atopology) || '.edge_data WHERE end_node = ' || anode; IF newedge.isclosed THEN sql := sql || ' UNION SELECT ' || newedge.edge_id || ',' || newedge.end_node || ',-1,0,0,' -- pretend we start elsewhere - || quote_literal(newedge.geom::text); + || quote_literal(newedge.cleangeom::text); END IF; i := 0; FOR rec IN EXECUTE sql @@ -2123,22 +2124,20 @@ BEGIN i := i + 1; - cleangeom := ST_RemoveRepeatedPoints(rec.geom); - IF rec.start_node = anode THEN -- -- Edge starts at our node, we compute -- azimuth from node to its second point -- - az := ST_Azimuth(ST_StartPoint(cleangeom), ST_PointN(cleangeom, 2)); + az := ST_Azimuth(ST_StartPoint(rec.geom), ST_PointN(rec.geom, 2)); ELSE -- -- Edge ends at our node, we compute -- azimuth from node to its second-last point -- - az := ST_Azimuth(ST_EndPoint(cleangeom), - ST_PointN(cleangeom, ST_NumPoints(cleangeom)-1)); + az := ST_Azimuth(ST_EndPoint(rec.geom), + ST_PointN(rec.geom, ST_NumPoints(rec.geom)-1)); rec.edge_id := -rec.edge_id; END IF; @@ -2220,19 +2219,19 @@ BEGIN RAISE DEBUG 'My end-segment azimuth: %', epan.myaz; sql := - 'SELECT edge_id, -1 as end_node, start_node, left_face, right_face, geom' - || ' FROM ' + 'SELECT edge_id, -1 as end_node, start_node, left_face, right_face, ' + || 'ST_RemoveRepeatedPoints(geom) as geom FROM ' || quote_ident(atopology) || '.edge_data WHERE start_node = ' || anothernode - || 'UNION SELECT edge_id, end_node, -1, left_face, right_face, geom' - || ' FROM ' + || 'UNION SELECT edge_id, end_node, -1, left_face, right_face, ' + || 'ST_RemoveRepeatedPoints(geom) FROM ' || quote_ident(atopology) || '.edge_data WHERE end_node = ' || anothernode; IF newedge.isclosed THEN sql := sql || ' UNION SELECT ' || newedge.edge_id || ',' || -1 -- pretend we end elsewhere || ',' || newedge.start_node || ',0,0,' - || quote_literal(newedge.geom::text); + || quote_literal(newedge.cleangeom::text); END IF; i := 0; FOR rec IN EXECUTE sql @@ -2240,22 +2239,21 @@ BEGIN i := i + 1; - cleangeom := ST_RemoveRepeatedPoints(rec.geom); - IF rec.start_node = anothernode THEN -- -- Edge starts at our node, we compute -- azimuth from node to its second point -- - az := ST_Azimuth(ST_StartPoint(cleangeom), ST_PointN(cleangeom, 2)); + az := ST_Azimuth(ST_StartPoint(rec.geom), + ST_PointN(rec.geom, 2)); ELSE -- -- Edge ends at our node, we compute -- azimuth from node to its second-last point -- - az := ST_Azimuth(ST_EndPoint(cleangeom), - ST_PointN(cleangeom, ST_NumPoints(cleangeom)-1)); + az := ST_Azimuth(ST_EndPoint(rec.geom), + ST_PointN(rec.geom, ST_NumPoints(rec.geom)-1)); rec.edge_id := -rec.edge_id; END IF; diff --git a/topology/test/regress/st_addedgenewfaces.sql b/topology/test/regress/st_addedgenewfaces.sql index 0cc0d4908..9270eeaf8 100644 --- a/topology/test/regress/st_addedgenewfaces.sql +++ b/topology/test/regress/st_addedgenewfaces.sql @@ -22,6 +22,14 @@ SELECT topology.ST_AddEdgeNewFaces('city_data', 60000, 6, SELECT topology.ST_AddEdgeNewFaces('city_data', 5, 5, 'LINESTRING(36 38, 40 50, 36 38)'); +-- Collapsed curve +SELECT topology.ST_AddEdgeNewFaces('city_data', 5, 5, + 'LINESTRING(36 38, 36 38, 36 38)'); + +-- Empty curve +SELECT topology.ST_AddEdgeNewFaces('city_data', 5, 5, + 'LINESTRING EMPTY'); + -- Coincident edge SELECT topology.ST_AddEdgeNewFaces('city_data', 18, 19, 'LINESTRING(35 22,47 22)'); diff --git a/topology/test/regress/st_addedgenewfaces_expected b/topology/test/regress/st_addedgenewfaces_expected index d91a5a70d..f27d54c9d 100644 --- a/topology/test/regress/st_addedgenewfaces_expected +++ b/topology/test/regress/st_addedgenewfaces_expected @@ -10,6 +10,8 @@ ERROR: SQL/MM Spatial exception - geometry crosses a node ERROR: SQL/MM Spatial exception - non-existent node ERROR: SQL/MM Spatial exception - non-existent node ERROR: SQL/MM Spatial exception - curve not simple +ERROR: Invalid edge (no two distinct vertices exist) +ERROR: Invalid edge (no two distinct vertices exist) ERROR: SQL/MM Spatial exception - coincident edge ERROR: SQL/MM Spatial exception - geometry crosses an edge ERROR: SQL/MM Spatial exception - geometry crosses an edge