4

What I want to do :

This question is about finding an equivalent path on a grid to a given line. The following image shows what I am trying to achieve : Starting from a generic line (in red), I want to get the equivalent path which is snapped on a grid. In red, the line i am starting from, and in blue what I would like to get


Why I want to do it

The grid is supposed to represent a raster. I am currently toying with a cellular automata model which simulates the run-off of fallen rain on a DEM (digital elevation model). I have pretty big cell sizes (usually around 10 meters) and I would like to account for linear walls on my domain, which greatly impact the way the water moved through the DEM. The red line corresponds to the location of such a wall. Obviously, since the cells are quite big, I can't simply rasterize the vector line since it would give the wall a 10 m-width. That is why I would like to modify the water fluxes between neighboring cells. To achieve that, I need to determine this blue line which is snapped to the cell edges.

What I did so far

First, I did a lot of googling, but I am relatively new to the manipulation of geodata, and to this king of data processing. I am quite sure this is a well-documented "problem" with well-known solutions, but I don't know how to formulate this issue better than with showing what I am looking for. My first ideas were to create additional points along the line and to snap them on a grid which matches the raster's cells edges : My attempt Before investing too much time on a junk code which may not work, I would like to know if there already are solutions out there. Usually, I prepare my data with QGIS, or with python, that's why ideally I'm interested in any QGIS processing ( or consecutive processings) which would do the tricks and/or python libraries which could do that.

If you only have vague ideas of ideas to explore I also am interested.

Similar questions on gis.stackexchange

How to snap a road network to a hexagonal grid in QGIS?

3
  • try overlay_nearest like here gis.stackexchange.com/a/400725/276
    – Mapperz
    Commented May 24 at 17:21
  • "Obviously, since the cells are quite big, I can't simply rasterize the vector line since it would give the wall a 10 m-width" If your cells are 10m, and your cellular automata presumably operates at this very resolution, why would rasterising the line to the same 10m resolution be a problem? At some point you will have a limitation of scale. Commented May 27 at 4:49
  • You are right : at some point, a limitation of scale is unavoidable. So you have to choose what has to be represented. The thing is, walls really are adequately represented by linear vector data. Especially in urban areas, you can't give a 10 m width to the walls : there is not enough space around. A 10 m length can easily be the width of a street.
    – TC_Blue
    Commented May 27 at 13:22

3 Answers 3

3

Use the Create grid tool to create a point grid with the same extent as your raster and horizontal and vertical spacing equal to the cell/pixel sizes of your raster. (Note if your line goes to the lower or right edges of the raster, you'll need to manually increase the xmax and decrease the ymin extent coordinates by the width/height of one pixel as the points are only created on the top left of a pixel).

Then use the Snap geometries to layer to snap your lines to your points grid, with the tolerance parameter set to the pixel size (or maximum if the pixel width and height are different).

For example, I have a 100m raster with the extent (xmin, xmax, ymin, ymax) of 18702643, 18704543, -5523042, -5522242 and a line.

enter image description here

I create a point grid with 100m spacing and increased xmax and decreased ymin by 100m:

enter image description here

enter image description here

Then I snapped the lines to the point grid:

enter image description here

enter image description here

1
  • 1
    Thank you very much, that seems to be exactly what I was looking for ! I've been playing a little bit with the different parameters. For future users, my advices are : 1) Use (Processing Toolbox/Vector Geometry/) Densify by interval on your line geometry with an interval close to the cell size, and 2) The behavior of Snap Geometries to Layer should be set to : " Prefer closest point, insert extra vertices where required"
    – TC_Blue
    Commented May 27 at 13:54
1

Densify the line, than snap each vertex to the closest corner of the cell grid an re-connect the points to a line. Best first delete all grid cells that do not intersect the line to make processing faster.

  1. Densify the line. Use a value small enough - in my case, 12.5 times smaller than the cell size (cell size: 1 m; densify distance: 0.08 m).
  2. Convert the grid cells to vertices to get the corners of the grid only (ore use a point grid from the start).
  3. Snap the points from step 1 to the points from step 2.
  4. Re-connect the points in the initial order to a line. You might want to run Remove duplicate vertices to the resulting layer.

You can do this step by step (or automatized in a model), using the dedicated algorithms or you could also do so in one step by using this expression with Geoemtry Generator or Geometry by expression:

simplify ( 
    make_line(
        array_foreach(
            geometries_to_array(
                nodes_to_points (
                    densify_by_distance( @geometry,0.08) 
                )
            ),
            closest_point (
                aggregate( 
                    'gridlines', 
                    'collect',
                    nodes_to_points (@geometry) 
                ),
                @element
            )
        )
    ),
    0.08
)

enter image description here

0

Use network tool shortest path along the edges of the grid:

  1. Select the grid cells (dotted lines on the screenshot) that intersect the line (blue) with Select by Location (yellow cells are selected). This is to make calculation more efficient.
  2. Run Polygons to lines for the selected cells (black solid line).
  3. Run Shortest Path (point to point) from the start-point of the line to the end point, using the grid lines from step 2 as network.

You get the red line as result:

enter image description here

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.