Skip to main content

Picture a very curvy stream polygon. I would like to quickly calculate the shortest width and the longest width. Bounding boxes would not be applicable.

Thanks,

Pete

If the "min/max length/width of polygon" means the shorter/longer length of the oriented bounding box of the polygon, the BoundingBoxReplecer (Replace With: Oriented Bounding Box) might help you.


Sorry @takashi,

Doesn't mean bounding box. Picture a winding river polygon. I'd like to find the shortest/longest width. Using the bounding box alone would only apply to relatively straight segments.

Thanks,

Pete


Sorry @takashi,

Doesn't mean bounding box. Picture a winding river polygon. I'd like to find the shortest/longest width. Using the bounding box alone would only apply to relatively straight segments.

Thanks,

Pete

I would be interested in any solutions you come up with for the width.


Sorry @takashi,

Doesn't mean bounding box. Picture a winding river polygon. I'd like to find the shortest/longest width. Using the bounding box alone would only apply to relatively straight segments.

Thanks,

Pete

OK. Will provide any solutions here...


Hold on, I'm picturing a curvy stream...

...

...

Right, now that's done. Perhaps a little fun with the CenterLineReplacer is what you need? In the attached template file there is a dummy MapInfo TAB file that contains a "pretend river". In the process I run a centerline down the middle, then create another with 'Straight Skeletal' sticky out bits to each node. Then drape one on the other so we just keep the ribs of the skeleton. Then extend each of these, clip them with the original geometry to clean them up and calculate the length to get the width of the river at each cross-section. You can control the number of cross-sections but playing with the tolerance of the Densifier up front.

I'll be interested to hear if that is any help.

FMWT for download here:

workoutriverwidth.fmwt


I put together a lengthy workbench for a project a number of years ago that ran something like this:

  1. Get (or calculate) the centreline of the feature - this can probably be approximate (CentreLineReplacer)
  2. Chop it up into short segments - say 10 metres (Snipper)
  3. Take a point on each segment (Chopper)
  4. Buffer the centrepoint (Bufferer)
  5. Chop the line segments against the buffered centrepoints (Clipper)
  6. Rotate the chopped line segments by 90 degrees (Rotator)
  7. Extend the lines out beyond the full polygon width, but not too far beyond (Extender)
  8. Clip the extended line against the full polygon (Clipper)
  9. Calculate lengths (LengthCalculator)
  10. Calculate the min/max/average/standard deviation/whatever of the lengths for the section you're interested in (StatisticsCalculator)
  11. Check, check, and check again (manually)

You might want to modify this by breaking the original feature down into smaller parts. I was doing this for roads, so hit problems at junctions. If you're doing rivers, it might be easier. Or harder...

Hope this gives you some ideas!


Combined the excellent solutions of @1spatialdave and @rollo + alpha: estimate-river-width.fmwt


Thought I'd throw in my 2c here. To me I'd start out with the Triangulator transformer. Creating triangles is the solution to everything!

Seriously, that should create river-spanning triangles. You just need to pick which has the longest axis. Maybe use the BoundingBoxReplacer on those triangles and select the longest edge?


HI,

I also create a centerline.

But i do this by preliminarily use a negative buffer on the stream, to get a more continous centerline.

I then join the bits of the centerline and extend them beyond the ends of the stream. Then cut the stream along its length.

Id them.

Segmenter to create veritces on one side only. Extract vertices. Name them like v1.

Neighbourfinder at decent distance to get vertices of other side.

Create vertices by nearest candidate x,y. Name them like V2.

Create lines by vertexcreators (V1 replace V2 add.)

GEt lenght of those.

Statistics calulator to get max and min. Wich will yield location.

It is highly shape dependant of course. So you might need some tweaking.


Thanks everyone for your thorough and rapid responses. I'll try each suggestion.


Thought I'd throw in my 2c here. To me I'd start out with the Triangulator transformer. Creating triangles is the solution to everything!

Seriously, that should create river-spanning triangles. You just need to pick which has the longest axis. Maybe use the BoundingBoxReplacer on those triangles and select the longest edge?

NRCAN-CITS had a complicated method they developed years ago involving Thiessen polygons, it was mentioned during the FME User Conferance.


Thought I'd throw in my 2c here. To me I'd start out with the Triangulator transformer. Creating triangles is the solution to everything!

Seriously, that should create river-spanning triangles. You just need to pick which has the longest axis. Maybe use the BoundingBoxReplacer on those triangles and select the longest edge?

A dumb question, I know, but my brain is not working. What is the quick way to extract the triangles to get the various axis, or feed into the BoundingBoxReplacer?


HI,

I also create a centerline.

But i do this by preliminarily use a negative buffer on the stream, to get a more continous centerline.

I then join the bits of the centerline and extend them beyond the ends of the stream. Then cut the stream along its length.

Id them.

Segmenter to create veritces on one side only. Extract vertices. Name them like v1.

Neighbourfinder at decent distance to get vertices of other side.

Create vertices by nearest candidate x,y. Name them like V2.

Create lines by vertexcreators (V1 replace V2 add.)

GEt lenght of those.

Statistics calulator to get max and min. Wich will yield location.

It is highly shape dependant of course. So you might need some tweaking.

Segmenter?


A dumb question, I know, but my brain is not working. What is the quick way to extract the triangles to get the various axis, or feed into the BoundingBoxReplacer?

The Deaggregator


The Deaggregator

Ah yes...thanks.


Hold on, I'm picturing a curvy stream...

...

...

Right, now that's done. Perhaps a little fun with the CenterLineReplacer is what you need? In the attached template file there is a dummy MapInfo TAB file that contains a "pretend river". In the process I run a centerline down the middle, then create another with 'Straight Skeletal' sticky out bits to each node. Then drape one on the other so we just keep the ribs of the skeleton. Then extend each of these, clip them with the original geometry to clean them up and calculate the length to get the width of the river at each cross-section. You can control the number of cross-sections but playing with the tolerance of the Densifier up front.

I'll be interested to hear if that is any help.

FMWT for download here:

workoutriverwidth.fmwt

Excellent visualization.


Hi @takashi and @Mark2AtSafe,

Here are some results of processing a sample stream (looks more like a cul-de-sac)

As you can see, some lines/edges span the polygon well and some don't. I wish I could just lengthen the lines that are perpendicular to the polygon edge, more as shown with the 'Inspect after Rotator' view.

The thick blue line (drawn by hand, supposed to be straight) would indicated the widest point of the polygon. How am I supposed to derive that? Am I missing something?

The best tool would just be a simple-acting polygon chopper that slices in parallel along the longest length of the polygon with a defined chop interval (much like dicing a curved cucumber down its length, or perhaps a gourd, in this case).


HI,

I also create a centerline.

But i do this by preliminarily use a negative buffer on the stream, to get a more continous centerline.

I then join the bits of the centerline and extend them beyond the ends of the stream. Then cut the stream along its length.

Id them.

Segmenter to create veritces on one side only. Extract vertices. Name them like v1.

Neighbourfinder at decent distance to get vertices of other side.

Create vertices by nearest candidate x,y. Name them like V2.

Create lines by vertexcreators (V1 replace V2 add.)

GEt lenght of those.

Statistics calulator to get max and min. Wich will yield location.

It is highly shape dependant of course. So you might need some tweaking.

The CenterLineReplacer in the Medial Axis mode works pretty well. My shapes are very independent...it is even hard to get a negative buffer that works for all polys, and since I can't measure the polygon width precisely, it is hard to variably assign the negative buffer length. Any further assistance would be greatly appreciated.

Thanks again,

Pete


Hi @takashi and @Mark2AtSafe,

Here are some results of processing a sample stream (looks more like a cul-de-sac)

As you can see, some lines/edges span the polygon well and some don't. I wish I could just lengthen the lines that are perpendicular to the polygon edge, more as shown with the 'Inspect after Rotator' view.

The thick blue line (drawn by hand, supposed to be straight) would indicated the widest point of the polygon. How am I supposed to derive that? Am I missing something?

The best tool would just be a simple-acting polygon chopper that slices in parallel along the longest length of the polygon with a defined chop interval (much like dicing a curved cucumber down its length, or perhaps a gourd, in this case).

Here's an example output resulting from running a python script I found for ArcMap that adds lines along the length of the polygon:

So far, it provides the best output with regard to segmenting polygons, even though I'm not seeing perpendicular lines for the more irregular shapes The script is provided in the attached python file.polygon-split-script2.py

Looking at the python script:

a.) Is there a string of transformers that accomplishes the same thing?

b) If not, how would I need to alter the python script to run in FME (other than the obvious...)?

c) Can the process be improved to maximize the number of perpendicular lines along the edges?

Sorry, but I'm pretty much a newbie with Python.

Thanks, as always, for your excellent responses. I'm hoping I can do this all in FME without bouncing back and forth to ArcMap.

Best,

Pete


Hi Pete - I've adapted my approach and it gives a better result now. See if its any use for you.

All the best, Dave

workoutriverwidth-v2.fmw


Hi Pete - I've adapted my approach and it gives a better result now. See if its any use for you.

All the best, Dave

workoutriverwidth-v2.fmw

looks like a very nicely diced snake.. i'll give the fmw a go!


Hi Pete - I've adapted my approach and it gives a better result now. See if its any use for you.

All the best, Dave

workoutriverwidth-v2.fmw

Sorry @1spatialdave,

Perhaps it is the morphology of the polygons but the wordoutriverwidth-v2 workspace is generating a lot of line segments creating more noise than signal. Virtually every polygon I inspected in the fmw output has non-parallel lines of various lengths. I noticed that your snaky river is based on a very simplified poly (i.e., no rounded edges). Do you think such an abstraction needs to be performed first? I'd rather not mess with the geometry, if possible, but if that's the only way....

I've attached some sample data if you want to play with it. sampleshapes.zip

I realize this is hard to do and I appreciate your help. Again, my best hope is to not get out of FME and into ArcMap and then back again to do my further analysis of the line segments. If this isn't possible, then please let me know either way.

Perhaps a plan B would be to incorporate the Python script into the workspace, but Plan A is definitely to do it all with FME transformers... Thoughts?

Thanks again,

Pete


Sorry @1spatialdave,

Perhaps it is the morphology of the polygons but the wordoutriverwidth-v2 workspace is generating a lot of line segments creating more noise than signal. Virtually every polygon I inspected in the fmw output has non-parallel lines of various lengths. I noticed that your snaky river is based on a very simplified poly (i.e., no rounded edges). Do you think such an abstraction needs to be performed first? I'd rather not mess with the geometry, if possible, but if that's the only way....

I've attached some sample data if you want to play with it. sampleshapes.zip

I realize this is hard to do and I appreciate your help. Again, my best hope is to not get out of FME and into ArcMap and then back again to do my further analysis of the line segments. If this isn't possible, then please let me know either way.

Perhaps a plan B would be to incorporate the Python script into the workspace, but Plan A is definitely to do it all with FME transformers... Thoughts?

Thanks again,

Pete

Perhaps you are right the Python approach is certainly winning out with elaborate geometries. Sadly Python is not my thing, so you somehow need to bribe @takashi or @DaveAtSafe to help you incorporate it into a PythonCaller as they are both Python Jedi Masters!


Unfortunately I also don't know how you can use the ArcGIS Python function in FME workspace.

I upgraded my previous solution. The attached workspace is not perfect, but generates "better" cross sections for some areas as shown in this image. estimate-river-cross-sections.zip

The key point is how to create "clean" center line for the river area, and the Generalizer might be useful in this case. However, the best solution could be different depending on the actual data condition. As @rollo mentioned at first, I think you cannot avoid doing trial and error approach to find appropriate solutions for each area. Good luck!


Unfortunately I also don't know how you can use the ArcGIS Python function in FME workspace.

I upgraded my previous solution. The attached workspace is not perfect, but generates "better" cross sections for some areas as shown in this image. estimate-river-cross-sections.zip

The key point is how to create "clean" center line for the river area, and the Generalizer might be useful in this case. However, the best solution could be different depending on the actual data condition. As @rollo mentioned at first, I think you cannot avoid doing trial and error approach to find appropriate solutions for each area. Good luck!

Probably the attached workspace simulates the algorithm of the ArcGIS Python function. simulate-arcgis-function-algorithm.zip (updated)


Reply