6

I work in precision agriculture and use QGIS. Today's technology makes it possible to adjust the spreading width of, for example, sprayers and manure spreaders according to where you have driven before, to reduce overlap. Such implements can have a spreading width of over 30 m. The overlap, when driving towards the headland at an angle <> 90 degrees, will be significant when considering investing in such equipment.

So, to the point. I want to make a tool in QGIS Graphic Modeler with the field boundary and the width of the implement and direction of travel as input. QGIS would then calculate the overlap. I have reached a point where I have made a headland (buffer on the inside of the border with the width corresponding to the tool). After specifying a direction of travel, I have made parallel lines indicating the center point of the track. These are then "clipped" to the headland.

enter image description here

A buffer on each side of the track (with a flat end cap) marks the area worked. The result is then an overlap on one side of the track and a "negative" overlap on the other side of the track (see figure) when I enter the headland on an angel <> 90 degrees. enter image description here

As I want to automate the process, I need help to figure out how to extend the worked area a little longer on each end to just cover the headland as the figure shows. enter image description here

Will it be possible to calculate the maximum extent of the worked area by figuring out point A and B, then extend the rectangle to that pint and then repeat this process for all the worked rectangles?

https://i.sstatic.net/IwcaY.png

3
  • Please define "headline", and edit your screeshot to show its location.
    – Stu Smith
    Commented Jan 7, 2021 at 16:03
  • Stupid auto-correct. "headland" or "hedland"
    – Stu Smith
    Commented Jan 7, 2021 at 16:04
  • “Headland” As the screenshot shows the headland is the pink area. This will be the area first area covered with with for example a planter driving along the field border. Then the tractor willl start driving in parallel lanes. My goal is to calculate the overlap between the parallel lines and the headland.
    – user29934
    Commented Jan 7, 2021 at 19:12

1 Answer 1

4

In principle, the solution is easy: extend the buffer of the worked area for so long until both lateral sides (boundaies) touch the inline of the headland. That is the distance until which the track should go to cover the whole area.

The realisation needs some steps as it includes some auxiliary lines and points to be constructed. At a first glance, it might seem a bit more complicated than it is in fact. If you need that repeatedly, you could create a processing model.

First is a "algorithmic" description, in the second part a guide how to actually implement that in QGIS.

The setting

Consider the screenshot below: red line (layer track): original track (with an interval of 44 m from line to line), blue polygon (layer worked_area): worked area (here: buffer of 22 m around red line), pink polygon (layer headland): headland (buffer around the farmland plot), line in dark pink (layer inner_boundary): inner boundary of the headland - this line encloses the area that should be fully covered by the blue buffers.

enter image description here

(By the way/side note, maybe to consider for other questions: providing sample data would ease the process of experimenting and looking for a solution that fits your data).

The basic idea

  1. Extend the red line for a distance long enough that it clearly projects beyond the headland: black dotted line (layer track_extended).

  2. Create a buffer of (again) 22 m around the line from step 1: light green outline (retangles, layer worked_area_extended)

  3. Find the intersection of the boundaray of the rectangles from 2 (light green line) with the inner boundary of the headland (dark pink line): you get the white dots (layer crossing_points).

  4. Create a line starting at the white dots, perpendicular to the direction (angle, azimuth) of the track (red line) and running on both sides for a distance slightly longer than the covered area width (22 m) to be sure it crosses the neighboring extended track - to the right as well as to the left. This line is not visible on the screenshot as it is an auxiliary line only, used to create the points in the next step (in fact, 4 & 5 will be implemented/processed in one step).

  5. Create points where the line of step 4 intersects the extended track (black dotted line): you get the red points, layer stop_point.

  6. These red points are the end point of the track you are looking for. All red points that lie on the same black dotted line should now be connected by a line. This is the final track. When implementing it in QGIS below, what is here described as one step is extended to several smaller steps (6 to 8) for auxiliary purposes.

Apply again a buffer of 22 m around it to get the final worked area (layer worked_area_final) you're looking for:

enter image description here

The implementation in QGIS

To create new geometries, use Menu Processing / Toolbox / Geometry by expression and set the appropriate geometry output type.

  1. extend ($geometry, 200,200), input: track

  2. Menu Vector / Geoprocessing Tools / Buffer

  3. Use this expression on the output from 2 to create the white dots crossing_points (and create singlepart geoemtries if you got multipoints).

intersection (
    boundary ($geometry),
    geometry (
        get_feature_by_id (
            'inner_boundary',
            1
        )
    )
)
  1. Create the perpendicular line. This step here only describes how to get the right angle for the line. We crete the actual auxiliary line starting at the crossing_points at once in step 5, where it is only used to create the final output as points stop_point, so the line itself is not needed and only an auxiliary tool. Importan is to get the correct angle (azimuth): 90 degrees from the direction of the track. To calculate it, use this expression. You might do this in the field calculator of the track layer with the expression: main_angle ($geometry). You don't need to execute it. The preview at the bottom in the expression editor shows you the value calculated: copy it. As all track lines are parallel, so this value is the same for all lines. In my case, the value is 74.84 degrees. So perpendicular means: 74.84° + 90°.

  2. Now that we have the angle, we create a new point layer on the basis of the points layer from step 3 with this expression that uses the auxiliary line to create the points: see the angle of 74.84 (change it according to your value), added 90 degrees to be perpendicular and converted to radians as the project expression expects radians, not degrees. As well, change the length of the auxiliary line (in my case: 22.1) according to your data: It should be slightly longer than the size of the buffer (22 in my case). If it has exactly the size of the buffer, the line should touch the track, but sometimes it does not create an intersection (see. QGIS snapping issue). If the line is too long, it intersects neighboring tracks as well.

intersection (
    extend ( 
        make_line (
            $geometry,
            project (
                $geometry,
                22.1,
                radians (90+74.84)
            )
        ), 
        22.1,
        22.1
    ),
    aggregate( 
        'track_extended', 
        'collect', 
        $geometry
    )
)

  1. As the output is a multipoint geometry, convert to to single points using Menu Vector / Geometry Tools / Multipart to singleparts. You get the layer stop_point as output.

  2. Now, assign to each feature (point) of the layer stop_point from 6 the no. of the track ("row" ) it belongs to so that we can group together those points that should be connected by a line in the next, final step. For this, create a new field track_no with field calculator using this expression. You should have a unique identifier in your layer track_extended, in my case it's the field named fid:

array_to_string (
    overlay_nearest( 
        'track_extended',
        fid
    )
)
  1. Connect all points from stop_point that belong to the same track using Menu Processing / Toolbox / Points to path with stop_point as Input point layer. Select track_no for both Order field and Group field. The output is the final track you're looking for, named layer track_final in my case. Apply the 22 m buffer to it to get the worked_area_final polygon layer.

Bonus: Final adjustments

If you look closely to the last screenshot, you see that there is a small corner left uncovered in the easternmost edge of the field. The same problem, but an even smaller area, can be found in the westernmost edge (barely visible on the screenshot above). You might neglect this very small area. However, to give a complete solution to your problem, you could do this:

Menu Vector / Geoprocessing tools / Difference and select inner_boundary as input layer and worked_area_final as Overlay layer to get those parts of the inline boundary of the headland that is not yet covered (outline of the "uncovered" corner). In the screenshot, it's layer difference in turquois.

Form these line(s), extract the vertices: my layer vertices (white crosses).

Create a line that connects the white crosses with the neares point on the worked_area_final with this expression:

make_line (
    $geometry,  
    closest_point ( 
        array_first (
            overlay_nearest( 
                'worked_area_final', 
                $geometry, 
                limit:=1
            )
        ),
    $geometry
    )
)

The black dotted line is for visualization purposes only, you don't have to create it, only measure the distance. For this, create a new attribute distance_corner on the layer vertices with the field calculator and the expression length(geometry), where you replace geometry by the expression from above.

Now inspect the results and decide which of the corners should be corrected, depending on the values of the distance_corner fields. In my case, the longest of the dotted black lines on the screenshot below is 12.8 m long. So the farthes point of the uncovered corner is 12.8 m away from the end of the covered area. That means: the track here has to be extended for 12.8 m.

enter image description here

Thus extend the line using the expression extend(geometry,start_distance,end_distance) and set the appropriate values, than re-create the buffer. See final result:

enter image description here

7
  • Thanks! I This is awesome! I’m working through it step by step. I have managed to reproduce to step 4 :-). In step 5 the expression runs without any errors, but the point layer has no geometry. The attribute table has an id, instance, offset and an angel field, but the id is NULL. I have tried to add a geometry column to verify that there is coordinates, bur it returns a NULL. I have also tried to simply fie the expression to locate the error. It seems that the make_line part does not create any line (empty layer without geometry. Anny suggestions?
    – user29934
    Commented Jan 19, 2021 at 21:20
  • Could it be that the lines are too short to create intersections? I used a value of 22.1 [m] - try increasing it. It should be slightly longer than the size of the buffer. If it has exactly the size of the buffer, the line should touch the track, but sometimes it does not create an intersection. If the line is too long, it intersects neighboring tracks as well.
    – Babel
    Commented Jan 19, 2021 at 21:25
  • Changing the points i 3 to single part solved the problem. Thanks. I'l grind on :-)
    – user29934
    Commented Jan 19, 2021 at 21:43
  • Will this expressions run in the graphical modeler?
    – user29934
    Commented Jan 19, 2021 at 21:45
  • OK, thanks for the hint to create single part geometries in step 3 - don't remember if I had this or converted it. I did not test it in graphic modeler, maybe a few tiny changes could be necessary, but hard to say without testing. Of course, the workflow itself for sure is possible to automatize.
    – Babel
    Commented Jan 19, 2021 at 21:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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