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
_______________________________________________
Iscriviti all'associazione GFOSS.it: http://www.gfoss.it/drupal/iscrizione
[email protected]
http://lists.faunalia.it/cgi-bin/mailman/listinfo/gfoss
Questa e' una lista di discussione pubblica aperta a tutti.
I messaggi di questa lista non rispecchiano necessariamente
le posizioni dell'Associazione GFOSS.it.

Rispondere a