'SQL/MM Spatial exception - null argument';
END IF;
+ -- Get topology id
+ SELECT id FROM topology.topology into topoid
+ WHERE name = atopology;
+
--
-- Check node existance
--
|| 'next_left_edge, next_right_edge,'
|| 'left_face, right_face, geom) '
|| 'VALUES('
- ||newedgeid||','||nodeid
- ||','||oldedge.end_node
- ||','||oldedge.next_left_edge
- ||',-'||anedge
- ||','||oldedge.left_face
- ||','||oldedge.right_face
- ||','||quote_literal(newedge2::text)
+ || newedgeid
+ || ',' || nodeid
+ || ',' || oldedge.end_node
+ || ',' || COALESCE( -- next_left_edge
+ NULLIF(
+ oldedge.next_left_edge,
+ -anedge
+ ),
+ -newedgeid
+ )
+ || ',' || -anedge -- next_right_edge
+ || ',' || oldedge.left_face -- left_face
+ || ',' || oldedge.right_face -- right_face
+ || ',' || quote_literal(newedge2::text) -- geom
||')';
--
|| ' SET geom = ' || quote_literal(newedge1::text)
|| ','
|| ' next_left_edge = ' || newedgeid
+ || ', abs_next_left_edge = ' || newedgeid
|| ','
|| ' end_node = ' || nodeid
|| ' WHERE edge_id = ' || anedge;
|| -newedgeid
|| ','
|| ' abs_next_right_edge = ' || newedgeid
- || ' WHERE next_right_edge = ' || -anedge;
+ || ' WHERE edge_id != ' || newedgeid
+ || ' AND next_right_edge = ' || -anedge;
EXECUTE 'UPDATE ' || quote_ident(atopology)
|| '.edge_data SET '
|| ' next_left_edge = ' || -newedgeid
|| ','
|| ' abs_next_left_edge = ' || newedgeid
- || ' WHERE next_left_edge = ' || -anedge;
-
- -- Get topology id
- SELECT id FROM topology.topology into topoid
- WHERE name = atopology;
+ || ' WHERE edge_id != ' || newedgeid
+ || ' AND next_left_edge = ' || -anedge;
--
-- Update references in the Relation table.
regress/st_getfacegeometry.sql \
regress/st_getfaceedges.sql \
regress/st_modedgeheal.sql \
+ regress/st_modedgesplit.sql \
regress/st_newedgeheal.sql \
regress/st_remedgenewface.sql \
regress/st_remedgemodface.sql \
--- /dev/null
+
+\set VERBOSITY terse
+set client_min_messages to ERROR;
+
+-- Import city_data
+\i load_topology.sql
+
+-- Save max node id
+select 'node'::text as what, max(node_id) INTO city_data.limits FROM city_data.node;
+INSERT INTO city_data.limits select 'edge'::text as what, max(edge_id) FROM city_data.edge;
+SELECT 'max',* from city_data.limits;
+
+-- Check changes since last saving, save more
+-- {
+CREATE OR REPLACE FUNCTION check_changes()
+RETURNS TABLE (o text)
+AS $$
+DECLARE
+ rec RECORD;
+ sql text;
+BEGIN
+ -- Check effect on nodes
+ sql := 'SELECT n.node_id, ''N|'' || n.node_id || ''|'' ||
+ COALESCE(n.containing_face::text,'''') || ''|'' ||
+ ST_AsText(ST_SnapToGrid(n.geom, 0.2))::text as xx
+ FROM city_data.node n WHERE n.node_id > (
+ SELECT max FROM city_data.limits WHERE what = ''node''::text )
+ ORDER BY n.node_id';
+
+ FOR rec IN EXECUTE sql LOOP
+ o := rec.xx;
+ RETURN NEXT;
+ END LOOP;
+
+ -- Check effect on edges (there should be one split)
+ sql := '
+ WITH node_limits AS ( SELECT max FROM city_data.limits WHERE what = ''node''::text ),
+ edge_limits AS ( SELECT max FROM city_data.limits WHERE what = ''edge''::text )
+ SELECT ''E|'' || e.edge_id || ''|sn'' || e.start_node || ''|en'' || e.end_node
+ || ''|nl'' || e.next_left_edge
+ || ''|nr'' || e.next_right_edge
+ || ''|lf'' || e.left_face
+ || ''|rf'' || e.right_face
+ :: text as xx
+ FROM city_data.edge e, node_limits nl, edge_limits el
+ WHERE e.start_node > nl.max
+ OR e.end_node > nl.max
+ OR e.edge_id > el.max
+ ORDER BY e.edge_id;
+ ';
+
+ FOR rec IN EXECUTE sql LOOP
+ o := rec.xx;
+ RETURN NEXT;
+ END LOOP;
+
+ UPDATE city_data.limits SET max = (SELECT max(n.node_id) FROM city_data.node n) WHERE what = 'node';
+ UPDATE city_data.limits SET max = (SELECT max(e.edge_id) FROM city_data.edge e) WHERE what = 'edge';
+
+END;
+$$ LANGUAGE 'plpgsql';
+-- }
+
+-- Invalid calls
+SELECT 'invalid', ST_ModEdgeSplit('city_data', 999, 'POINT(36 26, 38 30)');
+SELECT 'invalid', ST_ModEdgeSplit('city_data', 10, 'POINT(28 15)');
+SELECT 'invalid', ST_ModEdgeSplit('', 10, 'POINT(28 14)');
+SELECT 'invalid', ST_ModEdgeSplit(NULL, 10, 'POINT(28 14)');
+SELECT 'invalid', ST_ModEdgeSplit('city_data', NULL, 'POINT(28 14)');
+SELECT 'invalid', ST_ModEdgeSplit('city_data', 10, NULL);
+SELECT 'invalid', ST_ModEdgeSplit('fake', 10, 'POINT(28 14)');
+
+-- Non-isolated edge
+SELECT 'noniso', ST_ModEdgeSplit('city_data', 10, 'POINT(28 14)');
+SELECT check_changes();
+
+-- Isolated edge
+SELECT 'iso', ST_ModEdgeSplit('city_data', 25, 'POINT(11 35)');
+SELECT check_changes();
+
+-- Dangling on end point
+SELECT 'dangling_end', ST_ModEdgeSplit('city_data', 3, 'POINT(25 32)');
+SELECT check_changes();
+
+-- Dangling on start point
+SELECT 'dangling_start', ST_ModEdgeSplit('city_data', 4, 'POINT(45 32)');
+SELECT check_changes();
+
+-- Splitting closed edge
+SELECT 'closed', ST_ModEdgeSplit('city_data', 1, 'POINT(3 38)');
+SELECT check_changes();
+
+
+
+DROP FUNCTION check_changes();
+SELECT DropTopology('city_data');
--- /dev/null
+BEGIN
+t
+9
+22
+26
+COMMIT
+max|node|22
+max|edge|26
+ERROR: geometry has too many points at character 53
+ERROR: SQL/MM Spatial exception - point not on edge
+ERROR: zero-length delimited identifier at or near """" at character 15
+ERROR: SQL/MM Spatial exception - null argument
+ERROR: SQL/MM Spatial exception - null argument
+ERROR: SQL/MM Spatial exception - null argument
+ERROR: schema "fake" does not exist at character 15
+noniso|23
+N|23||POINT(28 14)
+E|10|sn13|en23|nl27|nr17|lf7|rf4
+E|27|sn23|en14|nl-20|nr-10|lf7|rf4
+iso|24
+N|24||POINT(11 35)
+E|25|sn21|en24|nl28|nr25|lf1|rf1
+E|28|sn24|en22|nl-28|nr-25|lf1|rf1
+dangling_end|25
+N|25||POINT(25 32)
+E|3|sn2|en25|nl29|nr2|lf2|rf2
+E|29|sn25|en3|nl-29|nr-3|lf2|rf2
+dangling_start|26
+N|26||POINT(45 32)
+E|4|sn5|en26|nl30|nr4|lf0|rf0
+E|30|sn26|en6|nl-5|nr-4|lf0|rf0
+closed|27
+N|27||POINT(3 38)
+E|1|sn1|en27|nl31|nr-31|lf1|rf0
+E|31|sn27|en1|nl1|nr-1|lf1|rf0
+Topology 'city_data' dropped