Solved

Progressively Combine Line Segments to Create new Cumulative Lines

  • 22 April 2021
  • 6 replies
  • 21 views

Badge

I'm properly stumped and would love some thoughts on this one.

 

I'm taking a collection of GPS points that make up a track. I've taken these points and sequenced them and created line separate line segments (strictly 2 points). These segments now span the length of the track and they have been sequenced with an ID in the order they occur (based on timestamp).

 

I'd like animate these lines in a stop motion/claymation fashion. And show a cumulative line segment (in order to reduce the number of features) and assign a frame identifier that dictates the frame in which to show/reveal the feature.

 

So far, I've been using the Cloner and setting the number of copies as the ID of the feature and assigning the output clones a _copynumber. This results in large volume of features that I can then combine using the LineCombiner and grouping based on the _copynumber. This works but it's not very efficient. Due to the number of segments in the tracks the number of features obviously quickly balloons when my translation hits the Cloner.

 

Would love to know if there's a more efficient method that would allow me to process larger portions of my input data at once.

FME_AnimationProcessing3

icon

Best answer by warren156 23 April 2021, 17:59

View original

6 replies

Badge +5

growing lineHow about using variables to store the geometry after every point is added

 

Badge +5

growing lineHow about using variables to store the geometry after every point is added

 

Let me know if you want that workspace. The CoordinateExtractor is getting index 1 of the line, the new point to be added to the line.

Badge +5

growing lineHow about using variables to store the geometry after every point is added

 

As a custom transformer:

growing line

Badge +2

Hi,

I'm not specially keen on using Python in FME, but this is definitely something to consider when looking for performance.

Here is the capture (can't figure out how to resize sorry 😉 ) of a workspace operating directly from the input points.

workspaceIt takes 3 seconds to process 10000 points on my laptop, and preserves input point attributes.

The first point is also output as a point, but you can easily filter it out.

Here is the Python code, which is pretty simple :

import fme
import fmeobjects
 
class LineMotionBuilder(object):
 
    def __init__(self):
        # Initialize with Null Line
        self.line = fmeobjects.FMELine()
 
    def input(self, feature):
        # append current point to existing line
        self.line.appendPoint(feature.getGeometry())
        # set feature's geometry to current line
        feature.setGeometry(self.line)
        # output current feature with updated geometry
        self.pyoutput(feature)
 
    def close(self):
        pass
 
    def process_group(self):
        pass

And the workspace is attached.

You might want to improve it by including group processing, should you want to process multiple series of points (I suspect resetting self.line to Null when changing group should do the trick).

Regards,

Fred

Badge

Hi,

I'm not specially keen on using Python in FME, but this is definitely something to consider when looking for performance.

Here is the capture (can't figure out how to resize sorry 😉 ) of a workspace operating directly from the input points.

workspaceIt takes 3 seconds to process 10000 points on my laptop, and preserves input point attributes.

The first point is also output as a point, but you can easily filter it out.

Here is the Python code, which is pretty simple :

import fme
import fmeobjects
 
class LineMotionBuilder(object):
 
    def __init__(self):
        # Initialize with Null Line
        self.line = fmeobjects.FMELine()
 
    def input(self, feature):
        # append current point to existing line
        self.line.appendPoint(feature.getGeometry())
        # set feature's geometry to current line
        feature.setGeometry(self.line)
        # output current feature with updated geometry
        self.pyoutput(feature)
 
    def close(self):
        pass
 
    def process_group(self):
        pass

And the workspace is attached.

You might want to improve it by including group processing, should you want to process multiple series of points (I suspect resetting self.line to Null when changing group should do the trick).

Regards,

Fred

To be honest, I've been aware of being able to call python before, during, and after workbenches but I can count on one hand the times I've actually done it. This is nearly exactly what I was looking for, and I've made a few adjustments to adapt it to my needs.

 

I'm reading multiple GPS tracks (tag_id) and I've also summarized movement and aggregated these to cumulative movement over the course of a day (frame_id).

 

Thanks so much for taking a look and offering a suggestion!

 

# edit 1: sorted incoming features by timestamp
# edit 2: implemented GroupBy on the PythonCaller using a tag_id and frame_id identifying individual GPS tag trackers (identify separate tracks)
# edit 3: moved python line appending logic to the process_group function so features are read as a group
# edit 4: converted features to lines to I used appendLine()
# edit 5: set the pyoutput as the last feature in the list to represent the maximum longest cumulative line for that frame
 
class LineMotionBuilder(object):
 
    def __init__(self):
        # Initialize with Null Line
        self.line = fmeobjects.FMELine()
        self.feature_list = []
 
    def input(self, feature):
        # append feature to list
        self.feature_list.append(feature)
 
    def close(self):
        pass
 
    def process_group(self):
        for feature in self.feature_list:
            # append current point to existing line
            self.line.appendLine(feature.getGeometry())
            # set feature's geometry to current line
            feature.setGeometry(self.line)
        # output the last feature for the unique playback day
        self.pyoutput(self.feature_list[-1])
        self.feature_list = []
        self.line = fmeobjects.FMELine()

FME_LineAnimation2

Badge

As a custom transformer:

growing line

Thanks so much for offering your suggestion! I checked it out but ultimately opted for the python implementation purely because I could wrap my head around it and adapt it a little easier 😄. Sometimes FME processing one-feature-at-a-time and trying to craft transformers to circumvent that can be tricky.

Reply