3

I'm looking to fill a polygon with points with a regular spacing, but the points don't need to be in line vertically.

So, in the image below, the points are all spaced out evenly on an x/y spacing, but while the rows are all in line, they have been shifted left or right to match the polygon shape and fit in the maximum points on each horizontal row.

Example of how the output should look

This was done on another piece of software, which we no longer have access to, but I'm looking to do the same in QGIS.

Any ideas?

So thanks to @Babel's help, I'm able to get somewhere, but where two polygons meet there is an overlap, the intersection expression worked for displaying the lines but not in the 'geometry by expression' output.

Id like to keep the lines within their own polygon, rather than the overlap.

overlapping lines

5

You can create parallel lines with Geometry generator (or geometry by expression, see here for the difference) and intersect them with the polygon. Than style this lines with Marker Line symbology. This is for visualization purposes; if you need actual geometries, it works very similarly, but with a few differences, see below.

For visualization purposes

To get horizontal lines, simple create the bounding box of the polygon and create a line from the upper left to the upper right angle of this bounding box, than shift this line in parallel several times for a defined interval - 70 [meters] in my case: you can change this value on line 8:

intersection( 
    $geometry,
    collect_geometries (
        array_foreach (
            generate_series (
                0,  
                bounds_height( $geometry), 
                70
            ),
            offset_curve( 
                make_line (
                    make_point (
                        x_min (bounds($geometry)),
                        y_max (bounds($geometry))),
                    make_point (
                        x_max (bounds($geometry)),
                        y_max (bounds($geometry)))
                ),
                -@element
            )
        )
    )
)

Screenshot 1: the undelying dotted lines are here for visualization purposes only (I added an additional symbol layer): enter image description here

Screenshot 2: Setting Marker Line with interval (one point every 100 m) and offset (first point 20 m from the polygon boundary on the left side):

enter image description here

To create actual geometries

If you have several polygons where the lines created in step 1 intersect with more than one polygon, see below how to solve this (it's based on this here, but with some other workflow except step 1 and 4 from here).

In principle, to create actual geometries, it works very similar as the solution above for visual purposes only:

  1. Use Menu Processing / Toolbox / [Geometry by expression][1] with the same expression as above, but only starting from line 3 (collect_geometries ( and deleting the closing bracket ) on the last line. This creats lines that project beyond the polygon.

  2. Use Menu Vector / Geoprocessing tools / Clip, set the line from step 1 as input and the polygon as Overlay layer`. You get lines clipped to the polygon.

  3. All lines are part of one multipart geometry, but we want a single feature per line, thus use Menu Vector / Geometry Tools / Multipart to singleparts.

  4. Use Menu Processing / Toolbox / Points along geometry, where you can define the Distance and Start offset for the points to be generated.

enter image description here

To avoid overlapping of the lines with neighboring polygons

Preparation: be sure you polygon layer contains an attribute with a field containing a unique identifier (field id in my case).

  1. Step 1 as above (Geometry by expression), result:

    enter image description here

  2. Run Menu Vector / Geoprocessing Tools / Clip, set the lines created in step 1 as Input layer and the polygon layer as Overlay layer, result:

    enter image description here

  3. On the lines created in step 2, run Menu Vector / Geometry Tools / Multipart to singleparts - output visually looks the same as above.

  4. Nex click the icon Select by expression, paste the following expression an apply it to select all lines (highlighted in yellow in the next screenshot) that can be deleted. Replace 'polygon' with the name of your polygon layer and id with the name of your attribute field containing the unique identifier:

    disjoint(
    $geometry,
    with_variable (
       'current',
       id,
       aggregate( 
           'polygon', 
           'collect', 
           $geometry, 
           filter:=id=@current
       )
    )
    )
    

    enter image description here

  5. Toggle editing and delete the selected lines.

    enter image description here

  6. Continue with step 4 from the previous solution above: Points along geometry - see result:

    enter image description here

Old solution, still preserved in case it's useful for others

This is an option to create not horizontal lines, but lines parallel to one of the polygon boundary segments.

As you don't provide more details, I show how I did it: adapt this to your use case (details below). Create a new symbol layer on the polygon layer, set it to Geometry Generator / LineString and paste this expression. Style the lines thus created as Marker Line:

intersection( 
    $geometry,
    collect_geometries (
        array_foreach (
            generate_series (1, 5000, 70),
            offset_curve( 
                extend (
                    make_line (
                        point_n( $geometry,2),
                        point_n( $geometry,1)
                    ),
                    1000,
                    0
                )
                ,
                -@element
            )
        )
    )
)

Screenshot: the undelying dotted lines are here for visualization purposes only (I added an additional symbol layer): enter image description here

How you can adapt this to your use case:

  1. The direction of the line. I took a line parallel to the upper polygon boundary. The upper right vertex of the polygon has index-no. 1, the upper left one is no. 2. So on line 9 and 10, change the index-no of the vertices that form the line to which your lines should be parallel.

  2. The interval between and number of parallel lines are defined in line 5 inside generate_series(). In my case, it generates parallel lines with interval of 70 [meters], starting from 1 to 5000. Increase this last value to get more lines, increase 70 to get more distance between the lines.

  3. The lines normally must be extended to cover the whole polygon. This is done with the values in line 12 and 13, 1000 and 0 in my case. You can safely increase these values as much as you want as the lines anyhow will be "cut" to the polygon extent by the intersection() function (line 1).

  4. In line 16, you have the variable @element, refering to the current iteration of the array created in line 5 (the generate_series() part). Depending to which side of the line you want to create parallel copies, this value must be positive (shifting to the left of the line, than delete the minus sign: -) or negative (as in my example, than the line is shifted to the right).

10
  • Hey, Thanks for the reply, The points would remain flat on the x axis, with the spacing between points being 20 meters. the y spacing would be 10 on the x axis. It looks like what youve done does answer my problem by shifting the rows to the side
    – Anthony
    May 14 at 17:03
  • So it does answer your question? Or there is still something unclear?
    – Babel
    May 14 at 17:04
  • sorry for the confusion, So in your first point you said how you drew the line parallel to the upper polygon boundary, Im look to have them flat, with a constant x value, running west to east. Also, Ive copied the expression but the line dont fill out the full polygon, i changed the distance between the lines to 10 and its only giving me 6 lines at the top of the polygon.
    – Anthony
    May 14 at 17:28
  • Horizontal lines are even easier, see updated solution. I also adapted the solution so I should automatically fill the whole polygon.
    – Babel
    May 14 at 17:42
  • This seems to be working, So im thinking if i run 'geometry by expression' to make these lines a shapefile, i can then use the QChainage plugin to put points along the lines? Im needing the points as a shapefile and this Qchainage was my first approach?
    – Anthony
    May 14 at 18:50

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.