[Gfoss] POSTGIS e i dislivelli
Alessandro Pasotti
ale.pas a tiscali.it
Lun 5 Ott 2009 13:00:00 CEST
Il venerdì 02 ottobre 2009, Antonio Falciano ha scritto:
> Alessandro Pasotti ha scritto:
> > Il venerdì 02 ottobre 2009, Antonio Falciano ha scritto:
> >> Alessandro Pasotti ha scritto:
> >>> Il venerdì 02 ottobre 2009, Antonio Falciano ha scritto:
> >>>> Alessandro Pasotti ha scritto:
> >>>>> Ciao (scusate il cross-post errato in lista soci),
> >>>>>
> >>>>> devo calcolare i dislivelli in discesa e in salita di una polilinea
> >>>>> 3D, sapete se (e come) si può fare con postgis?
> >>>>
> >>>> SELECT ST_ZMAX(the_geom) as z_max, ST_ZMIN(the_geom) as z_min,
> >>>> (ST_ZMAX(the_geom) - ST_ZMIN(the_geom)) as delta_z FROM streets;
> >>>>
> >>>> se ti interessa il dislivello esistente in assoluto, mentre per quello
> >>>> relativo occorre usare anche ST_PointN.
> >>>>
> >>>> ciao
> >>>> Antonio
> >>>
> >>> Grazie!
> >>>
> >>> se ho capito bene le prime due funzioni restituiscono quote minime e
> >>> massime,
> >>
> >> ok
> >>
> >>> se voglio sapere i dislivelli relativi devo quindi scrivere una
> >>> funzione che iterando su tutti i punti della polilinea, sommi tutti i
> >>> dislivelli in un verso (convenzionalmente salita) e in quello opposto
> >>> (discesa) ?
> >>
> >> No, perche' per via dei segni perderesti per strada buona parte
> >> dell'informazione. Cosi' facendo calcolaresti il dislivello tra il punto
> >> iniziale e finale e, a tal fine, basterebbe semplicemente recuperare la
> >> z di questi due agendo con ST_PointN (v. 2° es. in
> >> http://postgis.refractions.net/docs/ST_PointN.html
> >> Purtroppo cosi' si perdono tutti i dislivelli intermedi.
> >
> > Ho dato per scontato che userei due variabili, una per accumulare i
> > dislivelli in discesa e l'altra per quelli in salita (pseudo codice):
> >
> > for punto in linea
> > if punto_tmp
> > if punto.z > punto_tmp.z
> > salita += punto.z - punto_tmp.z
> > else
> > discesa += punto_tmp.z - punto.z
> > punto_tmp = punto
> >
> >
> > sbaglio qualcosa?
>
> ok, cosi' va meglio... ma, in ogni caso, mi calcolerei la pendenza,
> poiche' uno stesso dislivello lo puoi avere lungo 1 km opp. dopo soli 5
> m di tracciato, ti pare?
> Un'altra strategia potrebbe essere quella di "esplodere" le polilinee in
> linee, calcolare agevolmente il dislivello e quindi la pendenza di ogni
> singola linea ed, infine, riaggregare il tutto mediando le pendenze.
>
> >> Inoltre, potresti considerare anche la tipologia di tracciato (sterrato,
> >> pavimentato, ecc.) in modo considerare il grado di difficolta' nella sua
> >> percorrenza.
> >
> > Ho anche le variabili del mezzo: a piedi, in bici ecc. ma non so se mi
> > spingerò così avanti.
>
> Altre variabili da tenere conto nella funzione di costo potrebbero
> essere la tortuosita' del tracciato e le condizioni psico-fisiche del
> soggetto che lo percorre, ad es. con o senza grappino! :)
>
> ciao
Grappino a parte, ecco la funzione, in caso serva a qualcuno.
CREATE OR REPLACE FUNCTION dislivelli(line geometry)
RETURNS real[] AS
$BODY$
DECLARE
discesa real;
salita real;
point_iter geometry;
point_tmp geometry;
line_tmp geometry;
num_points integer;
i integer;
BEGIN
discesa := 0.0;
salita := 0.0;
IF (GEOMETRYTYPE(line) = 'MULTILINESTRING') THEN
line_tmp := ST_Force_3D(linemerge(line));
ELSIF (GEOMETRYTYPE(line) = 'LINESTRING') THEN
line_tmp := ST_Force_3D(line);
ELSE
Raise Exception 'Not a linestring or multilenstring!';
END IF;
num_points := ST_NPoints(line_tmp);
--Raise Notice 'Points: %', i;
point_tmp := NULL;
FOR i IN 1..num_points LOOP
point_iter := ST_PointN(line_tmp, i);
--Raise Notice 'Point Iter % : %', i, ST_asEWKT(point_iter);
--Raise Notice 'Point Tmp % : %', i, ST_asEWKT(point_tmp);
IF (NOT point_tmp IS NULL) THEN
IF ST_Z(point_tmp) > ST_Z(point_iter) THEN
discesa := discesa + ST_Z(point_tmp) - ST_Z(point_iter);
--Raise Notice 'Discesa : %' , discesa;
ELSE
salita := salita + ST_Z(point_iter) - ST_Z(point_tmp);
--Raise Notice 'Salita : %' , salita;
END IF;
END IF;
point_tmp := point_iter;
END LOOP;
RETURN ARRAY[salita,discesa];
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE STRICT
COST 100;
COMMENT ON FUNCTION dislivelli(geometry) IS 'Calcola i dislivelli in salita e
in discesa di una polilinea
Test: select dislivelli(st_geomfromewkt(''LINESTRING(1 2 4.0, 2 3 5.8, 3 6
8.09, 2 4 1.0008)''));';
Ciao
--
Alessandro Pasotti
itOpen - "Open Solutions for the Net Age"
w3: www.itopen.it
Linux User# 167502
Maggiori informazioni sulla lista
Gfoss