4

I have a set of polygons (buildings) and points that I'd like to spatially join. Unfortunately, some of these points are positioned outside the polygon because all points are positioned on the centroid of each building and sometimes when a building is shaped like an L, for example, the point feature isn't placed inside the polygon.

Now I'd like to preferably use QGIS to move the points that are outside polygons to be situated inside the nearest polygon.

I've tried the Snap Geometries to Layer function but the points sometimes end up on a node which is a corner node of more than one building.

Any ideas?

Buildings and points

Grey buildings are the ones where the point is positioned outside the building boundaries and therefore can't be joined.

  • 1
    I understand your pain, I've done this several times before.. Is there a 'nearest' option in your spatial join? If not but the buildings sit exclusively on land parcels then join the point with the land parcel and then spatial join the buildings to the modified land parcel - this is the preferred option but doesn't work if you have stacked land parcels (titles on floors of an apartment block), in these cases I ended up doing the join manually as there were fortunately only a few cases of owners/floor in the data I was working with. – Michael Stimson Dec 11 '19 at 22:37
  • @MichaelStimson I'm using QGIS and for what I know there is no spatial join with 'nearest' option. – oskarlin Dec 11 '19 at 22:52
  • 4
    Perhaps you could use the 'Point on surface' algorithm from the Vector geometry menu in the processing toolbox. This will generate a point for each polygon which is guaranteed to lie on the surface of its geometry. Then run 'Snap geometries to layer' again to snap your original points to the new points within each polygon. – Ben W Dec 11 '19 at 23:34
  • Do the "ID"s in common exist between building and points? If, not then is there any logic where exactly inside a polygon a point must be placed? Or it just has to be inside and does not matter where exactly? – Taras Dec 12 '19 at 5:49
4

You can achieve this join + displacement using a virtual layer.

Its underlying query would compute the distance between each point and each polygon, then will keep the closest polygon and will create a new geometry within the polygon.

go to the menu Layer > Add Layer > Add/Edit Virtual Layer... and enter the following query. Feel free to add any field of interest from the two layers.

SELECT point_on_surface(p.geometry) as geometry, p.id, b.bldID,
       MIN(ST_Distance(p.geometry,b.geometry)) AS distance
FROM p, bld as b
GROUP BY b.bldID
ORDER BY distance DESC;

The group by will ensure we get a single row for each row in the point layer (bld). Because we order by distance, the group by will retain the 1st entry, i.e. the nearest one.

The function point_on_surface guarantees that the output point will be within the specified polygon. Most of the time it will be at the centroid, but this is not guaranteed.

enter image description here

Let's note that you could filter building that are not already inside a polygon, or that you could completely remove the point displacement and simply keep the buildingID-polygonID relationship.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.