The solution: principle
Create a buffer around the street with variable width (until the nearest building), extend it slightly and than get all the boundary lines from the buildings completely inside the buffer.
Remark: as @Spacedman remarked, any solution to this problem is confronted with a general problem, inherent to the nature of the data: using relatively complex geometries (thus: not just a few generalized, straight lines for streets, not only perfect rectangles for buildings, parallel to streets) makes it almost impossible to automatically define universally valid criteria for what means "adjacent to a street". Compare the real world data I used on the screenshots below. This solution however creates pretty good results with reasonable effort - and it can be refined to fit the date you have.
Output of this solution (red lines) for a realworld example using OSM data with basemap that produces quite accurate results expect for a few special cases: the example illustrates what can be achieved with this solution and where potential problems arise. Facing "streets" here includes footpaths:
Step by step implementation using QGIS
Explode the line of the street layer to get a separate feature for each segment of the street lines.
Run Menu Vector / Geoprocessing Tools / Buffer
. For Distance
, use a data driven override with the following expression and check the box to Dissolve result
:
length (
make_line (
closest_point (
overlay_nearest( 'building', $geometry)[0],
$geometry
),
closest_point (
$geometry,
overlay_nearest ('building', $geometry)[0]
)
)
)*1.5
The expression calculates the shortest distance between each line feature of the street layer to the closest building and multiplies this distance by a factor defined in the last line (here: 1.5
) to get an individual buffer-distance for each street segment. See below to refine the expression.
Explode the lines of the buildings and run multipart to single parts.
Check which of the exploded/single part lines from the buildings are completely within the buffer. Use select by expression with overlay_within ('buffer')
or with this expression and Geometry generator:
if (
overlay_within ('buffer'),
$geometry,
''
)
Using real world data from Openstreetmap with streets (black lines), buffer (blue), buildings (gray) and edges of the buildings facing the streeets. Results are not yet perfect, but by adapting the size of the buffer, this can be easily done (see below):
Refine the result
To get better distances for the buffer, a number of changes to workflow can be implemented:
Break up the street line to segments of a max. length using Split lines by max length
- like 1 meter.
Don't use the closest building from the street, but the second closest by modifying the overlay_nearest
function as follows: overlay_nearest( 'building', $geometry, limit:=2)[1]
Set a maximum for the buffer size. Let's say create a buffer only if the nearest /2nd nearest building is max. 20 m away.
Use this modifyied expression as input for the buffer size in step 2 of the initial solution:
with_variable (
'length',
length (
make_line (
closest_point (
overlay_nearest( 'building', $geometry,limit:=2)[1],
$geometry
),
closest_point (
$geometry,
overlay_nearest ('building', $geometry,limit:=2)[1]
)
)
),
if (@length <= 20, @length, 0) *1.15
)
Result using the refined solution: