--{
--
--- AddNode(atopology, point)
+-- AddNode(atopology, point, allowEdgeSplitting, setContainingFace)
--
-- Add a node primitive to a topology and get its identifier.
-- Returns an existing node at the same location, if any.
--
-- The newly added nodes have no containing face.
--
---
-CREATE OR REPLACE FUNCTION topology.AddNode(atopology varchar, apoint geometry)
+-- }{
+CREATE OR REPLACE FUNCTION topology.AddNode(atopology varchar, apoint geometry, allowEdgeSplitting boolean, setContainingFace boolean DEFAULT false)
RETURNS int
AS
$$
DECLARE
nodeid int;
rec RECORD;
+ containing_face int;
BEGIN
--
-- Atopology and apoint are required
|| quote_literal(apoint::text)
|| ', ST_EndPoint(geom))'
LOOP
- RAISE EXCEPTION 'An edge crosses the given node.';
+ IF allowEdgeSplitting THEN
+ RETURN ST_ModEdgeSplit(atopology, rec.edge_id, apoint);
+ ELSE
+ RAISE EXCEPTION 'An edge crosses the given node.';
+ END IF;
END LOOP;
+ IF setContainingFace THEN
+ containing_face := topology.GetFaceByPoint(atopology, apoint, 0);
+ RAISE DEBUG 'containing face: %', containing_face;
+ ELSE
+ containing_face := NULL;
+ END IF;
+
--
-- Get new node id from sequence
--
-- Insert the new row
--
EXECUTE 'INSERT INTO ' || quote_ident(atopology)
- || '.node(node_id, geom)
- VALUES('||nodeid||','||quote_literal(apoint::text)||
- ')';
+ || '.node(node_id, containing_face, geom)
+ VALUES(' || nodeid || ',' || coalesce(containing_face::text, 'NULL') || ','
+ || quote_literal(apoint::text) || ')';
RETURN nodeid;
LANGUAGE 'plpgsql' VOLATILE;
--} AddNode
+--{
+--
+-- AddNode(atopology, point)
+--
+CREATE OR REPLACE FUNCTION topology.AddNode(atopology varchar, apoint geometry)
+ RETURNS int
+AS
+$$
+ SELECT topology.AddNode($1, $2, false, false);
+$$
+LANGUAGE 'sql' VOLATILE;
+--} AddNode
+
--{
--
-- AddEdge(atopology, line)
-- Check that adding a node in the middle of an existing edge is refused
-- While adding one on the endpoint is fine
-INSERT INTO nodes.edge VALUES(1,1,1,1,-1,0,0,'LINESTRING(0 10,10 10)');
+INSERT INTO nodes.edge VALUES(nextval('nodes.edge_data_edge_id_seq'),1,1,1,-1,0,0,
+ 'LINESTRING(0 10,10 10)');
SELECT 'p3*1', topology.addNode('nodes', 'POINT(5 10)'); -- refused
SELECT 'p3', topology.addNode('nodes', 'POINT(0 10)'); -- good
SELECT 'p4', topology.addNode('nodes', 'POINT(10 10)'); -- good
+
+-- Now allow edge splitting:
+SELECT 'p5', topology.addNode('nodes', 'POINT(5 10)', true);
+-- ... and verify the edge was split
+SELECT 'post-p5', edge_id, ST_AsText(geom) FROM nodes.edge ORDER BY edge_id;
+
+
-- And same against a closed edge
-INSERT INTO nodes.edge VALUES(2,2,2,2,-2,0,0,
- 'LINESTRING(0 20,10 20,10 30, 0 30, 0 20)');
-SELECT 'p5', topology.addNode('nodes', 'POINT(0 20)'); -- good
+INSERT INTO nodes.face VALUES(nextval('nodes.face_face_id_seq'), 'POLYGON((0 20, 10 20, 10 30, 0 30, 0 20))');
+INSERT INTO nodes.edge VALUES(nextval('nodes.edge_data_edge_id_seq'),2,2,2,-2,1,0,
+ 'LINESTRING(0 20,10 20,10 30, 0 30, 0 20)');
+SELECT 'p6', topology.addNode('nodes', 'POINT(0 20)'); -- good
--- Check we only have two points, both with unknown containing face
+-- Now allow computing containing face:
+SELECT 'p7', topology.addNode('nodes', 'POINT(5 25)', false, true);
+-- Check all nodes
SELECT node_id, containing_face, st_astext(geom) from nodes.node
ORDER by node_id;