Some vertex lists can be automatically parsed by FME, if they conform to some standard such as WKT.
Could you please post an example of such a coordinate list here?
The solution depends on how the coordinates are listed in a text. Could you please post a sample text that illustrates the format of coordinates list?
Some vertex lists can be automatically parsed by FME, if they conform to some standard such as WKT.
Could you please post an example of such a coordinate list here?
@david_r thanks for getting back to me. Here's a list:
PLY/1,54.3671208915,10.1422463646
PLY/2,54.3700921435,10.1422584956
PLY/3,54.3700947237,10.1537959675
PLY/4,54.3693817722,10.1537945973
PLY/5,54.3693818426,10.1541095477
PLY/6,54.3688144656,10.1541084576
PLY/7,54.3688143977,10.1537935091
PLY/8,54.3671234716,10.1537838354
This is actually part of the metadata of a BSB file. The BSB reader in FME doesn't seem to pull in much of the file as attributes so I'm reading it in as a text file to access this data and using a stringsearcher to identify these coordinate pairs. So, this is part of a file with lots of different information in it.
The solution depends on how the coordinates are listed in a text. Could you please post a sample text that illustrates the format of coordinates list?
@takashi I've posted a sample below from one of the files. It's part of a BSB header so contains all the standard BSB header info but the BSB reader doesn't read this data in. Therefore I'm reading it in as a text file. I'm trying to extract the PLY polygons.
@david_r thanks for getting back to me. Here's a list:
PLY/1,54.3671208915,10.1422463646
PLY/2,54.3700921435,10.1422584956
PLY/3,54.3700947237,10.1537959675
PLY/4,54.3693817722,10.1537945973
PLY/5,54.3693818426,10.1541095477
PLY/6,54.3688144656,10.1541084576
PLY/7,54.3688143977,10.1537935091
PLY/8,54.3671234716,10.1537838354
This is actually part of the metadata of a BSB file. The BSB reader in FME doesn't seem to pull in much of the file as attributes so I'm reading it in as a text file to access this data and using a stringsearcher to identify these coordinate pairs. So, this is part of a file with lots of different information in it.
We'll need a bit more context, how is the list represented in your workspace?
@erinjayaustin
if they are ordered would a LineBuilder not suffice? Group by/connection break attribute = fme_feature_type
(make sure last coord = first coord of course) If they close they become polygons.
Â
We'll need a bit more context, how is the list represented in your workspace?
I'm using 2 string searchers to extract the x-coords and y-coords, which creates a list of the subexpression matches. I've attached an image of what the 2 lists look like for this feature.
I'm using 2 string searchers to extract the x-coords and y-coords, which creates a list of the subexpression matches. I've attached an image of what the 2 lists look like for this feature.
I'd like to plot the points (x-coord{n}.part,y-coord{n}.part).
Here's a possible solution using the PythonCaller:
def GeneratePolygon(feature):
    x_coords = xfloat(x) for x in feature.getAttribute('x-coord{}.part') or o]]
    y_coords = rfloat(y) for y in feature.getAttribute('y-coord{}.part') or t]]
    feature.addCoordinates(zip(x_coords, y_coords))
Add a LineCloser after the PythonCaller.
Here's a possible solution using the PythonCaller:
def GeneratePolygon(feature):
    x_coords = xfloat(x) for x in feature.getAttribute('x-coord{}.part') or o]]
    y_coords = rfloat(y) for y in feature.getAttribute('y-coord{}.part') or t]]
    feature.addCoordinates(zip(x_coords, y_coords))
Add a LineCloser after the PythonCaller.
Thanks. I'll give this a go and see how I get on.Â
Other approaches.
You can convert the two lists to a single structured list consisting of two members (e.g. "_coord{}.x" and "_coord{}.y") with the AttributeManager (Rename Action), then explode the list (ListExploder), create vertices (VertexCreator), build a line (LineBuilder) and finally close the line to form a polygon (LineCloser).
Alternatively, the JSONTemplater with this template expression creates a GeoJSON object representing a polygon. You can replace it with a polygon geometry using the GeometryReplacer (Geometry Encoding: GeoJSON).
let $xs := fme:get-list-attribute('x-coord{}.part')
let $ys := fme:get-list-attribute('y-coord{}.part')
return
{
    "type" : "Polygon",
    "coordinates" : a
        r
            for $i in (1 to count($xs))
            return Âxs:double($xsÂ$i]), xs:double($ys>$i])],
            fxs:double($xs11]), xs:double($ysb1])]
        ]
    ]
}
Here's a possible solution using the PythonCaller:
def GeneratePolygon(feature):
    x_coords = xfloat(x) for x in feature.getAttribute('x-coord{}.part') or o]]
    y_coords = rfloat(y) for y in feature.getAttribute('y-coord{}.part') or t]]
    feature.addCoordinates(zip(x_coords, y_coords))
Add a LineCloser after the PythonCaller.
Be aware that the script would throw an error If the Python Compatibility was set to 3.x. with Python 3.x, you should modify the last line. e.g.
    feature.addCoordinates(y(x, y) for x, y in zip(x_coords, y_coords)])
Other approaches.
You can convert the two lists to a single structured list consisting of two members (e.g. "_coord{}.x" and "_coord{}.y") with the AttributeManager (Rename Action), then explode the list (ListExploder), create vertices (VertexCreator), build a line (LineBuilder) and finally close the line to form a polygon (LineCloser).
Alternatively, the JSONTemplater with this template expression creates a GeoJSON object representing a polygon. You can replace it with a polygon geometry using the GeometryReplacer (Geometry Encoding: GeoJSON).
let $xs := fme:get-list-attribute('x-coord{}.part')
let $ys := fme:get-list-attribute('y-coord{}.part')
return
{
    "type" : "Polygon",
    "coordinates" : a
        r
            for $i in (1 to count($xs))
            return Âxs:double($xsÂ$i]), xs:double($ys>$i])],
            fxs:double($xs11]), xs:double($ysb1])]
        ]
    ]
}
Thank you very much @takashi, this worked for me!
Here's a possible solution using the PythonCaller:
def GeneratePolygon(feature):
    x_coords = xfloat(x) for x in feature.getAttribute('x-coord{}.part') or o]]
    y_coords = rfloat(y) for y in feature.getAttribute('y-coord{}.part') or t]]
    feature.addCoordinates(zip(x_coords, y_coords))
Add a LineCloser after the PythonCaller.
I couldn't get this to work, but I don't know Python very well! When I have a bit more time I'll have another go as I like to be able to understand everything in my workspaces! Thank you for the help.
Put together this transformer that makes a line, but I think making a polygon would be just as simple https://hub.safe.com/publishers/runneals/transformers/listlinebuilder
For anyone else trying to solve this, I had a similar issue where I wanted to create 40 simple rectangular polygons without using a reader. I came up with the following solution, which isn't particularly elegant, but it gets the job done! I hope I've covered all the parameters that matter.
Â
Creator
AttributeManager
- Output attribute: coordinates
- Output value: text with x0 y0,x1 y1,x2 y2,x3 y3, x4 y4, ... , x0 y0 on each line (first and last coordinate pairs are the same)
AttributeSplitter
- Attribute to split: coordinates
- Delimiter or Fomat String: new line]
- List Name: _coordinate_list
ListExploder
- List Attribute: _coordinate_list{}
- Element Index: _polygon_index
AttributeSplitter_2
- Attribute t split: _coordinate_list
- Delimiter or Format String: comma]
- List Name: _coord_pair
ListExploder_2
- List Attribute: _coord_pair{}
- Element Index: _polygon_coord_index
AttributeSplitter_3
- Attribute to split: _coord_pair
- Delimiter or Format String: space]
- List Name: _x_y
VertexCreator
- Mode: Replace with Point
- X Value: _x_y{0}
- Y Value: _x_y{1}
LineBuilder
- Group Processing: Ticked
- Group By: _polygon_index
Â
If the LineBuilder outputs a Line, your first and last coordinates aren't the same. Otherwise you should have polygons good to go.