IF setContainingFace THEN
containing_face := topology.GetFaceByPoint(atopology, apoint, 0);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'containing face: %', containing_face;
+#endif
ELSE
containing_face := NULL;
END IF;
-- Reuse an EQUAL edge (be it closed or not)
IF ST_RelateMatch(rec.im, '1FFF*FFF2') THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Edge already known as %', rec.edge_id;
+#endif
RETURN rec.edge_id;
END IF;
right_side = ST_Line_Locate_Point(bounds, p1) <
ST_Line_Locate_Point(bounds, p2);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Edge % (left:%, right:%) - ring : % - right_side : %',
rec.edge_id, rec.left_face, rec.right_face, rrec.path, right_side;
+#endif
IF right_side THEN
right_edges := array_append(right_edges, rec.edge_id);
RAISE EXCEPTION 'Found no edges on the polygon boundary';
END IF;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Left edges: %', left_edges;
+#endif
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Right edges: %', right_edges;
+#endif
--
-- Check that all edges found, taken togheter,
IF faceid IS NOT NULL AND faceid != 0 THEN
IF NOT force_new THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Face already known as %, not forcing a new face', faceid;
+#endif
RETURN faceid;
ELSE
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Face already known as %, forcing a new face', faceid;
+#endif
END IF;
END IF;
|| tolerance || ') ORDER BY ST_Distance('
|| quote_literal(apoint::text)
|| '::geometry, a.geom) LIMIT 1;';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG '%', sql;
+#endif
EXECUTE sql INTO id;
IF id IS NOT NULL THEN
RETURN id;
END IF;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'No existing node within tolerance distance';
+#endif
-- 2. Check if any existing edge falls within tolerance
-- and if so split it by a point projected on it
|| tolerance || ') ORDER BY ST_Distance('
|| quote_literal(apoint::text)
|| '::geometry, a.geom) LIMIT 1;';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG '%', sql;
+#endif
EXECUTE sql INTO rec;
IF rec IS NOT NULL THEN
-- project point to line, split edge by point
prj := ST_ClosestPoint(rec.geom, apoint);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Splitting edge % with closest point %', rec.edge_id, ST_AsText(prj);
+#endif
IF NOT ST_Contains(rec.geom, prj) THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' Snapping edge to contain closest point';
+#endif
-- Snap the edge geometry to the projected point
-- The tolerance is an arbitrary number.
-- How much would be enough to ensure any projected point is within
END IF;
id := topology.ST_ModEdgeSplit(atopology, rec.edge_id, prj);
ELSE
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'No existing edge within tolerance distance';
+#endif
id := topology.ST_AddIsoNode(atopology, NULL, apoint);
END IF;
-- 1. Self-node
noded := ST_UnaryUnion(aline);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Self-noded: %', ST_AsText(noded);
+#endif
-- 2. Node to edges and nodes falling within tolerance distance
sql := 'WITH nearby AS ( SELECT geom FROM '
|| '.edge WHERE ST_DWithin(geom,'
|| quote_literal(aline::text) || '::geometry,'
|| tolerance || ') ) SELECT st_collect(geom) FROM nearby;';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG '%', sql;
+#endif
EXECUTE sql INTO set1;
IF set1 IS NOT NULL THEN
snapped := ST_Snap(noded, set1, tolerance);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Snapped: %', ST_AsText(snapped);
+#endif
noded := ST_Difference(snapped, set1);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Difference: %', ST_AsText(noded);
+#endif
set2 := ST_Intersection(snapped, set1);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Intersection: %', ST_AsText(set2);
+#endif
noded := ST_Union(noded, set2);
-- TODO: linemerge ?
END IF;
-- TODO: skip point elements ?
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Adding edge %', ST_AsText(rec.geom);
+#endif
start_node := topology.TopoGeo_AddPoint(atopology,
ST_StartPoint(rec.geom),
tolerance);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' Start Node: %', start_node;
+#endif
end_node := topology.TopoGeo_AddPoint(atopology,
ST_EndPoint(rec.geom),
tolerance);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' End Node: %', end_node;
+#endif
-- Added endpoints may have drifted due to tolerance, so
-- we need to re-snap the edge to the new nodes before adding it
sql := 'SELECT ST_Collect(geom) FROM ' || quote_ident(atopology)
|| '.node WHERE node_id IN (' || start_node || ',' || end_node || ')';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG '%', sql;
+#endif
EXECUTE sql INTO STRICT set2;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Endnodes: %', ST_AsText(set2);
+#endif
snapped := ST_Snap(rec.geom, set2, tolerance);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Snapped edge: %', ST_AsText(snapped);
+#endif
-- Check if the so-snapped edge _now_ exists
sql := 'SELECT edge_id FROM ' || quote_ident(atopology)
|| '.edge_data WHERE ST_Equals(geom, ' || quote_literal(snapped::text)
|| '::geometry)';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG '%', sql;
+#endif
EXECUTE sql INTO id;
IF id IS NULL THEN
id := topology.ST_AddEdgeModFace(atopology, start_node, end_node,
snapped);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'New edge id: %', id;
+#endif
ELSE
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Old edge id: %', id;
+#endif
END IF;
RETURN NEXT id;
-- 1. Extract boundary
boundary := ST_Boundary(apoly);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Boundary: %', ST_AsText(boundary);
+#endif
-- 2. Add boundaries as edges
FOR rec IN SELECT (ST_Dump(boundary)).geom LOOP
edges := array_cat(edges, array_agg(x)) FROM ( select topology.TopoGeo_addLinestring(atopology, rec.geom, tolerance) as x ) as foo;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'New edges: %', edges;
+#endif
END LOOP;
-- 3. Find faces covered by input polygon
|| '.face f WHERE f.mbr && '
|| quote_literal(apoly::text)
|| '::geometry';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG '%', sql;
+#endif
FOR rec IN EXECUTE sql LOOP
-- check for actual containment
fgeom := ST_PointOnSurface(ST_GetFaceGeometry(atopology, rec.face_id));
IF NOT ST_Covers(apoly, fgeom) THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Face % not covered by input polygon', rec.face_id;
+#endif
CONTINUE;
END IF;
RETURN NEXT rec.face_id;
FOR rec IN EXECUTE sql
LOOP
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'rn:%, n:%, edg:%, cnt:%, min:%, reord:%',
rec.rn, n, rec.edge_id, rec.cnt, rec.min, rec.reord;
+#endif
retrec.sequence = n;
retrec.edge = rec.edge_id;
rec.geom = ST_LineMerge(ST_Collect(e1rec.geom, e2rec.geom));
IF caseno = 1 THEN -- e1.end = e2.start
IF NOT ST_Equals(ST_StartPoint(rec.geom), ST_StartPoint(e1rec.geom)) THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'caseno=1: LineMerge did not maintain startpoint';
+#endif
rec.geom = ST_Reverse(rec.geom);
END IF;
rec.end_node = e2rec.end_node;
e2sign = 1;
ELSIF caseno = 2 THEN -- e1.end = e2.end
IF NOT ST_Equals(ST_StartPoint(rec.geom), ST_StartPoint(e1rec.geom)) THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'caseno=2: LineMerge did not maintain startpoint';
+#endif
rec.geom = ST_Reverse(rec.geom);
END IF;
rec.end_node = e2rec.start_node;
e2sign = -1;
ELSIF caseno = 3 THEN -- e1.start = e2.start
IF NOT ST_Equals(ST_EndPoint(rec.geom), ST_EndPoint(e1rec.geom)) THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'caseno=4: LineMerge did not maintain endpoint';
+#endif
rec.geom = ST_Reverse(rec.geom);
END IF;
rec.start_node = e2rec.end_node;
e2sign = -1;
ELSIF caseno = 4 THEN -- e1.start = e2.end
IF NOT ST_Equals(ST_EndPoint(rec.geom), ST_EndPoint(e1rec.geom)) THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'caseno=4: LineMerge did not maintain endpoint';
+#endif
rec.geom = ST_Reverse(rec.geom);
END IF;
rec.start_node = e2rec.start_node;
|| ' AND l.layer_id = r.layer_id AND abs(r.element_id) = '
|| e1id
;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'SQL: %', sql;
+#endif
EXECUTE sql;
rec.geom = ST_LineMerge(ST_Collect(e1rec.geom, e2rec.geom));
IF caseno = 1 THEN -- e1.end = e2.start
IF NOT ST_Equals(ST_StartPoint(rec.geom), ST_StartPoint(e1rec.geom)) THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'caseno=1: LineMerge did not maintain startpoint';
+#endif
rec.geom = ST_Reverse(rec.geom);
END IF;
rec.end_node = e2rec.end_node;
e2sign = 1;
ELSIF caseno = 2 THEN -- e1.end = e2.end
IF NOT ST_Equals(ST_StartPoint(rec.geom), ST_StartPoint(e1rec.geom)) THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'caseno=2: LineMerge did not maintain startpoint';
+#endif
rec.geom = ST_Reverse(rec.geom);
END IF;
rec.end_node = e2rec.start_node;
e2sign = -1;
ELSIF caseno = 3 THEN -- e1.start = e2.start
IF NOT ST_Equals(ST_EndPoint(rec.geom), ST_EndPoint(e1rec.geom)) THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'caseno=4: LineMerge did not maintain endpoint';
+#endif
rec.geom = ST_Reverse(rec.geom);
END IF;
rec.start_node = e2rec.end_node;
e2sign = -1;
ELSIF caseno = 4 THEN -- e1.start = e2.end
IF NOT ST_Equals(ST_EndPoint(rec.geom), ST_EndPoint(e1rec.geom)) THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'caseno=4: LineMerge did not maintain endpoint';
+#endif
rec.geom = ST_Reverse(rec.geom);
END IF;
rec.start_node = e2rec.start_node;
|| 'WHERE l.level = 0 AND l.feature_type = 2 '
|| ' AND l.topology_id = ' || topoid
|| ' AND abs(r.element_id) = ' || e1id ;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Checking TopoGeometry definitions: %', sql;
+#endif
FOR rec IN EXECUTE sql LOOP
RAISE EXCEPTION 'TopoGeom % in layer % (%.%.%) cannot be represented dropping edge %',
rec.topogeo_id, rec.layer_id,
|| abs(elink)
|| ' WHERE next_left_edge < 0 AND abs(next_left_edge) = '
|| e1id;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'next_left_edge update: %', sql;
+#endif
EXECUTE sql;
-- If the edge being removed links to self,
|| abs(elink)
|| ' WHERE next_left_edge > 0 AND abs(next_left_edge) = '
|| e1id;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'next_left_edge update: %', sql;
+#endif
EXECUTE sql;
-- }
|| abs(elink)
|| ' WHERE next_right_edge < 0 AND abs(next_right_edge) = '
|| e1id;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'next_right_edge update: %', sql;
+#endif
EXECUTE sql;
-- If the edge being removed links to self,
|| abs(elink)
|| ' WHERE next_right_edge > 0 AND abs(next_right_edge) = '
|| e1id;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'next_right_edge update: %', sql;
+#endif
EXECUTE sql;
-- }
|| 'group by r.topogeo_id, r.layer_id, l.schema_name, l.table_name, '
|| ' l.feature_column ) t WHERE NOT t.elems @> '
|| quote_literal(fidary);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'SQL: %', sql;
+#endif
FOR rec IN EXECUTE sql LOOP
RAISE EXCEPTION 'TopoGeom % in layer % (%.%.%) cannot be represented healing faces % and %',
rec.topogeo_id, rec.layer_id,
|| '.face WHERE face_id IN ('
|| e1rec.left_face || ',' || e1rec.right_face
|| ')';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'SQL: %', sql;
+#endif
EXECUTE sql;
END IF; -- }
|| ' WHERE left_face IN ('
|| e1rec.left_face || ',' || e1rec.right_face
|| ')';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'left_face update: %', sql;
+#endif
EXECUTE sql;
-- Update right_face for all edges still referencing old faces
|| ' WHERE right_face IN ('
|| e1rec.left_face || ',' || e1rec.right_face
|| ')';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'right_face update: %', sql;
+#endif
EXECUTE sql;
-- Update containing_face for all nodes still referencing old faces
|| ' WHERE containing_face IN ('
|| e1rec.left_face || ',' || e1rec.right_face
|| ')';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Isolated nodes update: %', sql;
+#endif
EXECUTE sql;
-- NOT IN THE SPECS:
|| ' AND l.topology_id = ' || topoid
|| ' AND l.layer_id = r.layer_id AND abs(r.element_id) = '
|| e1rec.left_face;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'SQL: %', sql;
+#endif
EXECUTE sql;
sql := 'UPDATE ' || quote_ident(toponame)
|| '.relation r '
|| ' AND l.topology_id = ' || topoid
|| ' AND l.layer_id = r.layer_id AND r.element_id = '
|| e1rec.right_face;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'SQL: %', sql;
+#endif
EXECUTE sql;
END IF; -- } two faces healed...
-- Delete the edge
sql := 'DELETE FROM ' || quote_ident(toponame)
|| '.edge_data WHERE edge_id = ' || e1id;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Edge deletion: %', sql;
+#endif
EXECUTE sql;
-- Check if any of the edge nodes remains isolated,
|| e1rec.end_node || ') AND NOT EXISTS (SELECT edge_id FROM '
|| quote_ident(toponame)
|| '.edge_data WHERE start_node = n.node_id OR end_node = n.node_id)';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Checking for nodes left isolated: %', sql;
+#endif
EXECUTE sql;
IF e1rec.right_face != e1rec.left_face THEN -- {
IF e1rec.left_face != 0 THEN
sql := 'DELETE FROM ' || quote_ident(toponame)
|| '.face WHERE face_id = ' || e1rec.left_face;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Left face deletion: %', sql;
+#endif
EXECUTE sql;
END IF;
THEN
sql := 'DELETE FROM ' || quote_ident(toponame)
|| '.face WHERE face_id = ' || e1rec.right_face;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Right face deletion: %', sql;
+#endif
EXECUTE sql;
END IF;
|| 'WHERE l.level = 0 AND l.feature_type = 2 '
|| ' AND l.topology_id = ' || topoid
|| ' AND abs(r.element_id) = ' || e1id ;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Checking TopoGeometry definitions: %', sql;
+#endif
FOR rec IN EXECUTE sql LOOP
RAISE EXCEPTION 'TopoGeom % in layer % (%.%.%) cannot be represented dropping edge %',
rec.topogeo_id, rec.layer_id,
|| abs(elink)
|| ' WHERE next_left_edge < 0 AND abs(next_left_edge) = '
|| e1id;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'next_left_edge update: %', sql;
+#endif
EXECUTE sql;
-- If the edge being removed links to self,
|| abs(elink)
|| ' WHERE next_left_edge > 0 AND abs(next_left_edge) = '
|| e1id;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'next_left_edge update: %', sql;
+#endif
EXECUTE sql;
-- }
|| abs(elink)
|| ' WHERE next_right_edge < 0 AND abs(next_right_edge) = '
|| e1id;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'next_right_edge update: %', sql;
+#endif
EXECUTE sql;
-- If the edge being removed links to self,
|| abs(elink)
|| ' WHERE next_right_edge > 0 AND abs(next_right_edge) = '
|| e1id;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'next_right_edge update: %', sql;
+#endif
EXECUTE sql;
-- }
|| 'group by r.topogeo_id, r.layer_id, l.schema_name, l.table_name, '
|| ' l.feature_column ) t WHERE NOT t.elems @> '
|| quote_literal(fidary);
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'SQL: %', sql;
+#endif
FOR rec IN EXECUTE sql LOOP
RAISE EXCEPTION 'TopoGeom % in layer % (%.%.%) cannot be represented healing faces % and %',
rec.topogeo_id, rec.layer_id,
|| '.face WHERE face_id IN ('
|| e1rec.left_face || ',' || e1rec.right_face
|| ') ) WHERE face_id = ' || floodfaceid ;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'SQL: %', sql;
+#endif
EXECUTE sql;
END IF; -- }
|| ' WHERE left_face IN ('
|| e1rec.left_face || ',' || e1rec.right_face
|| ')';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'left_face update: %', sql;
+#endif
EXECUTE sql;
-- Update right_face for all edges still referencing old faces
|| ' WHERE right_face IN ('
|| e1rec.left_face || ',' || e1rec.right_face
|| ')';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'right_face update: %', sql;
+#endif
EXECUTE sql;
-- Update containing_face for all nodes still referencing old faces
|| ' WHERE containing_face IN ('
|| e1rec.left_face || ',' || e1rec.right_face
|| ')';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Isolated nodes update: %', sql;
+#endif
EXECUTE sql;
-- NOT IN THE SPECS:
|| e1rec.left_face || ',' || e1rec.right_face
|| ') AND abs(r.element_id) != '
|| floodfaceid; -- could be optimized..
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'SQL: %', sql;
+#endif
EXECUTE sql;
END IF; -- } two faces healed...
-- Delete the edge
sql := 'DELETE FROM ' || quote_ident(toponame)
|| '.edge_data WHERE edge_id = ' || e1id;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Edge deletion: %', sql;
+#endif
EXECUTE sql;
-- Check if any of the edge nodes remains isolated,
|| e1rec.end_node || ') AND NOT EXISTS (SELECT edge_id FROM '
|| quote_ident(toponame)
|| '.edge_data WHERE start_node = n.node_id OR end_node = n.node_id)';
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Checking for nodes left isolated: %', sql;
+#endif
EXECUTE sql;
IF e1rec.right_face != e1rec.left_face THEN -- {
THEN
sql := 'DELETE FROM ' || quote_ident(toponame)
|| '.face WHERE face_id = ' || e1rec.left_face;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Left face deletion: %', sql;
+#endif
EXECUTE sql;
END IF;
THEN
sql := 'DELETE FROM ' || quote_ident(toponame)
|| '.face WHERE face_id = ' || e1rec.right_face;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Right face deletion: %', sql;
+#endif
EXECUTE sql;
END IF;
|| ')'
LOOP
IF rec.containing_face IS NOT NULL THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'containing_face for node %:%',
rec.node_id, rec.containing_face;
+#endif
IF newedge.left_face IS NULL THEN
newedge.left_face := rec.containing_face;
newedge.right_face := rec.containing_face;
-- Find links on start node -- {
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'My start-segment azimuth: %', span.myaz;
+#endif
sql :=
'SELECT edge_id, -1 AS end_node, start_node, left_face, right_face, '
rec.edge_id;
END IF;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Edge % - az % (%) - fl:% fr:%',
rec.edge_id, az, az - span.myaz, rec.left_face, rec.right_face;
+#endif
az = az - span.myaz;
IF az < 0 THEN
END LOOP; -- incident edges }
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'span ROW_COUNT: %', i;
+#endif
IF newedge.isclosed THEN
IF i < 2 THEN span.was_isolated = true; END IF;
ELSE
newedge.prev_left_edge := -span.nextCCW;
END IF;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'edge:%', newedge.edge_id;
+#endif
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' left:%, next:%, prev:%',
newedge.left_face, newedge.next_left_edge, newedge.prev_left_edge;
+#endif
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' right:%, next:%, prev:%',
newedge.right_face, newedge.next_right_edge, newedge.prev_right_edge;
+#endif
-- } start_node analysis
-- Find links on end_node {
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'My end-segment azimuth: %', epan.myaz;
+#endif
sql :=
'SELECT edge_id, -1 as end_node, start_node, left_face, right_face, '
END IF;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Edge % - az % (%)', rec.edge_id, az, az - epan.myaz;
+#endif
az := az - epan.myaz;
IF az < 0 THEN
END LOOP; -- incident edges }
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'epan ROW_COUNT: %', i;
+#endif
IF newedge.isclosed THEN
IF i < 2 THEN epan.was_isolated = true; END IF;
ELSE
-- } end_node analysis
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'edge:%', newedge.edge_id;
+#endif
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' left:%, next:%, prev:%',
newedge.left_face, newedge.next_left_edge, newedge.prev_left_edge;
+#endif
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' right:%, next:%, prev:%',
newedge.right_face, newedge.next_right_edge, newedge.prev_right_edge;
+#endif
----------------------------------------------------------------------
--
FROM paths p INNER JOIN faces f ON (p.path = f.path)
ORDER BY p.right_side DESC
LOOP -- {
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Adding % face', rec.side;
+#endif
SELECT topology.AddFace(atopology, rec.geom, true) INTO newface;
newfaces := array_append(newfaces, newface);
END LOOP; --}
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Added faces: %', newfaces;
+#endif
IF array_upper(newfaces, 1) > 2 THEN
-- Sanity check..
--RAISE DEBUG 'SQL: %', sql;
FOR rec IN EXECUTE sql
LOOP
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'TopoGeometry % in layer % contained the face being split (%) - updating to contain both new faces %', rec.topogeo_id, rec.layer_id, newedge.left_face, newfaces;
+#endif
-- Add reference to the other face
sql := 'INSERT INTO ' || quote_ident(atopology)
|| ')'
LOOP
IF rec.containing_face IS NOT NULL THEN
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'containing_face for node %:%',
rec.node_id, rec.containing_face;
+#endif
IF newedge.left_face IS NULL THEN
newedge.left_face := rec.containing_face;
newedge.right_face := rec.containing_face;
-- Find links on start node -- {
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'My start-segment azimuth: %', span.myaz;
+#endif
sql :=
'SELECT edge_id, -1 AS end_node, start_node, left_face, right_face, '
rec.edge_id;
END IF;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Edge % - az % (%) - fl:% fr:%',
rec.edge_id, az, az - span.myaz, rec.left_face, rec.right_face;
+#endif
az = az - span.myaz;
IF az < 0 THEN
END LOOP; -- incident edges }
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'span ROW_COUNT: %', i;
+#endif
IF newedge.isclosed THEN
IF i < 2 THEN span.was_isolated = true; END IF;
ELSE
newedge.prev_left_edge := -span.nextCCW;
END IF;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'edge:%', newedge.edge_id;
+#endif
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' left:%, next:%, prev:%',
newedge.left_face, newedge.next_left_edge, newedge.prev_left_edge;
+#endif
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' right:%, next:%, prev:%',
newedge.right_face, newedge.next_right_edge, newedge.prev_right_edge;
+#endif
-- } start_node analysis
-- Find links on end_node {
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'My end-segment azimuth: %', epan.myaz;
+#endif
sql :=
'SELECT edge_id, -1 as end_node, start_node, left_face, right_face, '
END IF;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Edge % - az % (%)', rec.edge_id, az, az - epan.myaz;
+#endif
az := az - epan.myaz;
IF az < 0 THEN
END LOOP; -- incident edges }
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'epan ROW_COUNT: %', i;
+#endif
IF newedge.isclosed THEN
IF i < 2 THEN epan.was_isolated = true; END IF;
ELSE
-- } end_node analysis
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'edge:%', newedge.edge_id;
+#endif
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' left:%, next:%, prev:%',
newedge.left_face, newedge.next_left_edge, newedge.prev_left_edge;
+#endif
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG ' right:%, next:%, prev:%',
newedge.right_face, newedge.next_right_edge, newedge.prev_right_edge;
+#endif
----------------------------------------------------------------------
--
--
IF newedge.left_face != 0 THEN -- {
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Checking face %', ST_AsText(rec.geom);
+#endif
-- Skip this if our edge is on the right side
IF ST_IsEmpty(ST_GeometryN(
END IF; -- }
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Adding % face', ST_AsText(rec.geom);
+#endif
SELECT topology.AddFace(atopology, rec.geom, true) INTO newface;
newfaces := array_append(newfaces, newface);
END LOOP; --}
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Added face: %', newface;
+#endif
IF newedge.left_face != 0 THEN -- {
--RAISE DEBUG 'SQL: %', sql;
FOR rec IN EXECUTE sql
LOOP
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'TopoGeometry % in layer % contained the face being split (%) - updating to contain also new face %', rec.topogeo_id, rec.layer_id, newedge.left_face, newface;
+#endif
-- Add reference to the other face
sql := 'INSERT INTO ' || quote_ident(atopology)
END; -- }
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Noding input linework';
+#endif
--
-- Node input linework with itself
WHERE ST_Dimension(geom) = 2
) as linework INTO STRICT nodededges;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Computed % noded edges', ST_NumGeometries(nodededges);
+#endif
--
-- Linemerge the resulting edges, to reduce the working set
--
SELECT ST_LineMerge(nodededges) INTO STRICT nodededges;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Merged edges: %', ST_NumGeometries(nodededges);
+#endif
--
WHERE ST_Dimension(geom) = 1
) as nodes INTO STRICT points;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Collected % input points', ST_NumGeometries(points);
+#endif
--
-- Further split edges by points
END LOOP;
SELECT ST_UnaryUnion(nodededges) INTO STRICT nodededges;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Noded edges became % after point-split',
ST_NumGeometries(nodededges);
+#endif
--
-- Collect all nodes (from points and noded linework endpoints)
SELECT ST_EndPoint(geom) FROM edges
) as endpoints INTO points;
+#ifdef POSTGIS_TOPOLOGY_DEBUG
RAISE DEBUG 'Total nodes count: %', ST_NumGeometries(points);
+#endif
--
-- Add all nodes as isolated so that