# Extracting lines from polygons/buildings based on adjacency to lines/streets

I have a building and street shapefile of a district. I am looking for a way to select and eventually extract those lines or edges of the buildings that face the street.

however the extracted edges for each building need to be somehow grouped or merged into 1 line since on the next step i need to create certain number of points on the lines based on a value given for each building.

Is there anyway to do this?

• Are your buildings all rectangular? Do you have any round buildings? What about buildings on a street corner? What about rectangular buildings that don't line up with streets? Is your street data the road centerline or road edges? What does it all look like? Can you show us a sample map? Do you just want to end up with a layer of detached building edges as line features with or without relation to the building they came from? Mar 11 '21 at 18:15
• Thanks for following up. so the buildings are in rectangular or similar shapes. and the streets are simple lines. (unfortunately i could not add image here to show it). what i am trying to is, i have the centeroids of the buildings as points with populations as their values. i need to distribute these population values into random number of points and align them along those edges of buildings that face the street. so if a building faces two streets, then algning along both. for aligning i am using "snap to geometry". so i was thinking of extracting the street fracing edges first. Mar 11 '21 at 18:42

A (partial) solution could look like this:

On the polygon layer with your buidings, create the point that is closest to the nearest segment of the street layer. You can use expressions with geometry generator (for visualization purposes only) or `Menu Processing / Toolbox / Geoemtry by expression` to create actual geometries as a separate point layer.

In both cases, use the following expression. For the purpose here, use `Geoemtry by expression` to create a new layer named 'closest_point':

``````closest_point(
\$geometry,
collect_geometries (
overlay_nearest(
'highway',
\$geometry
)
)
)
``````

You than can convert your polygons to lines and explode these lines - to have a separate feature for each segment of the line surrounding your buildings. On this explodes line layer, use `select by expression` with the expression `overlay_touches( 'closest_point')`.

You can copy the selected lines to a new layer. This should give you in many cases the result you want - see the red lines on the next screenshot. However, things can be tricky in all the cases mentioned in the comment by @Spacedman. So you should reflect clearly how to solve such cases. As you can see, there are many problems and I fear you have to address them one by one. But at least you have a starting point.

## 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

1. Explode the line of the street layer to get a separate feature for each segment of the street lines.

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

3. Explode the lines of the buildings and run multipart to single parts.

4. 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:

1. Break up the street line to segments of a max. length using `Split lines by max length` - like 1 meter.

2. 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]`

3. 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: