Punti random nel poligono soluzione SpatiaLite Help

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Punti random nel poligono soluzione SpatiaLite Help

pigreco
Ciao,
ho creato questo script SQL per sqlite/spatialite con cui genero dei punti
random all'interno del bounding box di un layer poligonale.
Ne genero ad esempio 1000 random, e poi all'interno del suo perimetro ne
ricadono 478.

-- creo una tabella vuota che conterrà i random point
CREATE TABLE point_01
(id INTEGER PRIMARY KEY AUTOINCREMENT,cir_id INTEGER);
-- popolo ID tabella
INSERT INTO point_01
WITH RECURSIVE
  cnt(id) AS ( SELECT 1 UNION ALL SELECT id + 1 FROM cnt LIMIT 1000)
SELECT id,0 FROM cnt;
-- aggiorno tabella con i punti casuali usando bounding box del poligono
SELECT AddGeometryColumn ('point_01','geom',4326,'POINT','XY');
UPDATE point_01 SET
geom = (SELECT makepoint (
CAST ((select (0.5 - RANDOM()/CAST(-9223372036854775808 AS REAL)/
2)*(extent_max_x - extent_min_x) + extent_min_x
FROM "vector_layers_statistics" WHERE id=point_01.id AND table_name =
'poly') AS REAL),
CAST ((select (0.5 - RANDOM()/CAST(-9223372036854775808 AS REAL)/
2)*(extent_max_y - extent_min_y) + extent_min_y
FROM "vector_layers_statistics" WHERE id=point_01.id AND table_name =
'poly') AS REAL), 4326) WHERE id=point_01.id);
SELECT 'Creazione indice spaziale su ', 'point_01','geom',
coalesce(checkspatialindex('point_01','geom'),CreateSpatialIndex('point_01','geom'));

Allego il file Spatialite su cui è possibile eseguire la query di sopra.
https://bit.ly/2HlvAoQ

Vorrei una mano per fare un passo in avanti nella logica dello script. Il
mio goal: dato un poligono, voglio generarne 1000 punti nel suo perimetro.
Quindi potrei:

1. generarne più di 1000, poi conteggiarne (vedi script sotto) quanti ne
ricadono all'interno del perimetro, e
  a. se sono più di 1000, eseguo un SELECT con LIMIT 1000 e ho finito.
  b. se sono meno di 1000, ne genero in aggiunga ai precedenti altri XXX,
faccio il check e
      - se sono più di 1000 torno ad a.;
      - se sono meno di 1000 torno a b..
   
So di soluzioni in QGIS, PostGIS, geo Python, ma vorrei stare nel contesto
spatialite.

C'è qualche suggerimento didattico su come risolvere tutto in una logica SQL
(in sqlite) o la strada preferenziale è fare dialogare spatialite con Python
(o altro) e qualche while loop?


-- associo cir_id ad ogni punto
UPDATE point_01 SET
cir_id = (SELECT pl.cir_id
FROM poly pl, point_01 pt
WHERE id=point_01.id AND pt.rowid IN (SELECT rowid FROM SpatialIndex
                        WHERE f_table_name = 'point_01' AND search_frame = pl.geom)
                  and ST_Intersects (pl.geom, pt.geom) = 1);
-- cancello i punti fuori poligono
DELETE FROM point_01 WHERE CIR_ID IS NULL;
-- conteggio punti
SELECT count(*) FROM point_01;

Grazie

-----
https://pigrecoinfinito.wordpress.com/
--
Sent from: http://gfoss-geographic-free-and-open-source-software-italian-mailing.3056002.n2.nabble.com/
_______________________________________________
[hidden email]
http://lists.gfoss.it/cgi-bin/mailman/listinfo/gfoss
Questa e' una lista di discussione pubblica aperta a tutti.
I messaggi di questa lista non hanno relazione diretta con le posizioni dell'Associazione GFOSS.it.
796 iscritti al 28/12/2017
Reply | Threaded
Open this post in threaded view
|

Re: Punti random nel poligono soluzione SpatiaLite Help

a.furieri
On Wed, 15 May 2019 12:16:48 -0700 (MST), pigreco wrote:
> C'è qualche suggerimento didattico su come risolvere tutto in una
> logica SQL
> (in sqlite) o la strada preferenziale è fare dialogare spatialite con
> Python
> (o altro) e qualche while loop?
>

chiaramente la strada piu' liscia, semplice e veloce e' quella di
scrivere
un banale programmicchio in C, C++, Java, Python o qualsiasi altro
linguaggio
di programmazione che supporti i loops.

SQL e' un linguaggio meraviglioso, ma e' comunque un linguaggio basato
sul
paradigma dichiarativo; tutti gli altri (C, Java etc) sono invece
linguaggi
basati sul paradigma imperativo.
nei linguaggi dichiarativi va specificato quale risultato finale si
intende
ottenere, dopo di che ci pensera' il linguaggio stesso ad identificare
in
modo ottimale tutte le azioni necessarie per arrivare a quel risultato.
tutto l'opposto avviene nei linguaggi imperativi, in cui e' il
programmatore
a dovere specificare minuziosamente tutte le azioni necessarie per
arrivare
al risultato finale.

non e' che un paradigma sia superiore all'altro; sono profondamente
diversi,
e ciascuno di essi e' piu' adatto ad alcuni problemi piuttosto che ad
altri.
e' un po' come avere a disposizione un coltello da cucina ed un'ascia;
se devi
affettare del pane l'ascia sara' decisamente poco pratica, esattamente
come
il coltello da cucina si rivelera' inadeguato per abbattere una
quercia.

venendo allo specifico del tuo problema, lo possiamo sintetizzare in
questo pseudo-algoritmo:

0. inizializzazione: definisci il poligoo ed azzeri il contatore
1. se il contatore ha raggiunto il valore massimo vai al punto 4)
    altrimenti procedi al punto successivo.
2. calcola un punto random all'interno del BBOX del poligono
3. verifica se il  punto cade realmente all'interno della superficie
    del poligono
    3-A) si: inseriscilo nella tavola, incrementa il contatore e torna
         al punto 1)
    3-B) no: torna al punto 1) senza incrementare il contatore
4. fine

questo e' un classico loop, e tutti i linguaggi di programmazione
imperativi sono fatti apposta per rendere semplice l'esecuzione
dei loops.
SQL invece segue tutt'altra logica, ed offre solo la WITH RECURSIVE
per mettere in piedi (in modo abbastanza macchinoso e contorto)
qualcosa che assomiglia ad un loop.
conclusione: quando usare un loop e' assolutamente critico (come
nel tuo caso, visto che non puoi sapere in anticipo se/quanti
punti random cadranno effettivamente dentro al poligono)
pretendere di usare solo SQL puro non e' la scelta ottimale.
e' un po' come cercare di affettare pane e salame con l'ascia;
se usi invece il coltello da cucina fatichi molto meno.

ciao Sandro
_______________________________________________
[hidden email]
http://lists.gfoss.it/cgi-bin/mailman/listinfo/gfoss
Questa e' una lista di discussione pubblica aperta a tutti.
I messaggi di questa lista non hanno relazione diretta con le posizioni dell'Associazione GFOSS.it.
796 iscritti al 28/12/2017
Reply | Threaded
Open this post in threaded view
|

Re: Punti random nel poligono soluzione SpatiaLite Help

pigreco
Grazie mille per la risposta.

Se riesco condividerò lo script.

T.


-----
https://pigrecoinfinito.wordpress.com/
--
Sent from: http://gfoss-geographic-free-and-open-source-software-italian-mailing.3056002.n2.nabble.com/
_______________________________________________
[hidden email]
http://lists.gfoss.it/cgi-bin/mailman/listinfo/gfoss
Questa e' una lista di discussione pubblica aperta a tutti.
I messaggi di questa lista non hanno relazione diretta con le posizioni dell'Associazione GFOSS.it.
796 iscritti al 28/12/2017
Reply | Threaded
Open this post in threaded view
|

Re: Punti random nel poligono soluzione SpatiaLite Help

Andrea Peri
In reply to this post by a.furieri
Ottima spiegazione Alessandro.

Il mar 21 mag 2019, 18:49 <[hidden email]> ha scritto:

> On Wed, 15 May 2019 12:16:48 -0700 (MST), pigreco wrote:
> > C'è qualche suggerimento didattico su come risolvere tutto in una
> > logica SQL
> > (in sqlite) o la strada preferenziale è fare dialogare spatialite con
> > Python
> > (o altro) e qualche while loop?
> >
>
> chiaramente la strada piu' liscia, semplice e veloce e' quella di
> scrivere
> un banale programmicchio in C, C++, Java, Python o qualsiasi altro
> linguaggio
> di programmazione che supporti i loops.
>
> SQL e' un linguaggio meraviglioso, ma e' comunque un linguaggio basato
> sul
> paradigma dichiarativo; tutti gli altri (C, Java etc) sono invece
> linguaggi
> basati sul paradigma imperativo.
> nei linguaggi dichiarativi va specificato quale risultato finale si
> intende
> ottenere, dopo di che ci pensera' il linguaggio stesso ad identificare
> in
> modo ottimale tutte le azioni necessarie per arrivare a quel risultato.
> tutto l'opposto avviene nei linguaggi imperativi, in cui e' il
> programmatore
> a dovere specificare minuziosamente tutte le azioni necessarie per
> arrivare
> al risultato finale.
>
> non e' che un paradigma sia superiore all'altro; sono profondamente
> diversi,
> e ciascuno di essi e' piu' adatto ad alcuni problemi piuttosto che ad
> altri.
> e' un po' come avere a disposizione un coltello da cucina ed un'ascia;
> se devi
> affettare del pane l'ascia sara' decisamente poco pratica, esattamente
> come
> il coltello da cucina si rivelera' inadeguato per abbattere una
> quercia.
>
> venendo allo specifico del tuo problema, lo possiamo sintetizzare in
> questo pseudo-algoritmo:
>
> 0. inizializzazione: definisci il poligoo ed azzeri il contatore
> 1. se il contatore ha raggiunto il valore massimo vai al punto 4)
>     altrimenti procedi al punto successivo.
> 2. calcola un punto random all'interno del BBOX del poligono
> 3. verifica se il  punto cade realmente all'interno della superficie
>     del poligono
>     3-A) si: inseriscilo nella tavola, incrementa il contatore e torna
>          al punto 1)
>     3-B) no: torna al punto 1) senza incrementare il contatore
> 4. fine
>
> questo e' un classico loop, e tutti i linguaggi di programmazione
> imperativi sono fatti apposta per rendere semplice l'esecuzione
> dei loops.
> SQL invece segue tutt'altra logica, ed offre solo la WITH RECURSIVE
> per mettere in piedi (in modo abbastanza macchinoso e contorto)
> qualcosa che assomiglia ad un loop.
> conclusione: quando usare un loop e' assolutamente critico (come
> nel tuo caso, visto che non puoi sapere in anticipo se/quanti
> punti random cadranno effettivamente dentro al poligono)
> pretendere di usare solo SQL puro non e' la scelta ottimale.
> e' un po' come cercare di affettare pane e salame con l'ascia;
> se usi invece il coltello da cucina fatichi molto meno.
>
> ciao Sandro
> _______________________________________________
> [hidden email]
> http://lists.gfoss.it/cgi-bin/mailman/listinfo/gfoss
> Questa e' una lista di discussione pubblica aperta a tutti.
> I messaggi di questa lista non hanno relazione diretta con le posizioni
> dell'Associazione GFOSS.it.
> 796 iscritti al 28/12/2017
_______________________________________________
[hidden email]
http://lists.gfoss.it/cgi-bin/mailman/listinfo/gfoss
Questa e' una lista di discussione pubblica aperta a tutti.
I messaggi di questa lista non hanno relazione diretta con le posizioni dell'Associazione GFOSS.it.
796 iscritti al 28/12/2017