<refnamediv>
<refname>AddFace</refname>
- <refpurpose>Adds a polygon to the faces table in the specified topology schema and returns the faceid of new face.
+ <refpurpose>Register a polygon as a topology face in the specified topology schema and returns the faceid of new face.
If face already exists the id of the existing face is returned. Edges of the polygon must already exist otherwise an error is thrown.</refpurpose>
</refnamediv>
<refsection>
<title>Description</title>
- <para>Add a face primitive to a topology and get it's identifier. For a newly added face, its edges will be appropriately linked (marked as left-face or right-face).</para>
+ <para>
+Registers a face primitive to a topology and get it's identifier.
+For a newly added face, the edges forming its boundaries and the ones
+contained in the face will be updated to have correct values in the
+left_face and right_face fields.
+Isolated nodes contained in the face will also be updated to have a correct
+containing_face field value.
+ </para>
<para>The target topology is assumed to be valid (containing no self-intersecting edges). An exception is raised if: The polygon boundary is not fully defined by existing edges or the polygon overlaps an existing face.</para>
<note><para>If the <varname>apolygon</varname> geometry already exists as a face the face id of the existing face is returned.</para></note>
<note><para>The <varname>apolygon</varname> geometry must have the same <varname>srid</varname> as defined for the topology otherwise an invalid spatial reference sys error will be thrown.</para></note>
END IF;
END IF;
-
p3 = ST_StartPoint(bounds);
IF ST_DWithin(edgeseg, p3, 0) THEN
-- Edge segment covers ring endpoint, See bug #874
END IF;
END IF;
--- EXECUTE 'SELECT ST_Collect(geom) FROM'
--- || quote_ident(atopology)
--- || '.edge_data '
--- || ' WHERE edge_id = ANY('
--- || quote_literal(array_append(left_edges, right_edges))
--- || ') ';
-
- --
- -- TODO:
- -- Check that NO edge is contained in the face ?
- --
- RAISE WARNING 'Not checking if face contains any edge';
-
IF faceid IS NOT NULL AND faceid != 0 THEN
RAISE DEBUG 'Face already known as %', faceid;
RETURN faceid;
|| ') ';
END IF;
+
+ --
+ -- Set left_face/right_face of any contained edge
+ --
+ EXECUTE 'UPDATE '
+ || quote_ident(atopology)
+ || '.edge_data SET right_face = '
+ || quote_literal(faceid)
+ || ', left_face = '
+ || quote_literal(faceid)
+ || ' WHERE ST_Contains('
+ || quote_literal(apoly::text)
+ || ', geom)';
+
+ --
+ -- Set containing_face of any contained node
+ --
+ EXECUTE 'UPDATE '
+ || quote_ident(atopology)
+ || '.node SET containing_face = '
+ || quote_literal(faceid)
+ || ' WHERE containing_face IS NOT NULL AND ST_Contains('
+ || quote_literal(apoly::text)
+ || ', geom)';
+
--
-- TODO:
-- Set next_left_face and next_right_face !
-- These are required by the model, but not really used
-- by this implementation...
+ -- NOTE: should probably be done when adding edges rather than
+ -- when registering faces
--
RAISE WARNING 'Not updating next_{left,right}_face fields of face boundary edges';
-set client_min_messages to WARNING;
+set client_min_messages to ERROR;
-- Test with zero tolerance
-- Add one edge only incident on a vertex
SELECT 'e5', topology.addEdge('tt', 'LINESTRING(0 0, 0 -10)');
--- Add 3 more edges closing a squre to the right,
+-- Add 3 more edges closing a square to the right,
-- all edges with same direction
SELECT 'e6', topology.addEdge('tt', 'LINESTRING(10 10, 20 10)');
SELECT edge_id, left_face, right_face from t3.edge ORDER by edge_id;
SELECT topology.DropTopology('t3');
+
+--
+-- Test proper updating of left/right face for contained edges
+-- and nodes
+--
+SELECT topology.CreateTopology('t4') > 0;
+
+SELECT 'N' || topology.addNode('t4', 'POINT(2 6)');
+UPDATE t4.node set containing_face = 0 WHERE node_id = 1;
+
+SELECT 'E' || topology.addEdge('t4', 'LINESTRING(0 0,10 0)');
+SELECT 'E' || topology.addEdge('t4', 'LINESTRING(10 0,10 10)');
+SELECT 'E' || topology.addEdge('t4', 'LINESTRING(10 10,0 10)');
+SELECT 'E' || topology.addEdge('t4', 'LINESTRING(0 0,0 10)');
+SELECT 'E' || topology.addEdge('t4', 'LINESTRING(0 0,5 5)');
+SELECT 'E' || topology.addEdge('t4', 'LINESTRING(5 5,6 5)');
+SELECT 'E' || topology.addEdge('t4', 'LINESTRING(0 10,8 8,10 0)');
+
+select 'F' || topology.addface('t4','POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))');
+
+-- Check edges and nodes
+SELECT 'E'||edge_id, left_face, right_face from t4.edge ORDER by edge_id;
+SELECT 'N'||node_id, containing_face from t4.node ORDER by node_id;
+
+SELECT topology.DropTopology('t4');
e6|6
e7|7
e8|8
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
f1|1
-WARNING: Not checking if face contains any edge
f1*|1
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
f2|2
0|
1|BOX(0 0,10 10)
MiX-e2|2
MiX-e3|3
MiX-e4|4
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
MiX-f1|1
Topology 'Ul' dropped
t
t2.e9|9
t2.e10|10
t2.e11|11
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
t2.f1|1
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
t2.f2|2
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
t2.f3|3
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
t2.f4|4
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
t2.f5|5
ERROR: Polygon boundary is not fully defined by existing edges at or near point POINT(12 5)
0|
t3.e1|1
t3.e2|2
t3.e3|3
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
t3.f1|1
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
t3.f2|2
0|
1|BOX(0 0,10 10)
2|1|2
3|0|1
Topology 't3' dropped
+t
+N1
+E1
+E2
+E3
+E4
+E5
+E6
+E7
+F1
+E1|1|0
+E2|1|0
+E3|1|0
+E4|0|1
+E5|1|1
+E6|1|1
+E7|1|1
+N1|1
+N2|
+N3|
+N4|
+N5|
+N6|
+N7|
+Topology 't4' dropped
-set client_min_messages to WARNING;
+set client_min_messages to ERROR;
SELECT topology.CreateTopology('schema_topo') > 0;
18
19
20
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
1
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
2
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
3
-WARNING: Not checking if face contains any edge
-WARNING: Not updating next_{left,right}_face fields of face boundary edges
4
4
4