Skip to main content

Hello all,

 

As far as I can tell the "Snapping Distance" param for the Snapper and the "Tolerance" param for the Intersector have to be hard coded or a workspace param. ie. They need to be known before the workspace runs.

It would be really useful to have these values calculated within the workspace as the snapping distance/tolerance may depend on the data being processed. ie. It would be nice to be able to set the snapping distance from an attribute and the Snapper uses the value from the attribute of the first feature of each group entering the Snapper.

Is this, or some variant, currently possible? I am considering splitting the workspace into two workspaces and having the first one calculate the value then calling the second one, however it would be much more convenient to be able to do the calculation of the snapping distance in the same workspace.

 

Any assistance is appreciated.

 

Thanks

 

Michael Pascoe

cc: @deanhowell​ , @luke.giles​ 

Good observation and you are correct. I took a deeper look at this does have to be known at "workspace parse time". Can't come up with any better workaround than your suggestion of a splitting and using a workspace runner to run a child workspace that does that actual snapping. Sorry about this. If you feel like braving the all new Ideas board here, maybe you could add this to see if others also could want the same thing?


Good observation and you are correct. I took a deeper look at this does have to be known at "workspace parse time". Can't come up with any better workaround than your suggestion of a splitting and using a workspace runner to run a child workspace that does that actual snapping. Sorry about this. If you feel like braving the all new Ideas board here, maybe you could add this to see if others also could want the same thing?

Well, I just ventured into the all new ideas area here and low and behold, there it is. https://community.safe.com/s/idea/0874Q000000TlF8QAK/detail

 

Seems like the points go up by 10s in this new world as opposed to going up just one at a time, so I'm sure these ideas are really going to be getting our attention now 😁


Well, I just ventured into the all new ideas area here and low and behold, there it is. https://community.safe.com/s/idea/0874Q000000TlF8QAK/detail

 

Seems like the points go up by 10s in this new world as opposed to going up just one at a time, so I'm sure these ideas are really going to be getting our attention now 😁

Thanks @Dale Lutz​ ,

I've upvoted that idea. Hopefully it gets enough momentum.

Michael


I think a key reason we don't allow selection from an attribute is that it could then vary between features.

For example, feature A has a tolerance of 2 and feature B has a tolerance of 1. They are 1.5 apart. Should they snap?

Ah - I see your comment on the idea. Yes, the first feature sets the snap tolerance is probably what we'd go with in this scenario. Let's hope that idea gets some upvotes and is implemented.


Once upon a time I wrote a custom transformer that allowed for the anchor snapper distance to be set by an attribute. Different features could have different distances.

 

It involved using fmeobjects.FMEFactoryPipeline in a pythonCaller.

 

@larry​ has a good breakdown of the process for a SpatialRelator and Chopper, the anchoredSnapper would be similar.

 

https://community.safe.com/s/question/0D54Q000080hSCkSAM/check-the-spatial-relationship-with-a-pythoncaller


Once upon a time I wrote a custom transformer that allowed for the anchor snapper distance to be set by an attribute.  Different features could have different distances.

 

It involved using fmeobjects.FMEFactoryPipeline   in a pythonCaller.  

 

 @larry​ has a good breakdown of the process for a SpatialRelator and Chopper,  the anchoredSnapper would be similar.

 

https://community.safe.com/s/question/0D54Q000080hSCkSAM/check-the-spatial-relationship-with-a-pythoncaller

Hi @jdh​ ,

Thank you very much. That worked perfectly.

For anyone that hits a similiar situation, here is the PythonCaller code I used:

import fme
import fmeobjects
 
# Create a Snapper and call it using the value of the snapping_distance
# from the first feature receieved as the snapping tolerance. Used as the
# Snapper transformers does not normally allow the snappnig tolerance 
# to come from an attribute.
 
SNAPPER_FACTORY_TEMPLATE = """\
FACTORY_DEF {{*}} SnappingFactory                                      \
   FACTORY_NAME Snapper_2                                              \
   INPUT  FEATURE_TYPE Input                                           \
   SNAP_TYPE ALL                                                       \
   SNAP_TOLERANCE {snapping_tolerance}                                 \
   FLUSH_WHEN_GROUPS_CHANGE No                                         \
   OUTPUT_DEGENERATES_AS_COLLAPSED YES                                 \
   DO_NOT_STROKE_ARCS_FOR_VERTEX_SNAPPING                              \
   CLEANING_TOLERANCE AUTO                                             \
   OUTPUT SNAPPED FEATURE_TYPE Snapper_2_SNAPPED                       \
   OUTPUT UNTOUCHED FEATURE_TYPE Snapper_2_UNTOUCHED\
"""
 
class FeatureProcessor(object):
 
    def __init__(self):
        self.pipeline = None
        
    def input(self, feature):
        if self.pipeline is None:
            snappingDistance = float(feature.getAttribute("snapping_distance"))
            self.pipeline = fmeobjects.FMEFactoryPipeline("SnappingPipeline")
            snapperFactoryDefinition = SNAPPER_FACTORY_TEMPLATE.format(snapping_tolerance=snappingDistance)
            self.pipeline.addFactory(snapperFactoryDefinition)
        feature.setFeatureType("Input")
        self.pipeline.processFeature(feature)
        
    def close(self):
        if self.pipeline is not None:
            self.pipeline.allDone()
            resultFeature = self.pipeline.getOutputFeature()
            while resultFeature is not None:
                self.pyoutput(resultFeature)
                resultFeature = self.pipeline.getOutputFeature()

Then to use you just need to make sure the first feature to enter has a snapping_distance attribute set to the snapping tolerance you wish to use.

 

If you wish to change the config for the Snapper (eg use a snapping type other than Segment Snapping) just configure a Snapper how you want in a workspace, copy it and paste into a text editor. Then copy the resulting FACTORY_DEF into the SNAPPER_FACTORY_TEMPLATE variable above. If you wish to then customize any params based on attribute (as I have done with snapping_tolerance) above just update them in the String with the values you want.

 

Michael


Reply