4

I have four boundary points around a plot area that I measured with an RTK unit, and I need to create a shapefile that has 13 equally-sized plots within those points. I am in the EPSG:32614 projection, so the four point coordinates are:

xcoord              ycoord
704388.4936225644, 4332694.122983527
704428.1828445836, 4332696.215448606
704427.2692543723, 4332714.244665029
704387.6004763406, 4332712.4337334875

I need 13 plots between these points, as illustrated in the picture below. The dimensions should be 3.048m x 18.29m. I have tried the v.mkgrid from the GRASS toolbox, but it doesn't quite line up precisely between the points like I need it to:

enter image description here

How can I make equally-sized grids between these four points?

If you would like the shapefiles for further investigation, they can be downloaded here (total download size: 24 KB).

s_o_c_account
  • 101
  • 2
  • 14
  • 2
    You can try looking at this answer. It addresses how to make subdivisions in a rectangle. The only issue is that your surveyed points assuredly don't describe a perfect rectangle. Maybe you could consider fitting a perfect rectangle using a tool like Oriented minimum bounding box? – Gabriel May 09 '23 at 15:46

1 Answers1

3

Use the following expression (see below) with Geometry by expression, making the following adaptations:

  • replace the @id of the points at the bottom/top - right/left (use a label with @id to see which point has which id); See QGIS documentation: @id is the newer syntax to use for the older $id, so in older QGIS versions, you might have to replace @id with $id
  • in line 2 ($id=1), change 1 to any number of the $id of one of the points
  • in line 3, change the number to define the numbor of polygons you want to create and replace
  • replace points with the name of your points layer

Run Multipart to singleparts on the resulting layer to get separate features.

Works even for irregularily shaped polygons: enter image description here

This is the expression to use:

case 
when @id=1  -- must be a valid @id value of one of the points
then with_variable('no',13,  -- no. of sub-polygons you want the polygon to divide into
with_variable(
    'line1',
    make_line (
        geometry (get_feature_by_id ('points', 0)), -- @id of point at bottom left
        geometry (get_feature_by_id ('points', 1))  -- @id of point at bottom right
    ),
with_variable(
    'line2',
    make_line (
        geometry (get_feature_by_id ('points', 3)),  -- @id of point at top left
        geometry (get_feature_by_id ('points', 2))  -- @id of point at top right
    ),
collect_geometries (
    array_foreach (
        generate_series (1,@no),
        make_polygon(
            make_line(
                end_point(
                    line_substring (
                        @line1,
                        0,
                        length(@line1)/@no*(@element-1)
                    )
                ),
                end_point(
                    line_substring (
                        @line1,
                        0,
                        length(@line1)/@no*@element
                    )
                ),
                end_point(
                    line_substring (
                        @line2,
                        0,
                        length(@line2)/@no*@element
                    )
                ),
                end_point(
                    line_substring (
                        @line2,
                        0,
                        length(@line2)/@no*(@element-1)
                    )
                )       
)))))))
end

The expression in use, here with Geometry Generator (just for visual purpose, not creating actual geometries): enter image description here


If you have not one set of 4 points, but several ones, you can slightly modify the expression to subdivide all rectangles at once. For this, you have to define an array for each rectangle, listing the points as you can see in the screenshot (find the expression below):

enter image description here

collect_geometries(
case 
when @id=1  -- must be a valid $id value of one of the points
then with_variable('no',13,  -- no. of sub-polygons you want the polygon to divide into
array_foreach(
    array (
        array (0,1,19,18),
        array (19,18,20,15),
        array(22,11,23,10),
        array(20,15,21,14),
        array(21,14,22,11),
        array(2,3,17,4),
        array(17,4,16,5),
        array(16,5,13,6),
        array(13,6,12,7),
        array(12,7,9,8)
    ),
    with_variable(
        'line1',
        make_line (
            geometry (get_feature_by_id ('points', @element[0])), -- $id of point at bottom left
            geometry (get_feature_by_id ('points', @element[1]))  -- $id of point at bottom right
        ),
    with_variable(
        'line2',
        make_line (
            geometry (get_feature_by_id ('points', @element[2])),  -- $id of point at top left
            geometry (get_feature_by_id ('points', @element[3]))  -- $id of point at top right
        ),
    collect_geometries (
    array_foreach (
        generate_series (1,@no),
        make_polygon(
            make_line(
                end_point(
                    line_substring (
                        @line1,
                        0,
                        length(@line1)/@no*(@element-1)
                    )
                ),
                end_point(
                    line_substring (
                        @line1,
                        0,
                        length(@line1)/@no*@element
                    )
                ),
                end_point(
                    line_substring (
                        @line2,
                        0,
                        length(@line2)/@no*@element
                    )
                ),
                end_point(
                    line_substring (
                        @line2,
                        0,
                        length(@line2)/@no*(@element-1)
                    )
                )       
))))))))
end

)

Babel
  • 71,072
  • 14
  • 78
  • 208
  • Thank you! Is id the same as fid? I have fid instead of id. – s_o_c_account May 09 '23 at 20:04
  • 1
    You can use fid, but then you have to replace $id by fid in the expression. $id is often the same as fid, but fid is a field containing unique values. For Geopackage, you need such a field, whereas for Shapefiles, there's no need for such a field. $id, however, exists for all kind of data and is the (internal) unique numbering of the features. For that reason, I used $id, as it exists in any case, whereas fid does not (or might have different names, as id, uid etc.) – Babel May 09 '23 at 20:08
  • See https://docs.qgis.org/latest/en/docs/user_manual/expressions/functions_list.html#expression-function-record-and-attributes-id - this mentions that for newer versions, better use @id instead of the older $id – Babel May 09 '23 at 20:10
  • It still didn't work, sent you a pm. – s_o_c_account May 09 '23 at 20:20