Rimozione del segmento più lungo di linea e segmenti che si ricongiungono
Sto cercando di rimuovere il segmento che ha la lunghezza più lunga da una linea e unire i due gruppi di segmenti che rimangono dal segmento più corto tra di loro.
È stato facile, usare ST_Difference
( ST_Split
funziona anche) tra la stringa di linea e il suo segmento più lungo, e poi ho usato ST_ShorestLine
per unire entrambi i gruppi di segmenti risultanti.

Ma ho trovato il problema più grande quando il segmento principale attraversa molti segmenti della stringa di linea. il risultato ST_Difference
o ST_Split
restituisce più di due gruppi di segmenti (poiché vengono prese in considerazione anche le intersezioni di tipo punto).
Ciò rende difficile la successiva unione dei gruppi.

Quello che potrebbe aiutarmi, penso, è che ST_Difference
or ST_Split
(o un'altra funzione, IDK) prende in considerazione solo le intersezioni del tipo di stringa di linea ma non riesco a creare la query corretta.
O forse esiste un modo più semplice per rimuovere il segmento più lungo e far ricongiungere le due linee adiacenti?
Qualche idea?
Risposte
Ecco la prima parte di una soluzione: SQL per trovare le parti della linea su entrambi i lati del segmento più lungo.
WITH data(id, geom) AS (VALUES
( 1, 'LINESTRING (0 0, 1 1, 2.1 2, 3 3, 4 4)'::geometry )
),
longest AS (SELECT i AS iLongest, geom,
ST_Distance( ST_PointN( data.geom, s.i ),
ST_PointN( data.geom, s.i+1 ) ) AS dist
FROM data JOIN LATERAL (
SELECT i FROM generate_series(1, ST_NumPoints( data.geom )-1) AS gs(i)
) AS s(i) ON true
ORDER BY dist LIMIT 1
)
SELECT
CASE WHEN iLongest > 2 THEN ST_AsText( ST_MakeLine(
(ARRAY( SELECT (ST_DumpPoints(geom)).geom FROM longest))[1 : iLongest - 1]
)) ELSE null END AS line1,
CASE WHEN iLongest < ST_NumPoints(geom) - 1 THEN ST_AsText( ST_MakeLine(
(ARRAY( SELECT (ST_DumpPoints(geom)).geom FROM longest))[iLongest + 1: ST_NumPoints(geom)]
)) ELSE null END AS line2
FROM longest;
Modelli utili in questo codice:
JOIN LATERAL generate_series
per estrarre i segmenti di linea- sezionamento dell'array per estrarre una sottolinea contenente una sezione della riga originale
Poiché la strategia per unire le (potenziali) due linee non è chiara, questa non è implementata.
Sarebbe più chiaro se parti di questo SQL fossero fornite da funzioni (ad esempio una ST_LineSlice
funzione e una ST_DumpSegments
funzione - che forse un giorno faranno parte di PostGIS).
Pubblico la mia soluzione originale e divertente su Postgre / PostGIS SQL per coloro che incontreranno una situazione in cui le linee hanno autointersezioni,
Quindi, la situazione iniziale è mostrata nella figura, la tabella iniziale denominata line (LineString EPSG: 4326):

Crea una nuova funzione originale e avvia una richiesta per eseguirla:
CREATE OR REPLACE FUNCTION ST_SelfIntersectingLineRectifier(
geom GEOMETRY
)
RETURNS GEOMETRY AS
$BODY$
WITH
tbla AS (SELECT (ST_Dump(geom)).geom geom),
tblb AS (SELECT ST_MakeLine(pt1, pt2) geom FROM (SELECT ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) pt1,
ST_PointN(geom, generate_series(2, ST_NPoints(geom))) pt2 FROM tbla) AS geom),
tblc AS (SELECT DISTINCT ST_Union(a.geom) geom FROM tblb a, tblb b WHERE ST_Length(a.geom)<ST_Length(b.geom)),
tbld AS (SELECT DISTINCT (ST_Dump(ST_Difference(a.geom, b.geom))).geom geom FROM tblb a JOIN tblc b ON ST_Intersects(a.geom, b.geom)),
tble AS (SELECT ST_MakeLine(ST_LineSubstring(geom, 0.1, 0.9)) geom FROM tbld),
tblf AS (SELECT (a.geom) geom FROM tblb a JOIN tble b ON ST_Intersects(a.geom, b.geom)),
tblg AS (SELECT (a.geom) geom FROM tblf a WHERE NOT EXISTS (SELECT 1 FROM tbld b WHERE ST_Intersects(a.geom, ST_StartPoint(b.geom)))),
tblh AS (SELECT (a.geom) geom FROM tblb a JOIN tbld b ON ST_Touches(a.geom, b.geom) LIMIT 1),
tbli AS (SELECT ST_MakeLine(ST_EndPoint(a.geom), ST_EndPoint(b.geom)) geom FROM tblg a, tblh b)
SELECT ST_Union(geom) geom FROM (SELECT * FROM tblc UNION SELECT * FROM tbli) foo
$BODY$
LANGUAGE SQL
SELECT ST_SelfIntersectingLineRectifier(geom) geom FROM line
Puoi vedere il risultato nella foto qui sotto:

Lo script si chiama ST_SelfIntersectingLineRectifier
In realtà è davvero difficile risolvere questo problema analiticamente, ma è abbastanza facile risolverlo geometricamente ...
Ricorda, è sempre importante definire un punto o una linea nodale che ti aiuterà a trovare una soluzione ...
"All'inizio corro al tuo incontro, ma poi mi costringi a scappare da te ..." 🙂
Tradotto con www.DeepL.com/Translator (versione gratuita)