Namn

ST_DWithin — Testar om två geometrier ligger inom ett givet avstånd

Synopsis

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);

Beskrivning

Returnerar true om geometrierna ligger inom ett givet avstånd

För geometri: Avståndet anges i enheter som definieras av geometriernas spatiala referenssystem. För att denna funktion ska vara meningsfull måste källgeometrierna vara i samma koordinatsystem (ha samma SRID).

För geografi: enheterna är i meter och avståndsmätning sker som standard med use_spheroid = true. För snabbare utvärdering, använd use_spheroid = false för att mäta på sfären.

[Notera]

Använd ST_3DDWithin för 3D-geometrier.

[Notera]

Detta funktionsanrop innehåller en jämförelse av begränsningsrutor som använder alla index som finns tillgängliga för geometrierna.

Denna metod implementerar OGC:s implementeringsspecifikation för enkla funktioner för SQL 1.1.

Tillgänglighet: 1.5.0 stöd för geografi infördes

Förbättrad: 2.1.0 förbättrad hastighet för geografi. Se Göra geografi snabbare för mer information.

Förbättrad: 2.1.0 stöd för krökta geometrier infördes.

Före 1.3 användes ST_Expand ofta i kombination med && och ST_Distance för att testa avstånd, och före 1.3.4 använde den här funktionen den logiken. Från och med 1.3.4 använder ST_DWithin en snabbare funktion för kortslutningsavstånd.

Exempel

This self-contained geometry example keeps the compared shapes visible while also returning the boolean results.

Code
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;
Rasterutdata
-[ 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)
Figure
Geometry figure for visual-st-dwithin-01

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.

Code
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).

Code
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.

Code
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.

Code
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.

Code
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);