Skip to main content

Hi,

I'm trying to transfer attributes from an 'inaccurate' set of points to another 'accurate' one, however I'd like to limit canditates (or bases) to have a 1 to 1 relationship where if a candidate was already found as nearest neighbour to a base, then it is 'taken out of the pool' and not found again for another base.

In example below, I want to match A to 1 and B to 2, however 1 is closest to A and B thus gets assigned twice. If I change ports (Base<>Candidate) then I got opposite: 1 and 2 is assigned to B.

Is there a way of saying; if you already found A~1 then 1 is out of the pool and B~2 ?

Points have no common attributes to use for grouping by and there is 100's of thousands of those, hence finding nearest neighbour by location to assign correct attributes from incorrect geometry.

What version of FME are you using? I just tried it with a NeighborFinder in FME 2017 and it has the option to specify a max number of neighbors to find, so set that to 1 and for each base (points A and 😎 it will find the closest candidate (points 1 and 2) and then it appears to remove that candidate from consideration.

none2none.fmw

Hope this helps.


Hi @kkrajewski, if I understand the requirement correctly, this workflow might help you. $(NUM) must be an integer number greater than 0. Smaller $(NUM) could cause larger number of Failed features from the Tester.

0684Q00000ArLsgQAF.png

# PythonCaller Script Example
class FeatureProcessor(object):
    def __init__(self):
        self.pool = set(n])

    def input(self, feature):
        i = 0
        while True:
            id = feature.getAttribute('_candidates{%d}._cand_id' % i)
            if id == None:
                self.pyoutput(feature) # Unmatched
                break
            elif id not in self.pool: # "1 to 1" candidate found in the list.
                self.pool.add(id)
                feature.setAttribute('_list_index', i)
                self.pyoutput(feature) # Matched
                break
            else:
                i += 1


Hi @kkrajewski, if I understand the requirement correctly, this workflow might help you. $(NUM) must be an integer number greater than 0. Smaller $(NUM) could cause larger number of Failed features from the Tester.

0684Q00000ArLsgQAF.png

# PythonCaller Script Example
class FeatureProcessor(object):
    def __init__(self):
        self.pool = set(n])

    def input(self, feature):
        i = 0
        while True:
            id = feature.getAttribute('_candidates{%d}._cand_id' % i)
            if id == None:
                self.pyoutput(feature) # Unmatched
                break
            elif id not in self.pool: # "1 to 1" candidate found in the list.
                self.pool.add(id)
                feature.setAttribute('_list_index', i)
                self.pyoutput(feature) # Matched
                break
            else:
                i += 1

Forgot to mention. Assuming that "Generate List" is checked and "_candidates" is set to the Closest Candidate List Name parameter in the NeighborFinder.

 

 


What version of FME are you using? I just tried it with a NeighborFinder in FME 2017 and it has the option to specify a max number of neighbors to find, so set that to 1 and for each base (points A and 😎 it will find the closest candidate (points 1 and 2) and then it appears to remove that candidate from consideration.

none2none.fmw

Hope this helps.

@redgeographics Using 2016.1 in this instance.

 

I believe that you were lucky in that situation with positions of A & B with relation to 1 & 2. If you reverse bases and candidates in your workspace, then A comes out unmatched and both 1 & 2 are matched to B. Checked in both 2016.1 and 2017.0 (v14 & v15 of NeighborFinder).
@redgeographics Using 2016.1 in this instance.

 

I believe that you were lucky in that situation with positions of A & B with relation to 1 & 2. If you reverse bases and candidates in your workspace, then A comes out unmatched and both 1 & 2 are matched to B. Checked in both 2016.1 and 2017.0 (v14 & v15 of NeighborFinder).
Swapping base and candidate features means you're doing a different comparison. I am assuming that A and B are the "accurate" points, so they're the bases, 1 and 2 are the candidates as they need to be matched to the bases.

 

 


Swapping base and candidate features means you're doing a different comparison. I am assuming that A and B are the "accurate" points, so they're the bases, 1 and 2 are the candidates as they need to be matched to the bases.

 

 

True. Using 'accurate' set as bases so that I have unique set of output points. But if spatial relationship is a bit different, two of 'accurate' bases will be attributed to same 'candidate' which is exactly what I don't want.

 

 


Hi @kkrajewski, if I understand the requirement correctly, this workflow might help you. $(NUM) must be an integer number greater than 0. Smaller $(NUM) could cause larger number of Failed features from the Tester.

0684Q00000ArLsgQAF.png

# PythonCaller Script Example
class FeatureProcessor(object):
    def __init__(self):
        self.pool = set(n])

    def input(self, feature):
        i = 0
        while True:
            id = feature.getAttribute('_candidates{%d}._cand_id' % i)
            if id == None:
                self.pyoutput(feature) # Unmatched
                break
            elif id not in self.pool: # "1 to 1" candidate found in the list.
                self.pool.add(id)
                feature.setAttribute('_list_index', i)
                self.pyoutput(feature) # Matched
                break
            else:
                i += 1

Now I only need to find out how to 'intelligently' order the data on input when Nearest Neighbour isn't a correct answer, as in picture below:

 

0684Q00000ArMohQAF.png

Green lines show current FME assignment. Arrows show desired output. Red become unmatched.

 

 


@kkrajewski

It is possible to create a iterative neighbor finder with the options to either keep candidate and or bases.

It searches by incremental steps..and optionally removes found pairs from the next round

The customtrnasforemer

and the blocking transformer within the customtransformer

I built it in fme2015 it think. But it still works, also in fme2017.

I have a version that has as an option to keep bases as well, but it is noticeably slower then just the candidate option.


Reply