ST_DWithin — Teste si deux géométries se trouvent à une distance donnée
boolean ST_DWithin(geometry g1, geometry g2, double precision distance_of_srid);
boolean ST_DWithin(geography gg1, geography gg2, double precision distance_meters, boolean use_spheroid = true);
Renvoie true si les géométries se trouvent à une distance donnée
Pour le type geometry : la distance est spécifiée en unités définies par le système de référence spatiale des géométries. Pour que cette fonction ait un sens, les géométries sources doivent se trouver dans le même système de coordonnées (avoir le même SRID).
Pour le type geography : les unités sont en mètres et la mesure de la distance est par défaut use_spheroid = true. Pour une évaluation plus rapide, utilisez use_spheroid = false pour mesurer sur la sphère.
|
|
|
Utilisez ST_3DDWithin pour les géométries 3D. |
|
|
|
Cet appel de fonction inclut une comparaison de la boîte de délimitation qui utilise tous les index disponibles sur les géométries. |
Cette méthode implémente la spécification OGC Simple Features Implementation Specification for SQL 1.1.
Disponibilité : la prise en charge du type geography a été introduite dans la version 1.5.0
Amélioration : la version 2.1.0 a amélioré la vitesse pour le type geography. Voir Making Geography faster pour plus de détails.
Amélioration : la prise en charge des géométries courbes a été introduite dans la version 2.1.0.
Avant la version 1.3, ST_Expand était couramment utilisé en conjonction avec && et ST_Distance pour tester la distance, et avant la version 1.3.4, cette fonction utilisait cette logique. À partir de la version 1.3.4, ST_DWithin utilise une fonction de distance de court-circuit plus rapide.
This self-contained geometry example keeps the compared shapes visible while also returning the boolean results.
WITH sample AS (
SELECT ST_Buffer('POINT(100 90)'::geometry, 50, 'quad_segs=2') AS coverage,
ST_Point(120, 120) AS inside_pt,
ST_Point(170, 90) AS outside_pt
)
SELECT ST_DWithin(coverage, inside_pt, 0) AS inside_now,
ST_DWithin(coverage, outside_pt, 10) AS outside_within_10,
coverage AS coverage_geom,
inside_pt AS inside_geom,
outside_pt AS outside_geom
FROM sample;
-[ RECORD 1 ]----- inside_now | t outside_within_10 | f coverage_geom | POLYGON((150 90,135 55,100 40,65 55,50 90,65 125,100 140,135 125,150 90)) inside_geom | POINT(120 120) outside_geom | POINT(170 90)
Find the nearest hospital to each school. That is within 3000 units of the school. We do an ST_DWithin search to utilize indexes to limit our search list. That the non-indexable ST_Distance needs to process. If the units of the spatial reference is meters then units would be meters.
SELECT DISTINCT ON (s.gid) s.gid, s.school_name, s.geom, h.hospital_name
FROM schools s
LEFT JOIN hospitals h ON ST_DWithin(s.geom, h.geom, 3000)
ORDER BY s.gid, ST_Distance(s.geom, h.geom);
The schools with no close hospitals. Find all schools with no hospital within 3000 units away from the school. Units are in units of spatial reference (for example meters, feet, or degrees).
SELECT s.gid, s.school_name
FROM schools s
LEFT JOIN hospitals h ON ST_DWithin(s.geom, h.geom, 3000)
WHERE h.gid IS NULL;
Find locations more than 3000 units away from their nearest hospital. Use NOT EXISTS so that a location is returned only when no nearby hospital exists.
SELECT l.location_name
FROM locations l
WHERE NOT EXISTS (
SELECT 1
FROM hospitals h
WHERE ST_DWithin(l.geom, h.geom, 3000)
);
Find broadcasting towers that a receiver with limited range can receive. Data is geometry in Spherical Mercator (SRID=3857), ranges are approximate.
CREATE INDEX ON broadcasting_towers USING gist (geom); CREATE INDEX ON broadcasting_towers USING gist (ST_Expand(geom, sending_range));
Query towers that a 4-kilometer receiver in Minsk Hackerspace can get. Note: two conditions are required because the shorter LEAST(b.sending_range, 4000) will not use an index.
SELECT b.tower_id, b.geom
FROM broadcasting_towers b
WHERE ST_DWithin(b.geom, 'SRID=3857;POINT(3072163.4 7159374.1)', 4000)
AND ST_DWithin(b.geom, 'SRID=3857;POINT(3072163.4 7159374.1)', b.sending_range);