3

I want to identify several types of polygons. I got stuck at two types of categories that I don't know how to identify. I will post every situation here, maybe someone has an idea.

I have a layer with polygon segments (line type) which has a calculated field where the front street is equal to 1 and the others to 0. I also have the field with the number of faces.

I have to identify on this layer with line segments that also have the group field with identifier for each polygon. Then it's easy for me to turn this layer back into a polygon layer, but I don't know how to identify 2 types of plots.

Case 1: angle plots - at the crossroads of two roads.

enter image description here

Here i have to identify the consecutive segments that have the value 1 in the "front street" field.

Case 2: polygons with 4 sides, which has two sides overlooking two different roads.

enter image description here

Here i have to find the polygons that have 2 parallel street segments.

1
  • 2
    How is your data structured: can you provide sample data and/or a screenshot of your attribute table? Why do you want to do this with lines? Why don't you use the polygon layer for this task?
    – Babel
    May 17 '21 at 16:35
6

Prepare your data: Make sure the polygon layer contains a uniqe identifyer attribute called id. Do not use the fid field if working with Geopackage: after step 2, this field will not be unique any more and you can't save it as Geopackage.

  1. Convert the polygons to lines.

  2. Explode lines

  3. Create a new attribute field namend bound with field calculator to identify each line segment (polygon side): inner if it borders to a neighboring polygon, outer if not. Use this expression: if (overlay_contains( @layer),'inner','outer') (overlay_contains is available since QGIS 3.16).

    Screenshot: see the exploded lines labeled with the output (black); blue labels represent the id of each polygon: enter image description here

  4. In step 3, we calculated for each line segment (each side of the polygon) if it borders on another polygon (inner) or not (outer). Now let's create another value: each side of the polygon is connected to two other sides (lines) of the same polygon (at start- and end-points: the corners of the polygon). So now let's calculate for each line/side how many of the two connected lines/sides are outer, too. Create a new field neighboring_outer, using this expression in the field calculator:

array_length(
    array_remove_all( 
         array_foreach (
            array_filter (
                overlay_touches( 
                    @layer,
                    $id
                ),
                attribute (
                    get_feature_by_id(
                        @layer,
                        @element 
                    ),
                    'id'
                ) = id
            ),
            if (
                attribute (
                    get_feature_by_id(
                        @layer, 
                        @element
                    ),
                    'bound'
                ) = 'outer',
                @element,
                0
            )
        ),
        0
    )
)

Screenshot showing the result by labeling each line with the value calculated: the number of neighboring line with outer values each line has: enter image description here

  1. The distribution of these values now can be used to differentiate between different categories of polygons, based on two characteristics:
    1. sum of 'outer' sides per polygon (how many sides of the polygon are 'outer')
    1. highest value per polygon of 'outer' values for neighboring sides (neighboring_outer)

Thus calculate a new field cat_code with this expression:

aggregate( 
    @layer, 
    'sum', 
    neighboring_outer, 
    filter:= attribute (@parent, 'id') = id
) ||
aggregate( 
    @layer, 
    'max', 
    neighboring_outer, 
    filter:= attribute ( @parent, 'id') = id
)

Screenshot: the blue labels are the result of the calculation. The value of the blue label is simply a concatenation of the sum of black values per polygon with the highest black value per polygon (black values as above): enter image description here

  1. Copy the created cat_code from the exploded line- back to the original polygon layer. Create there a field, called cat_code as well using this expression:
attribute (
    get_feature (
        'exploded',
        'id',
        id
    ),
    'cat_code'
)
  1. We have 6 different cases, coded with these numbers: 0, 21, 41, 42, 62, 82 (the higher the number, the more outside sides the polygon has). We can convert these numbers to a descriptive text, creating a new field category with this expression:
case 
   when "cat_code" = 0 then 'enclosed'
   when "cat_code" = 21 then 'inside'
   when "cat_code" = 41 then 'corner'
   when "cat_code" = 42 then 'front/back'
   when "cat_code" = 62 then 'exposed'
   when "cat_code" = 82 then 'isolated'
end

And this is how the result looks like:

enter image description here


You might remark a problem with polygons no. 16, 17 and 18 (see next screenshot below for identification): here, the results are wrong (see last two screenshots above). That's because in this case, the southern side of polygon 16 borders on two different polygons. For polygon 16, we have one straight line, northern line of polygon 17 and 18 are shorter lines. Because of that, in step 3, these lines are not recognized by overlay_contains() as being contained in each other (16 is not contained in 17 nor in 18; 17 and 18 are not contained in 16).

In this case, the problem can easily be avoided by adding a vertex in the polygon on the southern line of polygon 16 where it meets the corners of polygons 17 and 18.

Screenshot with additional vertex (red arrow) that affects the results for polygons 16 to 18 that are now correctly categorized: enter image description here

5
  • This method is superb. However, this require quite "clean" polygons". In my case I have worst polygons since they have a higher number of sides, even if quite small. The result for your step 3 is this: [![enter image description here][1]][1] [1]: i.stack.imgur.com/PSYeG.png I tried to simplify the geometry with no great success since when the simplification occurs it may affect the boundary of the line (goes from inner to outer for instance in contiguous buildings) I am still trying to understand what to do.... any clue would be great Aug 11 '21 at 15:05
  • 1
    For more complex forms, you might indeed need another solution. Maybe some of the steps here can provide some ideas.
    – Babel
    Aug 11 '21 at 15:09
  • Maybe a Minimum Oriented Rectangle could help you? It will for sure generate a simplified version of your geometries - however, topology will not be preserved.
    – Babel
    Aug 11 '21 at 15:17
  • Looks good, but Minimum Oriented Rectangle originates not coincident inner lines and then wrong outer faces Aug 11 '21 at 15:41
  • I believe that could be something related with both "outer " inner" line condition and the orientation. Some type of sumif and then a geometry logic. Still trying... Aug 11 '21 at 16:10

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.