SQL fiddle
Crea una tabella con la colonna poligono
Si prega di notare, che per usare indici spaziali, non è possibile utilizzare InnoDB. È possibile utilizzare la geometria senza indici spaziali, ma le prestazioni si degradano come al solito.
CREATE TABLE IF NOT EXISTS `spatial` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`poly` geometry NOT NULL,
UNIQUE KEY `id` (`id`),
SPATIAL INDEX `poly` (`poly`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Prendi 3 quadrati e un triangolo inserito
INSERT INTO `spatial` (`poly`) VALUES (GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0))',0));
INSERT INTO `spatial` (`poly`) VALUES (GeomFromText('POLYGON((10 50,50 50,50 10,10 10,10 50))',0));
INSERT INTO `spatial` (`poly`) VALUES (GeomFromText('POLYGON((1 15,5 15,5 11,1 11,1 15))',0));
INSERT INTO `spatial` (`poly`) VALUES (GeomFromText('POLYGON((11 5,15 5,15 1,11 5))',0));
Selezionare tutto ciò che si interseca piccola piazza nell'angolo in basso a sinistra (viola quadrato # 1)
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Intersects(`poly`,
GEOMFROMTEXT('POLYGON((0 0,2 0,2 2,0 2,0 0))', 0)
)
;
Seleziona tutto ciò che interseca il triangolo che va via m basso a sinistra per abbassare gli angoli retti in alto a destra) (piazze # 1 e # 2 e triange # 4.)
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Intersects(`poly`,
GEOMFROMTEXT('POLYGON((0 0,50 50,50 0,0 0))', 0)
)
;
Seleziona tutto in piazza che è al di fuori della nostra immagine (niente)
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Intersects(`poly`,
GEOMFROMTEXT('POLYGON((100 100,200 100,200 200,100 200,100 100))', 0)
)
;
Modifica # 1:
ho riletto la questione e penso di avere le relazioni spaziali un po 'confuso. Se quello che vuoi è trovare tutto ciò che si adatta all'interno di un quadrato (poligono), allora devi usare Contains/ST_Contains. Si prega di vedere spatial functions in MySQL documentation per scoprire quale funzione fa il lavoro per voi. Si prega di notare quanto segue differenza tra le funzioni ST/MBR:
Seleziona tutto ciò che è completamente all'interno di un quadrato (# 0 dal basso) (quadrati # 1, # 2, triangolo 4 #)
SELECT id,AsText(poly) FROM `spatial`
WHERE
Contains(
GEOMFROMTEXT('POLYGON((0 0,20 0,20 20,0 20,0 0))', 0),
`poly`
)
;
seleziona tutto ciò che è completamente all'interno di un quadrato (# 0 dal basso) e condivide spigoli (quadrato # 2, # triangolo 4)
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Contains(
GEOMFROMTEXT('POLYGON((0 0,20 0,20 20,0 20,0 0))', 0),
`poly`
)
;
Edit # 2:
Molto bella aggiunta da @StephanB (SQL fiddle)
Per elencare tutte le intersezioni unirsi al tavolo su se stesso e filtrare via l'intersezione inversa
Seleziona eventuali oggetti sovrapposti
SELECT s1.id,AsText(s1.poly), s2.id, AsText(s2.poly)
FROM `spatial` s1, `spatial` s2
WHERE
ST_Intersects(s1.poly, s2.poly)
AND s1.id < s2.id
;
(solo informiamo che è necessario rimuovere il AND s1.id < s2.id
se si sta lavorando con CONTAINS
, come CONTAINS(a,b) <> CONTAINS(b,a)
mentre Intersects(a,b) = Intersects(b,a)
)
Nella figura seguente (elenco non esaustivo):
2 interseca # 6.
6 interseca # 2
0 interseca # 1, # 2, # 3, # 4, # 5
1 interseca # 0, # 5
0 contiene # 1, # 3, # 4 e # 5 (# 1, # 3, # 4 e # 5 sono raggiungibili # 0)
1 contiene # 5 (# 5 è entro 1 #)
0 ST_Contains # 3, # 4 e # 5
1 ST_Contains # 5
Modifica # 3: Ricerca per distanza/Lavorare in (con) circola attorno
MySQL non supporta direttamente il cerchio come una geometria, ma è possibile utilizzare la funzione spaziale Buffer(geometry,distance)
per aggirare il problema. Quello che fa Buffer()
sta creando un buffer di detta distanza attorno alla geometria. Se inizi con il punto di geometria, il buffer è effettivamente un cerchio.
Si può vedere ciò che realmente fa tampone chiamando semplicemente:
SELECT ASTEXT(BUFFER(GEOMFROMTEXT('POINT(5 5)'),3))
(risultato è piuttosto lungo, quindi non mi post qui) Si crea in realtà un poligono che rappresenta il buffer - in questo caso (e il mio MariaDB) il risultato è un poligono di 126 punti, che si avvicina a un cerchio. Con un tale poligono puoi lavorare come faresti con qualsiasi altro poligono. Quindi non ci dovrebbero essere penalità per le prestazioni.
Quindi, se si vuole selezionare tutti i poligoni che rientrano in un circolo si può lavare e ripetere precedente esempio (questo sarà trovare solo la piazza # 3)
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Contains(
Buffer(GEOMFROMTEXT('POINT(6 15)'), 10),
`poly`
)
;
Seleziona tutti i poligoni che si intersecano con un cerchio
SELECT id,AsText(poly) FROM `spatial`
WHERE
ST_Intersects(
Buffer(GEOMFROMTEXT('POINT(6 15)'), 10),
`poly`
)
;
Quando si lavora con forme diverse da rettangoli, è necessario utilizzare il ST_*
fu nctions. Le funzioni senza ST_
utilizzano un rettangolo di delimitazione. Quindi l'esempio precedente seleziona il triangolo # 4 anche se non è nel cerchio.
Poiché Buffer()
crea poligoni abbastanza grandi, ci sarà sicuramente qualche penalizzazione delle prestazioni rispetto all'utilizzo del metodo ST_Distance()
. Purtroppo non posso quantificarlo. Dovrai fare un po 'di benchmarking.
altro modo di trovare oggetti per distanza utilizza la funzione ST_Distance()
.
selezionare tutti gli elementi della tavola e calcolare la loro distanza dal punto PUNTO (6 15)
SELECT id, AsText(`poly`),
ST_Distance(poly, GeomFromText('POINT(6 15)'))
FROM `spatial`
;
È possibile utilizzare ST_Distance
in WHERE
clausola pure.
Seleziona tutti gli elementi la cui distanza dal punto (0 0) è inferiore o uguale a 10 (seleziona # 1, # 2 e # 3)
SELECT id, AsText(`poly`),
ST_Distance(poly, GeomFromText('POINT(6 15)'))
FROM `spatial`
WHERE ST_Distance(poly, GeomFromText('POINT(6 15)')) <= 10
;
Sebbene la distanza viene calcolata dal punto più vicino punto più vicino Rendendolo simile allo ST_Intersect
. Quindi l'esempio sopra selezionerà # 2 anche se non si adatta interamente al cerchio.
E sì, il secondo argomento (0) per GeomFromText(text,srid)
, non svolge alcun ruolo, è possibile ignorarlo tranquillamente. L'ho preso da un campione ed è rimasto bloccato nella mia risposta. L'ho lasciato fuori nelle mie successive modifiche.
btw. Il supporto phpMyAdmin per l'estensione spaziale non è perfetto, ma aiuta un po 'a vedere cosa c'è nel tuo database. Mi ha aiutato con queste immagini che ho allegato.
https://dev.mysql.com/doc/refman/5.0/en/using-spatial-data.html – DhruvPathak