Question

How to calculate width of polygon (Rivers/roads)?


Badge +1

How can calculate width of polygon in case rivers or roads?

I have a road data and I need to know how minimum width of each segment of roads. I tried with some steps such as below:

- First: from road polygon I generate centerline by CenterLineReplacer Transformer

- After that: I used Chopper Transformer to chopped the Centerline into segments with mode "by vertex". 

- Next: I rotate all vertex with 90 degree and I extend line with a length (my problem is here). With road data which have more branch, and each branch have width difference, some case the range between minimum and maximum is so big (e.g. minimum is 0.5 met but maximum is 200 m). So when set the length parameter it not right for all branch. 

imageimage- Next: I used Clipper to clip this line with polygon

- Finally: I calculated length of lines and this value mean are width of polygon.

That all I understood and tried to calculate width of polygon. Because the length which set in The extend line step is not really right for all branch so the result like this image bellow:

imageThis case has many cross lines from other branch, so I don't have ideas to filter all cross lines.

If you have ideas to solve this issue, let's show me! Thank you so much!


17 replies

Userlevel 3
Badge +16

From the road centreline, I'd use a Densifier to 1m or 5m frequency, Chop into individual vertices. Then a NeighborFinder between the road polygons and centreline points, treating polygons as lines. That'll give the distance from each centreline point to the edge. Multiply by 2 to get the width.

Then you need to decide how you want to define road width, whether it's per road segment, per road name, per centreline etc. Use a StatisticsCalculator to get the median width, across whatever group you choose to group by.

Userlevel 5
Badge +36

After you have split your polygon (for which you have posted a separate question) you can get a quick approximation of the lenght and width from the area and perimeter of the polygon.

Approx_Length = @Evaluate(@Length()/4 + @sqrt(@pow(@Length()/4,2)-@Area()))
Approx_Width = @Evaluate(@Length()/4 - @sqrt(@pow(@Length()/4,2)-@Area()))

This works best for long thin polygons.

Badge +1

From the road centreline, I'd use a Densifier to 1m or 5m frequency, Chop into individual vertices. Then a NeighborFinder between the road polygons and centreline points, treating polygons as lines. That'll give the distance from each centreline point to the edge. Multiply by 2 to get the width.

Then you need to decide how you want to define road width, whether it's per road segment, per road name, per centreline etc. Use a StatisticsCalculator to get the median width, across whatever group you choose to group by.

Thank for your sharing the good idea! I'll try it! 😊

Badge +1

After you have split your polygon (for which you have posted a separate question) you can get a quick approximation of the lenght and width from the area and perimeter of the polygon.

Approx_Length = @Evaluate(@Length()/4 + @sqrt(@pow(@Length()/4,2)-@Area()))
Approx_Width = @Evaluate(@Length()/4 - @sqrt(@pow(@Length()/4,2)-@Area()))

This works best for long thin polygons.

Yes, thank you so much! I want to know how width of road before each parcel (or house). So I need calculate it with small segments and after that I assign the value to each parcel which nearest with the point. That is my idea! 

Hi 

I want to calculate min, max, avg width(breadth) from polygons.

My input have only list polygons:

{ "type": "Feature", "properties": { "OBJECTID": 1.0, "SHAPE_Leng": 0.00057672519222000005, "SHAPE_Area": 5.191152e-09, "name": null, "rongMax": null, "rongMin": null, "rongTB": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 105.814052974000049, 21.009160664000035 ], [ 105.814018928000053, 21.00919353200004 ], [ 105.814021210000078, 21.009195662000025 ], [ 105.814026385000034, 21.009202952000066 ], [ 105.81405440900005, 21.009242426000071 ], [ 105.814090260000057, 21.009269388000064 ], [ 105.814124937000088, 21.009292263000077 ], [ 105.814203617000032, 21.009343118000061 ], [ 105.814214316000061, 21.009350654000059 ], [ 105.814223964000064, 21.009340076000058 ], [ 105.814170518000083, 21.009304149000059 ], [ 105.81414109900004, 21.009282088000077 ], [ 105.814117868000039, 21.009266112000034 ], [ 105.814087328000085, 21.009244852000052 ], [ 105.814074111000082, 21.009232288000078 ], [ 105.814072411000041, 21.009232829000041 ], [ 105.814058327000055, 21.009186317000058 ], [ 105.814055345000043, 21.009175664000054 ], [ 105.814052974000049, 21.009160664000035 ] ] ] ] } }

Can you give me some iead to solve it, or tool, or code example.

Many thanks

Here I had drawn it to easy understand:

image

Userlevel 5
Badge +36

There is a great custom transformer called BoundsSplitter on FME Hub. It can create cross lines at a set interval. Next you can calculate the length of these lines, and determine the minimal, maximal and mean length.

GeoJSON_Polygon_minmaxwidth

There is a great custom transformer called BoundsSplitter on FME Hub. It can create cross lines at a set interval. Next you can calculate the length of these lines, and determine the minimal, maximal and mean length.

GeoJSON_Polygon_minmaxwidth

hi @geomancer​ thank you very much. If program can export to python code? Can you give me example code python. It very good for automatic

Userlevel 5
Badge +36

There is a great custom transformer called BoundsSplitter on FME Hub. It can create cross lines at a set interval. Next you can calculate the length of these lines, and determine the minimal, maximal and mean length.

GeoJSON_Polygon_minmaxwidth

The BoundsSplitter custom transformer does contain Python code, which does most of the work. You can look into it if you want.

I did not create this transformer, and I am no Python specialist, so unfortunately I cannot help you there.

@geomancer​ thank you for your help. I very happy if you can give me the source hub(link) python.

Userlevel 5
Badge +36

Hi, you can find the Python code inside the custom transformer BoundsSplitter.

Just add the transformer to your FME workspace (or open the workspace I provided yesterday), right-click the transformer, and click Edit. The Python code is inside the PythonCaller inside the BoundsSplitter. It is best to study the Python code inside the FME environment, because of the dependencies. Good luck!

Hi, you can find the Python code inside the custom transformer BoundsSplitter.

Just add the transformer to your FME workspace (or open the workspace I provided yesterday), right-click the transformer, and click Edit. The Python code is inside the PythonCaller inside the BoundsSplitter. It is best to study the Python code inside the FME environment, because of the dependencies. Good luck!

Thank you very much.

Hi, you can find the Python code inside the custom transformer BoundsSplitter.

Just add the transformer to your FME workspace (or open the workspace I provided yesterday), right-click the transformer, and click Edit. The Python code is inside the PythonCaller inside the BoundsSplitter. It is best to study the Python code inside the FME environment, because of the dependencies. Good luck!

sorry @geomancer​ I am a new bie, so I can not find where transformer to edit

imageI'm happy that You can tutorial or copy python to here.

Thank you

Badge +1

Hi 

I want to calculate min, max, avg width(breadth) from polygons.

My input have only list polygons:

{ "type": "Feature", "properties": { "OBJECTID": 1.0, "SHAPE_Leng": 0.00057672519222000005, "SHAPE_Area": 5.191152e-09, "name": null, "rongMax": null, "rongMin": null, "rongTB": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 105.814052974000049, 21.009160664000035 ], [ 105.814018928000053, 21.00919353200004 ], [ 105.814021210000078, 21.009195662000025 ], [ 105.814026385000034, 21.009202952000066 ], [ 105.81405440900005, 21.009242426000071 ], [ 105.814090260000057, 21.009269388000064 ], [ 105.814124937000088, 21.009292263000077 ], [ 105.814203617000032, 21.009343118000061 ], [ 105.814214316000061, 21.009350654000059 ], [ 105.814223964000064, 21.009340076000058 ], [ 105.814170518000083, 21.009304149000059 ], [ 105.81414109900004, 21.009282088000077 ], [ 105.814117868000039, 21.009266112000034 ], [ 105.814087328000085, 21.009244852000052 ], [ 105.814074111000082, 21.009232288000078 ], [ 105.814072411000041, 21.009232829000041 ], [ 105.814058327000055, 21.009186317000058 ], [ 105.814055345000043, 21.009175664000054 ], [ 105.814052974000049, 21.009160664000035 ] ] ] ] } }

Can you give me some iead to solve it, or tool, or code example.

Many thanks

Here I had drawn it to easy understand:

image

Hi, can you show me your email or phone? I will contact and guide you to solve this issue! Thank

Badge +1

From the road centreline, I'd use a Densifier to 1m or 5m frequency, Chop into individual vertices. Then a NeighborFinder between the road polygons and centreline points, treating polygons as lines. That'll give the distance from each centreline point to the edge. Multiply by 2 to get the width.

Then you need to decide how you want to define road width, whether it's per road segment, per road name, per centreline etc. Use a StatisticsCalculator to get the median width, across whatever group you choose to group by.

Or you can contact me by phone: 0944550477 or email: pqtkha@gmail.com

Userlevel 5
Badge +36

Hi, you can find the Python code inside the custom transformer BoundsSplitter.

Just add the transformer to your FME workspace (or open the workspace I provided yesterday), right-click the transformer, and click Edit. The Python code is inside the PythonCaller inside the BoundsSplitter. It is best to study the Python code inside the FME environment, because of the dependencies. Good luck!

Hi @tuphamkhactu122​ , (1) right-click the BoundsSplitter transformer, and (2) select Edit in the popup-menu that appears. This opens a new tab (3) called BoundsSplitter in FME Workbench. On this new tab (4) open the PythonCaller.

How_to_Edit_a_Custom_Transformer

Hi @geomancer​ 

after trying to improve. I saw that: with the polygon in same direction, the calculate good, but with complicated polygon(multi direction), work badly.

Now I think, if can determine the direction and split polygons to blocks. It works better.

Have you have ideas to solve it??(split polygon to block with same direction)

Many thanks.

image.pngHere is my data:

{ "type": "Feature", "properties": { "OBJECTID": 6.0, "SHAPE_Leng": 0.0018435614763720001, "SHAPE_Area": 1.830693e-08, "name": null, "rongMax": null, "rongMin": null, "rongTB": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 105.814233473000058, 21.009605263000026 ], [ 105.814270254000064, 21.009557108000024 ], [ 105.814294123000082, 21.009508220000043 ], [ 105.814310222000074, 21.00947741400006 ], [ 105.814272326000037, 21.009456668000041 ], [ 105.814212241000064, 21.009415109000031 ], [ 105.81420315400004, 21.00940840100003 ], [ 105.81417328200007, 21.009386347000031 ], [ 105.814165209000066, 21.009398109000074 ], [ 105.814144615000032, 21.009394712000073 ], [ 105.814124802000038, 21.009382587000061 ], [ 105.814117689000057, 21.009392403000049 ], [ 105.814070315000038, 21.009362398000064 ], [ 105.814035767000064, 21.00933989300006 ], [ 105.81399544900006, 21.009314226000072 ], [ 105.813992317000043, 21.00931666200006 ], [ 105.813938111000084, 21.009278877000042 ], [ 105.813956262000033, 21.009253924000063 ], [ 105.813898282000082, 21.009273615000041 ], [ 105.813906806000034, 21.009281664000071 ], [ 105.813926242000036, 21.009296736000067 ], [ 105.813930008000057, 21.009292257000027 ], [ 105.814022481000052, 21.009355528000071 ], [ 105.814091046000044, 21.009398283000053 ], [ 105.814108600000054, 21.009407042000078 ], [ 105.814147095000067, 21.009413957000049 ], [ 105.814147350000042, 21.009413089000077 ], [ 105.814174914000034, 21.009421213000053 ], [ 105.814174412000057, 21.009422525000048 ], [ 105.814199988000041, 21.009438416000023 ], [ 105.814196086000038, 21.00944436900005 ], [ 105.81427995100006, 21.009495137000044 ], [ 105.81422490500006, 21.009573164000074 ], [ 105.814231047000078, 21.009576607000042 ], [ 105.814197398000033, 21.009632903000067 ], [ 105.814200504000041, 21.009634568000024 ], [ 105.814165204000062, 21.009698650000075 ], [ 105.814130529000067, 21.009681203000071 ], [ 105.814110726000081, 21.009670929000038 ], [ 105.814077452000049, 21.00965476600004 ], [ 105.814043983000033, 21.009639770000035 ], [ 105.814037492000068, 21.009636667000052 ], [ 105.814028830000041, 21.009653373000049 ], [ 105.814056730000061, 21.009666333000041 ], [ 105.814085146000082, 21.009679532000064 ], [ 105.814120301000059, 21.009698368000045 ], [ 105.814155253000081, 21.009715444000051 ], [ 105.81417351500005, 21.009716377000075 ], [ 105.814180653000051, 21.009702379000032 ], [ 105.814231116000087, 21.009606946000076 ], [ 105.814233473000058, 21.009605263000026 ] ] ] ] } }

 

Userlevel 5
Badge +36

Hi @tuphamkhactu122​, that is a good question. Thanks for the sample polygon!

To split this polygon, I looked (with the PolylineAnalyzer, another great custom transformer from the Hub) for the vertices where the change in direction is about 270 degrees, and then only the vertices that have no other vertex of this kind nearby. From these vertices I created splitting lines, with which I then split the polygon.

This method will not work for polygons with slightly concave vertices, so probably there are better solutions.

GeoJSON_Polygon_minmaxwidth_split

Reply