I generated a grid with 300m spacing but the ids generated from top to bottom in sequential oder. How could I get in horizontal from left to right sequence.enter image description here



There is a more general expression to be used with all types of polygon-grid that can be generated by menu vector > resarch tools > create grid, be it rectangle, diamond or hexagon and indifferent of cell-size (see documentation for grid-creation: https://docs.qgis.org/3.10/en/docs/user_manual/processing_algs/qgis/vectorcreation.html#create-grid)

Just copy&paste this expression to where you want the grid-id to appear (be it as a text-label or as a separate field or updating the id-field, see below, original answer):

(round((maximum( y(centroid($geometry))) -
 y(centroid($geometry)) ) 
/ (range( y(centroid($geometry)))/ 
(count_distinct( ( y(centroid($geometry))),x(centroid($geometry)))-1))))*
(count_distinct( x(centroid($geometry)))) + 
(round ((x(centroid($geometry))
-  minimum( x(centroid($geometry))))
/ (range( x(centroid($geometry)))
/ (count_distinct( x(centroid($geometry)))-1)))+1)

enter image description here

Explanation: the expression calculates the horizontal (x-)distance (in coordinates) from every cell-centroid to the leftermost (minimum) centroid, let's call it the x-offset. This x-offset is divided by the horizontal distance between cells, getting a coninuous counting of column-numbers. Horizontal distance between cells is calculated as the range (total distance from highest to lowest centroid x-coordinat value) of x-coord- values, divided by the number of columns (using count_distinct expression: how many different x-values are there?). There must be subtracted 1 (if you have e.g. 27 columns, there are only 26 distances from centroid to centroid of neighboring cell). Now you have a numbering starting with 0, if you wish the first cell to start with 1, include a +1 in the expression. So we have the first part of the expression, let's call it as a variable "column_no". This first part looks like that:

round (
          (x(centroid($geometry)) -  minimum( x(centroid($geometry)))
      ) / 
          (range(x(centroid($geometry))) / 
          (count_distinct( x(centroid($geometry)))-1)

The result of "column_no" looks something like that: enter image description here

Now with a very similar approach you get the number of the rows (lines). I added a round()-expression to get integer-values. Due to the shape of diamond and hexagon, the rows go up and down - that's why I had to introduce a "group-by"-paramenter in the count_distinct-expression to group the cells that are exactly vertically above eacht other (i.e. that have the same x-value for their centroids) - only these should count as a new row, not the "half-rows" in-between. So the whole expression to get the value of the row-number (let's call it "row_no") is as follows:

   (  maximum( y(centroid($geometry))) - 
      y(centroid($geometry)) ) / 
      (range( y(centroid($geometry)))/ 
         ( y(centroid($geometry))),x(centroid($geometry)))-1)

The result of "row_no" looks something like that:

enter image description here

Otherwise (without the group-by-paramenter), you would have this result:

enter image description here

No combining the two calculations, you get something like in the next picture, with "column-no" in red, "row_no" in black:

enter image description here

Now it's easy to calculate a continuous counting, let's call "cell_id", starting on the upper left to the right and after the last cell of the first line starting again on the left of the next line. You just need the number of columns, let's call it "no_of_columns" with this expression:

(count_distinct( x(centroid($geometry))))

Now we can bring all together with this formula (paste the expressions form the steps explained above and you get the whole expression): cell_id = "row_no" * "no_of_columns" + "column_no"

Original answer:

You can use this expression to generate a new number for each cell, following a counting order as you wish it from the top left cell to the right and than down:

round((((x_min ($geometry) - x_min( geometry( get_feature_by_id (@layer, 1))))/( (x_max( geometry( get_feature_by_id (@layer,   (count_distinct( x_min( $geometry))-1)* (count_distinct( y_min( $geometry))) + 1   ))) - x_min (geometry( get_feature_by_id (@layer, 1))) )/ (count_distinct( x_min( $geometry))
)))+1 )
 ((y_max ( geometry( get_feature_by_id (@layer, 1))) - y_max($geometry))/( (y_max (geometry( get_feature_by_id (@layer, 1))) - y_min( geometry( get_feature_by_id (@layer, count_distinct( y_min( $geometry)))))) / (count_distinct( y_min( $geometry)))
)) * count_distinct( x_min( $geometry))))

It will work without any adaptation as long as you work on the layer that contains the polygon-grid and it will generate a continuous numbering of the cells (indifferent of the size of your cellsize, be it 100 x 100 km, 300 m * 700 m or whatever you use) starting form the top left cell and than following the order form left to right and from top to bottom, for as many columns and rows you have.

On the screenshot below I have used the expression to generate a label, but you could also use the expression to create a new field with the field-calculator to create a permanent new "cell_id"-value from left to right and from top to bottom. In the field-calculator, you could even update the fid with the expression so you don't need to create a new field as long as you don't need the original id-values any more.

See Screenshot: Open layer styling, labelling, Open Expression editor and paste the expression above.

enter image description here

| improve this answer | |

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