2013-12-07

Middle Point of Curve

This is a frequent question.
Although there should be several ways, I think the following way is easiest.

1. General - Curve (Line, Arc, Path)
Calculate half length of the curve, then use the Snipper to create the middle point.
-----
Snipping Mode: Distance (Value)
Starting Location: <half length>
Ending Location: <half length>
-----
The Snipper outputs a point when "Ending Location" is equal to "Starting Location".
To calculate length of a curve, the LengthCalculator or @Length function (from FME Feature Functions) can be used in general.
=====
2014-09-17
There is "Distance (Percentage)" mode. You don't need to calculate the length.
-----
Snipping Mode: Distance (Percentage)
Starting Location: 50
Ending Location: 50
=====

2. Line Segment
Line segment is a special curve i.e. a straight line having only 2 end nodes; the CenterPointReplacer can be also used to get its midpoint.
The CenterPointReplacer creates center point of the bounding box, it's equivalent to midpoint if the original geometry is a straight line.

When testing for the Snipper method, I noticed the resultant coordinates could contain a slight computational error (very very slight, about 10-14 - 10-15 order in my testing). I guess that "FME stores all attributes as character strings" causes such a computational error.

I think such a very slight error will not be an issue in almost all the cases. But if it will be an issue, consider using a PythonCaller. Python could generate higher-precision result (but is not mathematically exact, computational error cannot be avoided).
-----
# Python Script Example: Replace Curve with Middle Point
# When input geometry is not a curve, do nothing.
# Measure length in 2D.
import fmeobjects
def replaceCurveWithMidpoint(feature):
    geom = feature.getGeometry()
    if isinstance(geom, fmeobjects.FMECurve):
        measure3D = False
        len = geom.getLength(measure3D) * 0.5
        geom.snip(fmeobjects.SNIP_DISTANCE, measure3D, len, -1)
        feature.setGeometry(geom.getStartPoint())
-----

(FME 2013 SP4 Build 13547)

No comments:

Post a Comment