I have a workflow in FME where I need to iteratively buffer a feature and check for neighbours, until no neighbour is found.
The logic I want is roughly this:
Buffer the feature by 10 m
Use NeighborFinder to check if any neighbour exists
If a neighbour is found, increase the buffer by 5 m
Check again with NeighborFinder
Repeat (increase buffer by 5 m each time)
Stop when no neighbour is found and output that feature
So the buffer distance sequence would be something like:
10 m → 15 m → 20 m → 25 m → … until no neighbour exists
What is the recommended way in FME to build this kind of iterative / looping buffer logic?
Thanks in advance!
Best answer by geomancer
You can do this without looping, and without iterations, by processing all buffers at once, and after that determine the buffer that fulfills your requirements. Something like this:
Determine the number of buffers to create (based on the distance to the furthest candidate, or just set a number)
Create all buffers
Use NeighborFinder with the buffers as Base and the neighbors as Candidates, treat polygons as Areas, and generate a list of the candidates
For each buffer, determine the index of the first list item with a distance greater than 0 (because NeighborFinder is set to treat polygons as Areas, all candidates inside the buffer get distance 0)
When serveral buffers have the same index value, the smallest of these buffers is the buffer you are looking for.
See the attached workspace (FME 2023.1). It's not fit for production, but it may give you an idea. Good luck!
@max_h when I use the neighbor finder in the looper i get an error. Any idea?
Loop to Looping_Looped1765832145 Input Splitter (BranchingFactory): Transformer/Factory Looping_NeighborFinder is blocking and cannot be used in a loop, but was found between 'Loop to Looping_Looped1765832145 Input Splitter' and 'Looping_Looped1765832145 Input Splitter'
My bad, didnt know neighbourfinder is blocked in a loop.
As you only want to know if there is any feature nearby, maybe a SpatialFilter with "Filter OGC-Contains Candidate" "Filter OGC-Equals Candidate" "Filter OGC-Touches Candidate" "Filter OGC-Intersects Candidate" (depending on what geometry your features have)
And whenever something gets out of the passed port you loop again and you stop when the passed port is empty (NoFeaturesTester helps here)
Why the looping? You can set a maximum distance on the NeighborFinder, it will give you the first (closest) result and the distance (to the original candidate), so everything you’re hoping to find with the iterative buffers can be done with the stock NeighborFinder.
In fact, if you use your buffers as candidate the NeighborFinder will still find results that are outside the buffers, making it a bit of an awkward solution.
Why the looping? You can set a maximum distance on the NeighborFinder, it will give you the first (closest) result and the distance (to the original candidate), so everything you’re hoping to find with the iterative buffers can be done with the stock NeighborFinder.
In fact, if you use your buffers as candidate the NeighborFinder will still find results that are outside the buffers, making it a bit of an awkward solution.
As I understood he is interested in the first n*10m buffer-area without a neighbour
Why the looping? You can set a maximum distance on the NeighborFinder, it will give you the first (closest) result and the distance (to the original candidate), so everything you’re hoping to find with the iterative buffers can be done with the stock NeighborFinder.
In fact, if you use your buffers as candidate the NeighborFinder will still find results that are outside the buffers, making it a bit of an awkward solution.
As I understood he is interested in the first n*10m buffer-area without a neighbour
Exactly. Simply using NeighborFinder doesn’t help. I need to find the first n×10 m buffer area along the line that has no neighbours. If there is no neighbour, I will create a point there—the rule is that there must not be any other points nearby. I thought using a loop might be the way to go.
You can do this without looping, and without iterations, by processing all buffers at once, and after that determine the buffer that fulfills your requirements. Something like this:
Determine the number of buffers to create (based on the distance to the furthest candidate, or just set a number)
Create all buffers
Use NeighborFinder with the buffers as Base and the neighbors as Candidates, treat polygons as Areas, and generate a list of the candidates
For each buffer, determine the index of the first list item with a distance greater than 0 (because NeighborFinder is set to treat polygons as Areas, all candidates inside the buffer get distance 0)
When serveral buffers have the same index value, the smallest of these buffers is the buffer you are looking for.
See the attached workspace (FME 2023.1). It's not fit for production, but it may give you an idea. Good luck!