# How can I detect even terrain in geometry nodes?

I'm trying to scatter an object on terrain using geometry nodes. The only problem is I want to only scatter if the surrounding terrain is even. I'm not talking about the angle of the normal; I want the surrounding area to be relatively flat. I've tried to use the blur node to detect, but nothing has worked so far.

Here is a photo the terrain, if that helps.

The goal is that, given a vertex, it can somehow find how flat the surrounding area is.

• Some mockup or illustration would be helpfull to better understand ... btw how is the terrain generated? Especially mentioned flat part of the mesh? Nov 11, 2023 at 17:13
• Sure I'll add some more info, in a minute, but its generated based on a few procedural textures as a heightmap. The goal is that given a vertex, it can somehow find how flat the surrounding area is. Nov 11, 2023 at 17:16
• Can you mark (paint) the areas you count as flat? I'm guessing you dont want to use normal angle since it will scatter objects on top of hills ... probbably you can use just the elevation? Or there will be flat areas in higher elevations? Nov 11, 2023 at 17:29
• The reason I don't want to only use the normal is that a point can have a normal facing up, but still not be on even terrain. I want to check if the height is nearby is around the same height as the point. For example, I might want to scatter a tree with a thick stump. If it happened to scatter next to a hill, it would clip in. Nov 11, 2023 at 17:36

If you want to keep some distance from uneven terrain, you can use the Shortest Edge paths node, as it can give you the shortest path through edges to vertices defined as an end vertex. This method performs better in a geometry with high resolution and with faces that don't differ much in size

First you need to define what is uneven geometry, I just check if the dot product between the normal and the vector $$(0, 0, 1)$$, or just the $$Z$$ component of the normal, is less than $$0.95$$:

Then you use that selection as end vertex of the Shortest Edge paths node and the edge length as the edge cost, using the total cost (distance travelling through edges) to select which faces will have points distributed:

Node tree:

Update:

With the node tree above, no points are distributed when there's no uneven terrain. To solve that, if you have a single mesh island, check if there's any uneven terrain using the Attribute Statistic node:

Or, if you have multiple mesh islands, check if each has any uneven terrain:

• I love this answer, just tried it and it works very well. I didn't know about shortest edge paths. Is that some kind of pathfinding? Thank you very much Nov 11, 2023 at 22:23
• @JackJamison The node's algorithm is the Dijkstra's algorithm, as stated by its documentation. Nov 11, 2023 at 22:33
• I am trying it out and it works pretty well, but when there are no positions that are too steep the selection is blank. I've tried to fix it with an or equal to zero, but it didn't work. Any ideas? Nov 11, 2023 at 23:00
• @JackJamison see edit. Nov 11, 2023 at 23:16
• It works great, thank you Nov 12, 2023 at 0:33

Simple terrain sample ...

You can try to get selection from Edge Angle node ...

• Thanks for the response, but my terrain doesn't have any exactly flat areas. The goal is that it can detect roughly flat areas to scatter on Nov 11, 2023 at 17:44
• See edit ... Probably some search for selection based on angle between two faces like the "Edge Angle" node ... but it means if there will be a side of the hill with straight wall with faces in low angle it would be taken into account, so I'm not sure if there is something that can cover it ... that is why I asked you if just low elevation can be used. Nov 11, 2023 at 20:00

I would do it like this: first use a Capture Attribute node set to Vector and Face to get the normals of the faces.

Plug the Attribute output into a Vector Math node set to Dot Product, as the second vector you use 0/0/1, that is the pointing upwards in Z direction which would be perfectly horizontal.

Now the dot product returns 1, when both vectors point in the same direction (in this case upwards) and lower values when they differ from each other. So now with a Math node set to Less Than you can set a threshold how much deviation from the perfectly flat you will accept. Values less than the threshold will result in a Boolean value of 1, which you plug into a Delete Geometry node. This helps you see which areas now remain as flat.

Now some of the remaining mesh islands might be flat, but too small and you do not want to distribute points there. So you take Face Area node and a Mesh Island node's Island Index output and plug them into an Accumulate Field node set to Face. Then plug the Total output into another Less Than node and the result in another Delete Geometry node, to delete mesh islands that are smaller than the threshold you've set in the Less Than.

The remaining mesh you can now plug into a Distribute Points on Faces node. The resulting points you combine with the original landscape mesh through a Join Geometry node and that's it. You can later decide how flat it should be or how large the islands.

By the way, the face area threshold cannot really distinguish if an area is large enough in length and width, so a very long thin strip of flat terrain will be possible, too.

• Hey, this looks good. I'm going to try it out in a little bit and let you know. Thank you Nov 11, 2023 at 19:55