# How can I calculate the distance to the nearest five neighbors for a polygon layer?

Data set (shapefile) contains polygons. How can I calculate the distance to the nearest five polygons in the data set in QGIS?

• dataset is a shapefile? Sep 2, 2015 at 15:40
• how you want to measure the distance? Is it centroid to centroid? Closest vertices? Shortest line between edges? Sep 2, 2015 at 15:53
• shortest line between edges Jan 26, 2016 at 18:50

Here's an example of how you can do this, using postgresql and qgis. It finds the closest 5 polygons to each polygon in the dataset. The screenshot should show how it establishes distances.

Note that I'm using British National Grid (27700) - this a local UTM projection in meters, so over these relatively short distances the results will be quite accurate. You'll need to project your data into a similar CRS for your locale. If you're using longer distances - such as between countries or regions - you'll need to use ::geography.

• imported polygons from OpenStreetMap into PostgreSQL using shp2pgsql. This tool also sets up spatial indexes to speed things up.
• ran the query below
• exported to CSV, then imported as delimited layer
• set CRS of new layer to my local projection (27700)

Query:-

``````select * from (
select
a.gid as from_gid, -- this is an ID created on import
b.gid as to_gid,
a.full_id as from_originalid, -- this was original unique ID in shapefile
b.full_id as to_originalid,
st_asewkt(st_shortestline(a.geom,b.geom)),
st_distance(a.geom,b.geom) as distance,
RANK() OVER(PARTITION BY a.gid ORDER BY st_distance(a.geom,b.geom)) as rk
from
my_table as a,
my_table as b
where
st_dwithin(a.geom,b.geom,4000) and a.gid!=b.gid -- must be < 4km
group by
a.gid,
b.gid
order by
a.gid,
st_distance(a.geom,b.geom) ASC
) as res
where rk<=5 -- how many neighbours you want
``````

Now, I have a table which links each patch to its 5 closest neighbours...

``````"from_gid","to_gid","from_originalid","to_originalid","?column?","distance","rk"
1,90,"w33458756","w233167579","geometry",0.8228431343271,1
1,91,"w33458756","w233167992","geometry",21.1914264821244,2
1,92,"w33458756","w233168011","geometry",44.5356828699015,3
1,88,"w33458756","w233167212","geometry",86.986670207639,4
1,89,"w33458756","w233167528","geometry",109.008710565124,5
2,140,"w33458843","w307855181","geometry",41.0315108912926,1
2,11,"w33458843","w232374434","geometry",123.281434892635,2
2,10,"w33458843","w232373705","geometry",184.603505248759,3
...etc...
``````

Note that the st_dwithin() is used to speed up the query. This means that if a line is longer than 4km, it's not used. You'll need to tweak that for your dataset.