## 2014-11-08

### Create Trapezoidal Buffered Areas from Line

ラインから台形状のバッファーエリアを作成

このスレッドからの続き。
FME Community Answers > Is it possible to create a " trapezoids" shaped line buffer?

It's an interesting subject.
I tried replacing the procedure except the Dissolver with a concise Python script.
For what it's worth.

Dissolver以外の処理手順を簡潔なPythonスクリプトに置き換えてみました。

-----
# Script Example for PythonCaller
# Creates Trapezoid Buffered Areas for Each Line Segment.
# Assumes input feature geometry is a Line.
import fmeobjects, math

class TrapezoidBufferer(object):
def input(self, feature):
rb = float(feature.getAttribute('_beg_width')) * 0.5
re = float(feature.getAttribute('_end_width')) * 0.5
k = (re - rb) / float(feature.performFunction('@Length()'))
coordSys = feature.getCoordSys()
coords = feature.getAllCoordinates()
if feature.getDimension() == fmeobjects.FME_THREE_D:
coords = [(x, y) for (x, y, z) in coords]
x0, y0, measure = coords[0][0], coords[0][1], 0.0
g0 = fmeobjects.FMEEllipse(fmeobjects.FMEPoint(x0, y0), rb, rb, 0.0, 0)
for x1, y1 in coords[1:]:
measure += math.hypot(x1 - x0, y1 - y0)
rm = rb + k * measure
g1 = fmeobjects.FMEEllipse(fmeobjects.FMEPoint(x1, y1), rm, rm, 0.0, 0)
geom = fmeobjects.FMEAggregate()
geom.appendPart(g0)
geom.appendPart(g1)
hull = feature.cloneAttributes()
hull.setCoordSys(coordSys)
hull.setGeometry(geom)
hull.performFunction('@ConvexHull()')
self.pyoutput(hull)
x0, y0, g0 = x1, y1, g1
-----

The script transforms a polyline into multiple polygons like this image. To get final geometry, dissolve them with a Dissolver.
このスクリプトはひとつのポリラインを図のような複数のポリゴンに変換します。最終的なジオメトリを得るには、これらをDissolverでディゾルブします。

FME 2014 SP4 build 14433

=====
Really interesting :)

=====
2014-11-10: I didn't think that "dissolving" can be performed with the Python FME Objects API. Probably that's true but I noticed that the required result can be generated by "buffering with specifying 0 as amount" against an aggregate geometry, in this case.
「ディゾルブ(dissolving)」は Python FME Objects API でできるとは思っていませんでした。おそらくそれはその通りでしょうが、このケースでは、集約ジオメトリ(aggregate)に対する「バッファ量0のバッファリング(buffering)」によって求められる結果が得られることに気がつきました。
-----
# Script Example for PythonCaller
# Creates a Tapered Buffer Area for a Line.
# Assumes input feature geometry is a Line.
import fmeobjects, math

class TaperLineBufferer(object):
def input(self, feature):
rb = float(feature.getAttribute('_beg_width')) * 0.5
re = float(feature.getAttribute('_end_width')) * 0.5
k = (re - rb) / float(feature.performFunction('@Length()'))
coords = feature.getAllCoordinates()
hullCollection = fmeobjects.FMEAggregate()
x0, y0, measure = coords[0][0], coords[0][1], 0.0
g0 = fmeobjects.FMEEllipse(fmeobjects.FMEPoint(x0, y0), rb, rb, 0.0, 0)
for coord in coords[1:]:
x1, y1 = coord[0], coord[1]
measure += math.hypot(x1 - x0, y1 - y0)
rm = rb + k * measure
g1 = fmeobjects.FMEEllipse(fmeobjects.FMEPoint(x1, y1), rm, rm, 0.0, 0)
geom = fmeobjects.FMEAggregate()
geom.appendPart(g0)
geom.appendPart(g1)
hull = fmeobjects.FMEFeature()
hull.setGeometry(geom)
hull.performFunction('@ConvexHull()')
hullCollection.appendPart(hull.getGeometry())
x0, y0, g0 = x1, y1, g1
feature.setGeometry(hullCollection)
feature.buffer(0.0, 0.0) # dissolve parts
self.pyoutput(feature)
-----
Like a strange living thing...
ヘンな生き物のような...

I published a custom transformer named "TaperLineBufferer" in the FME Store, which  has been implemented based on the Python script.
このPythonスクリプトに基づいて実装した"TaperLineBufferer"という名前のカスタムトランスフォーマーを FME Store で公開しました。