Consider creating a line geometry based on a list attribute containing coordinates.

Assuming that the input feature has no geometry, but has a list attribute like this.

_coord{}.x

_coord{}.y

_coord{}.z

TclCaller with this compact script creates a 2D line geometry from the list.

-----

proc createLine {} {

for {set i 0} {[FME_AttributeExists "_coord{$i}.x"] == 1} {incr i} {

set x [FME_GetAttribute "_coord{$i}.x"]

set y [FME_GetAttribute "_coord{$i}.y"]

FME_Coordinates addCoord $x $y

}

}

-----

Fine.

Then, create a 3D line. I expected this script would work fine as well.

-----

proc create3DLine {} {

FME_Coordinates dimension 3

for {set i 0} {[FME_AttributeExists "_coord{$i}.x"] == 1} {incr i} {

set x [FME_GetAttribute "_coord{$i}.x"]

set y [FME_GetAttribute "_coord{$i}.y"]

set z [FME_GetAttribute "_coord{$i}.z"]

FME_Coordinates addCoord $x $y $z

}

}

-----

But it failed unfortunately. Created line was still in 2D, Z-values were missing.

It seems that "dimension" option of FME_Coordinates command is invalid when the feature has no geometry. If I set dimension to 3D after creating line, every Z-value becomes 0 although the line becomes 3D. It works like the 3DForcer transformer, but is not the expected functionality.

A workaround I found is: Add a dummy coordinate, set dimension to 3D, and remove the dummy coordinate before creating a line.

*Note: There is more appropriate workaround as after-mentioned*

*(2013-12-14).*

-----

proc create3DLine {} {

FME_Coordinates addCoord 0 0 0

FME_Coordinates dimension 3

FME_Coordinates resetCoords

for {set i 0} {[FME_AttributeExists "_coord{$i}.x"] == 1} {incr i} {

...

}

}

-----

It worked, but I don't like wasting steps for the dummy coordinate.

I expect the geometry to become 3D automatically when Z is given as the third argument for "FME_Coordinates addCoord".

=====

2013-12-14

I had requested Safe support about this problem; they provided a more appropriate workaround. That is, to set a geometry type beforehand.

If I set both geometry type and dimension like this, a 3D line will be created expectedly. It seems that "dimension" option will be valid after setting geometry type.

This is more desirable script. Thanks, Dan@Safe.

-----

proc create3DLine {} {

FME_Coordinates geomType fme_line

FME_Coordinates dimension 3

for {set i 0} {[FME_AttributeExists "_coord{$i}.x"] == 1} {incr i} {

...

}

}

=====

For geometric operations, FME_Execute procedure can be also used. FME_Execute calls an FME Function directly.

"Close" function, for example, can be used to change a line to a polygon when the line consists of 3 or more coordinates. It's similar to the LineCloser transformer.

Just append a line to the procedure like this.

-----

proc createPolygon {} {

for { ...

...

}

FME_Execute Close

}

-----

There are many FME Functions for geometric operations. If we could see detailed documentations about them, Tcl could be used much more effectively.

I remember that we could see the documentation "FME Functions and Factories" a few years ago, but it cannot be accessed now (2013-12-07).

FMEpedia > Documentation: FME Functions and Factories

...so, my answer to the title is maybe a little negative, currently.

(FME 2013 SP4 Build 13547)

=====

2014-03-21: I discovered that the documentation has been enabled. So I now change my answer to the title into "positive"!

> FME Factory and Function Documentation

=====

2013-12-14: Found another way to change an unclosed line to a polygon.

FME_Coordinates procedure with "geomType" option can be also used to do that.

If I set explicitly the geometry type to "fme_polygon" before or after creating an unclosed line, then the line will be closed automatically and the resultant geometry will be a polygon.

-----

FME_Coordinates geomType fme_polygon

-----

There seems to be many things which are not told in published documentations.

=====

2013-12-08: For comparison...

-----

# Python Script Example: Create 2D Line

import fmeobjects

def createLine(feature):

xs = feature.getAttribute('_coord{}.x')

ys = feature.getAttribute('_coord{}.y')

coords = [(float(x), float(y)) for x, y in zip(xs, ys)]

feature.setGeometry(fmeobjects.FMELine(coords))

-----

# Python Script Example: Create 3D Line

import fmeobjects

def create3DLine(feature):

xs = feature.getAttribute('_coord{}.x')

ys = feature.getAttribute('_coord{}.y')

zs = feature.getAttribute('_coord{}.z')

coords = [(float(x), float(y), float(z)) for x, y, z in zip(xs, ys, zs)]

feature.setGeometry(fmeobjects.FMELine(coords))

-----

# Python Script Example: Create 3D Polygon

import fmeobjects

def createPolygon(feature):

xs = feature.getAttribute('_coord{}.x')

ys = feature.getAttribute('_coord{}.y')

zs = feature.getAttribute('_coord{}.z')

coords = [(float(x), float(y), float(z)) for x, y, z in zip(xs, ys, zs)]

boundary = fmeobjects.FMELine(coords)

feature.setGeometry(fmeobjects.FMEPolygon(boundary))

-----

Of course FME Transformers without any scripting can do those operations.

I think a general approach will be like this.

ListExploder --> 2D/3DPointReplacer --> PointConnector (--> LineCloser

2013-12-15: corrected a typo of "LineCloser". sorry.

## No comments:

## Post a Comment