Commit 5a548dbe authored by Jean-Benoist Leger's avatar Jean-Benoist Leger

Very more efficent method to compute CC

parent 7a1b2d90
...@@ -2,10 +2,8 @@ ...@@ -2,10 +2,8 @@
BEGIN; BEGIN;
-- rv_ways -- rv_ways
DROP TABLE IF EXISTS rv_ways; DROP TABLE IF EXISTS rv_ways;
CREATE TABLE rv_ways (id BIGINT, cc BIGINT, ccprov BIGINT); CREATE TABLE rv_ways (id BIGINT);
ALTER TABLE rv_ways ADD CONSTRAINT pk_rv_ways PRIMARY KEY (id); ALTER TABLE rv_ways ADD CONSTRAINT pk_rv_ways PRIMARY KEY (id);
CREATE INDEX idx_rv_ways_cc ON rv_ways USING btree (cc);
CREATE INDEX idx_rv_ways_ccprov ON rv_ways USING btree (ccprov) WHERE cc IS NULL;
-- rv_nodes -- rv_nodes
DROP TABLE IF EXISTS rv_nodes; DROP TABLE IF EXISTS rv_nodes;
......
DROP FUNCTION IF EXISTS propto();
DROP FUNCTION IF EXISTS propage(); CREATE FUNCTION propto() RETURNS VOID AS $$
CREATE FUNCTION propage() RETURNS VOID AS $$
DECLARE DECLARE
nb BIGINT; nb BIGINT;
k BIGINT; k BIGINT;
BEGIN BEGIN
nb:=1; nb:=1;
k:=1;
WHILE nb<>0 LOOP WHILE nb<>0 LOOP
UPDATE rv_ways
SET
ccprov=k+1
FROM
(
SELECT
w2.id AS id
FROM
rv_ways AS w1
INNER JOIN
rv_way_way AS ww ON w1.id=ww.id1
INNER JOIN
rv_ways AS w2 ON w2.id=ww.id2
WHERE
w1.ccprov=k AND w1.cc IS NULL
AND
w2.ccprov IS NULL AND w2.cc IS NULL
) AS sub
WHERE
rv_ways.id=sub.id;
k:=k+1;
GET DIAGNOSTICS nb = ROW_COUNT;
END LOOP;
END;
$$ LANGUAGE plpgsql;
DROP FUNCTION IF EXISTS etiqueter(); WITH
CREATE FUNCTION etiqueter() RETURNS BIGINT AS $$ mm AS
DECLARE (
n BIGINT; SELECT
ccref BIGINT; DISTINCT ON (wc1.cc_id)
updated BIGINT; wc1.cc_id AS old_cc_id,
count BIGINT; wc2.cc_id AS new_cc_id
BEGIN FROM
ccref:=0; rv_way_cc AS wc1
INNER JOIN
rv_way_way AS ww ON wc1.way_id=ww.id1
INNER JOIN
rv_way_cc AS wc2 ON ww.id2=wc2.way_id
ORDER BY wc1.cc_id,wc2.cc_id
)
UPDATE rv_way_cc
SET
cc_id=sub.new_cc_id
FROM
(
SELECT * FROM mm WHERE NOT old_cc_id=new_cc_id
) AS SUB
WHERE
cc_id=sub.old_cc_id;
SELECT DISTINCT cc FROM rv_ways WHERE NOT cc IS NULL ORDER BY cc DESC LIMIT 1 INTO ccref; GET DIAGNOSTICS nb = ROW_COUNT;
GET DIAGNOSTICS count = ROW_COUNT; RAISE INFO '% ways updated', nb;
ccref:=ccref+1;
IF count=0 THEN
ccref:=0;
END IF;
n:=ccref;
LOOP
UPDATE rv_ways
SET
ccprov=1
FROM
(
SELECT
id
FROM
rv_ways
WHERE
cc IS NULL
LIMIT 1
) AS sub
WHERE rv_ways.id=sub.id;
PERFORM propage();
UPDATE rv_ways SET cc=n, ccprov=NULL WHERE cc IS NULL AND NOT ccprov IS NULL;
GET DIAGNOSTICS updated = ROW_COUNT;
PERFORM id FROM rv_ways WHERE cc IS NULL;
GET DIAGNOSTICS count = ROW_COUNT;
RAISE INFO 'Connected component % with % ways, % ways left', n, updated, count;
n:=n+1;
EXIT WHEN count=0;
END LOOP; END LOOP;
RETURN ccref;
END; END;
$$ LANGUAGE plpgsql; $$ LANGUAGE plpgsql;
-- --
-- modifs -- modifs
DROP FUNCTION IF EXISTS osmosisUpdate(); DROP FUNCTION IF EXISTS updateRV();
CREATE FUNCTION osmosisUpdate() RETURNS VOID AS $$ CREATE FUNCTION updateRV() RETURNS VOID AS $$
DECLARE
ccref BIGINT;
BEGIN BEGIN
-- rv_ways -- rv_ways
-- on note les cc touchées par la modification des ways -- on note les cc touchées par la modification des ways
...@@ -66,86 +64,6 @@ BEGIN ...@@ -66,86 +64,6 @@ BEGIN
) )
); );
-- update de la table des liens du graph dual, deux ways sont liées si elles
-- partagent un noeud
-- on utilise la methode bourinne, on efface le contenu et on le recrée
CREATE TEMP TABLE rv_way_way (id1 BIGINT, id2 BIGINT) ON COMMIT DROP;
INSERT INTO rv_way_way
(
SELECT DISTINCT
w1.id AS id1,
w2.id AS id2
FROM
rv_ways AS w1
INNER JOIN
way_nodes AS wn1 ON wn1.way_id=w1.id
INNER JOIN
way_nodes AS wn2 ON wn2.node_id=wn1.node_id AND wn2.way_id<>wn1.way_id
INNER JOIN
rv_ways AS w2 ON w2.id=wn2.way_id
);
CREATE INDEX idx_rv_ways_id1 ON rv_way_way USING btree (id1);
-- on note les cc touchées, ce sont les cc qui ont été touchés par l'ajout
-- d'un noeud dans un way, donc il faut propager une fois par rv_way_way
-- pour voir toutes les composantes connexes qui auront été réunies
INSERT INTO actions
(
SELECT
'c' AS data_type,
'M' AS action,
sub.id AS id
FROM
(
(
SELECT DISTINCT
rv_ways.cc AS id
FROM
actions AS a1
INNER JOIN
rv_way_way ON a1.id=rv_way_way.id1
INNER JOIN
rv_ways ON rv_way_way.id2=rv_ways.id
WHERE
a1.data_type='W'
AND
NOT rv_ways.cc IS NULL
)
EXCEPT
(
SELECT
id
FROM
actions
WHERE
data_type='c'
)
) AS sub
);
-- maintenant qu'on a toutes les cc touchées par la modification on mets à
-- NULL la cc de tous les ways pour un calcul de composantes connexe
-- ulterieur
UPDATE rv_ways
SET
cc=NULL
FROM
(
SELECT DISTINCT
id
FROM
actions
WHERE
data_type='c'
) AS sub
WHERE
rv_ways.cc=sub.id;
DELETE FROM actions WHERE data_type='c';
-- on labelise les cc qui ont été placés à NULL
SELECT etiqueter() INTO ccref;
-- rv_edges -- rv_edges
-- etape 1 : on effacte tous les edges qui proviennent d'un ways -- etape 1 : on effacte tous les edges qui proviennent d'un ways
DELETE FROM rv_edges DELETE FROM rv_edges
...@@ -256,8 +174,46 @@ BEGIN ...@@ -256,8 +174,46 @@ BEGIN
nodes ON nodes.id=n.id nodes ON nodes.id=n.id
); );
-- etape 4 : on mets à jour les labels de cc à partir de ceux calculés sur -- computation of connected components
-- puis on mets à jour les labels de cc à partir de ceux calculés sur
-- le graph dual -- le graph dual
CREATE TEMP TABLE rv_way_way (id1 BIGINT, id2 BIGINT);
INSERT INTO rv_way_way
(
SELECT DISTINCT
w1.id AS id1,
w2.id AS id2
FROM
rv_ways AS w1
INNER JOIN
way_nodes AS wn1 ON wn1.way_id=w1.id
INNER JOIN
way_nodes AS wn2 ON wn2.node_id=wn1.node_id AND wn2.way_id<>wn1.way_id
INNER JOIN
rv_ways AS w2 ON w2.id=wn2.way_id
);
INSERT INTO rv_way_way
(
SELECT
w.id AS id1,
w.id AS id2
FROM
rv_ways AS w
);
CREATE TEMP TABLE rv_way_cc (way_id BIGINT, cc_id BIGINT);
INSERT INTO rv_way_cc
(
SELECT
w.id AS way_id,
w.id AS cc_id
FROM
rv_ways AS w
);
PERFORM propto();
UPDATE rv_nodes UPDATE rv_nodes
SET SET
cc=sub.cc cc=sub.cc
...@@ -265,15 +221,13 @@ BEGIN ...@@ -265,15 +221,13 @@ BEGIN
( (
SELECT DISTINCT SELECT DISTINCT
wn.node_id AS id, wn.node_id AS id,
w.cc AS cc wc.cc_id AS cc
FROM FROM
rv_ways AS w rv_way_cc AS wc
INNER JOIN INNER JOIN
way_nodes AS wn ON wn.way_id=w.id way_nodes AS wn ON wn.way_id=wc.way_id
INNER JOIN INNER JOIN
rv_nodes ON rv_nodes.id=wn.node_id rv_nodes ON rv_nodes.id=wn.node_id
WHERE
w.cc >= ccref
) AS sub ) AS sub
WHERE WHERE
sub.id=rv_nodes.id; sub.id=rv_nodes.id;
......
--
-- modifs
DROP FUNCTION IF EXISTS osmosisUpdate();
CREATE FUNCTION osmosisUpdate() RETURNS VOID AS $$
BEGIN
PERFORM updateRV();
END;
$$ LANGUAGE plpgsql;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment