set client_min_messages to ERROR;

-- Test with zero tolerance

SELECT topology.CreateTopology('tt') > 0;

-- Register a face in absence of edges (exception expected)
SELECT 'f*',  topology.addFace('tt', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))');

-- Create 4 edges

SELECT 'e1',  topology.addEdge('tt', 'LINESTRING(0 0, 10 0)');
SELECT 'e2',  topology.addEdge('tt', 'LINESTRING(10 0, 10 10)');
SELECT 'e3',  topology.addEdge('tt', 'LINESTRING(0 10, 10 10)');
SELECT 'e4',  topology.addEdge('tt', 'LINESTRING(0 0, 0 10)');

-- Add one edge only incident on a vertex
SELECT 'e5',  topology.addEdge('tt', 'LINESTRING(0 0, 0 -10)');

-- 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 'e7',  topology.addEdge('tt', 'LINESTRING(20 10, 20 0)');
SELECT 'e8',  topology.addEdge('tt', 'LINESTRING(20 0, 10 0)');

-- Register a face with no holes
SELECT 'f1',  topology.addFace('tt', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))');

-- Register the _same_ face  again
SELECT 'f1*',  topology.addFace('tt', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))');

-- Register a face with no holes matching all edges in the same direction
SELECT 'f2',  topology.addFace('tt', 'POLYGON((10 10, 20 10, 20 0, 10 0, 10 10))');

-- Check added faces
SELECT face_id, Box2d(mbr) from tt.face ORDER by face_id;

-- Check linking
SELECT edge_id, left_face, right_face from tt.edge ORDER by edge_id;

-- Force re-registration of an existing face
SELECT 'f1-force',  topology.addFace('tt', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', true);

-- re-check added faces and linking
SELECT face_id, Box2d(mbr) from tt.face ORDER by face_id;
SELECT edge_id, left_face, right_face from tt.edge ORDER by edge_id;

SELECT topology.DropTopology('tt');

-- Test topology with MixedCase
SELECT topology.CreateTopology('Ul') > 0;
SELECT 'MiX-e1',  topology.addEdge('Ul', 'LINESTRING(0 0, 10 0)');
SELECT 'MiX-e2',  topology.addEdge('Ul', 'LINESTRING(10 0, 10 10)');
SELECT 'MiX-e3',  topology.addEdge('Ul', 'LINESTRING(0 10, 10 10)');
SELECT 'MiX-e4',  topology.addEdge('Ul', 'LINESTRING(0 0, 0 10)');
SELECT 'MiX-f1',  topology.addFace('Ul', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))');
SELECT topology.DropTopology('Ul');

-- Test polygons with holes
SELECT topology.CreateTopology('t2') > 0;

-- Edges forming two squares
SELECT 't2.e1',  topology.addEdge('t2', 'LINESTRING(0 0, 10 0)');
SELECT 't2.e2',  topology.addEdge('t2', 'LINESTRING(10 0, 10 10)');
SELECT 't2.e3',  topology.addEdge('t2', 'LINESTRING(0 10, 10 10)');
SELECT 't2.e4',  topology.addEdge('t2', 'LINESTRING(0 0, 0 10)');
SELECT 't2.e5',  topology.addEdge('t2', 'LINESTRING(10 10, 20 10)');
SELECT 't2.e6',  topology.addEdge('t2', 'LINESTRING(20 10, 20 0)');
SELECT 't2.e7',  topology.addEdge('t2', 'LINESTRING(20 0, 10 0)');

-- Clockwise hole within the square on the left
SELECT 't2.e8',  topology.addEdge('t2', 'LINESTRING(1 1, 1 2, 2 2, 2 1, 1 1)');
-- Counter-clockwise hole within the square on the left
SELECT 't2.e9',  topology.addEdge('t2', 'LINESTRING(3 1,4 1,4 2,3 2,3 1)');

-- Multi-edge hole within the square on the right
SELECT 't2.e10',  topology.addEdge('t2', 'LINESTRING(12 2, 14 2, 14 4)');
SELECT 't2.e11',  topology.addEdge('t2', 'LINESTRING(12 2, 12 4, 14 4)');

-- Register left face with two holes
SELECT 't2.f1',  topology.addFace('t2',
'POLYGON((10 5, 10 10,0 10, 0 0,10 0,10 5),
         (1 1,2 1,2 2,1 2,1 1),
         (3 1,3 2,4 2,4 1,3 1))'
);

-- Register right face with one hole
SELECT 't2.f2',  topology.addFace('t2',
'POLYGON((20 0,10 0,10 10,20 10,20 0),
         (12 2,14 2,14 4,12 4, 12 2))'
);

-- Register left hole in left square
SELECT 't2.f3',  topology.addFace('t2',
'POLYGON((1 1,2 1,2 2,1 2,1 1))'
);

-- Register right hole in left square
SELECT 't2.f4',  topology.addFace('t2',
'POLYGON((3 1,4 1,4 2,3 2,3 1))'
);

-- Register hole in right face
SELECT 't2.f5',  topology.addFace('t2',
'POLYGON((12 2,12 4,14 4,14 2,12 2))'
);

-- Attempt to register a not-fully-defined face
SELECT topology.addFace('t2',
'POLYGON((12 2,12 5,14 5,14 2,12 2))'
);

-- Check added faces
SELECT face_id, Box2d(mbr) from t2.face ORDER by face_id;

-- Check linking
SELECT edge_id, left_face, right_face from t2.edge ORDER by edge_id;

SELECT topology.DropTopology('t2');

--
-- Test edge touching face ring on both endpoints but not covered
-- (E1 with F1)
--
--
--   N2 +-------.
--      |\  F1  |
--   E1 | \     | E3
--      |F2\    |
--      |  /    |
--      | /E2   |
--      |/      |
--   N1 +-------'
--
SELECT topology.CreateTopology('t3') > 0;

SELECT 't3.e1',  topology.addEdge('t3', 'LINESTRING(0 0, 0 10)');
SELECT 't3.e2',  topology.addEdge('t3', 'LINESTRING(0 10, 5 5, 0 0)');
SELECT 't3.e3',  topology.addEdge('t3', 'LINESTRING(0 10, 10 10, 10 0, 0 0)');

-- Register F1
SELECT 't3.f1',  topology.addFace('t3',
'POLYGON((5 5, 0 10, 10 10, 10 0, 0 0, 5 5))');

-- Register F2
SELECT 't3.f2',  topology.addFace('t3', 'POLYGON((0 0, 5 5, 0 10, 0 0))');

-- Check added faces
SELECT face_id, Box2d(mbr) from t3.face ORDER by face_id;

-- Check linking
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');

--
-- Test narrow face. See ticket #1302.
-- {
--
SELECT '#1302', topology.CreateTopology('tt') > 0;

SELECT '#1302', 'E' || topology.addEdge('tt', '01020000000300000000917E9BA468294100917E9B8AEA2841C976BE1FA4682941C976BE9F8AEA2841B39ABE1FA46829415ACCC29F8AEA2841');
SELECT '#1302', 'E' || topology.addEdge('tt', '010200000003000000B39ABE1FA46829415ACCC29F8AEA284137894120A4682941C976BE9F8AEA284100917E9BA468294100917E9B8AEA2841');
SELECT '#1302', 'F' || topology.addFace('tt', '0103000000010000000500000000917E9BA468294100917E9B8AEA2841C976BE1FA4682941C976BE9F8AEA2841B39ABE1FA46829415ACCC29F8AEA284137894120A4682941C976BE9F8AEA284100917E9BA468294100917E9B8AEA2841');

SELECT '#1302', 'E' || edge_id, 'L' || left_face, 'R' || right_face FROM tt.edge_data ORDER BY edge_id;

SELECT '#1302', topology.DropTopology('tt');
-- }

--
-- Test face ring with endpoint matching edge endpoint
-- and tricky numbers (see #1383)
-- {
--
SELECT '#1383', CreateTopology('tt') > 0;

SELECT '#1383', 'E' || addEdge('tt', 'LINESTRING(-0.1 -10, -0.2 0)');
SELECT '#1383', 'E' || addEdge('tt', 'LINESTRING(-0.2 0, -1e-8 0)');
SELECT '#1383', 'E' || addEdge('tt', 'LINESTRING(-1e-8 0, 1 0, -0.1 -10)');

SELECT '#1383', 'F' || addFace('tt', 'POLYGON((-1e-8 0, 1 0, -0.1 -10, -0.2 0, -0.2 0, -1e-8 0))');

SELECT '#1383', 'E' || edge_id, 'L' || left_face, 'R' || right_face FROM tt.edge_data ORDER BY edge_id;

SELECT '#1383', DropTopology('tt');
-- }
