I have 2,000+ polygons that I need to find the shortest perimeter edge for. Does anyone have any solutions? Thanks in advance!
There is no direct tool for that. The process would entail scripting
Concerns
Perhaps you could elaborate on the purpose for identifying the 'shortest polygon edge'
Concernsyou will need to ensure that each polygon initially has extraneous vertices removed (Generalize, removing points on the perimeter that aren't part of a direction change.
To add to this, a shape you see as a 'rectangle', may actually be composed of smaller edges that look like 4 edges when you zoom out far enough inside the GIS. (e.g. the computer sees it as a 18 sided polygon, not a rectangle!) The generalise tool can help simplify the shape, but you need to enter tolerances that make sense with your particular data.
Simple example:
Actual Coords (5 sided shape to the computer):
1,1 1,2 2,2 2,1 2.02, 1.02
Human interpreted coords (Shape looks like a rectangle to me as the final vertex added nothing):
1,1 1,2 2,2 2,1
In this example, if I generalise the input data with a 0.05m tolerance, it would clean out the node thats not required as the 0.02 metre deviation has less effect on the shape of the polygon than the 0.05 tolerance.. and is therefore not required.
I have used the code below in the past to find the longest edge of a polygon, but you could rewrite it to find the shortest edge. However, there could be some discussion on what an edge is or how this should be interpreted:
<SPAN class="keyword token">def</SPAN> <SPAN class="token function">GetLargestLine</SPAN><SPAN class="punctuation token">(</SPAN>polygon<SPAN class="punctuation token">,</SPAN> offset<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> max_length <SPAN class="operator token">=</SPAN> <SPAN class="number token">0</SPAN> prev_pnt <SPAN class="operator token">=</SPAN> None side <SPAN class="operator token">=</SPAN> None sr <SPAN class="operator token">=</SPAN> polygon<SPAN class="punctuation token">.</SPAN>spatialReference polygon2 <SPAN class="operator token">=</SPAN> polygon<SPAN class="punctuation token">.</SPAN>generalize<SPAN class="punctuation token">(</SPAN><SPAN class="number token">0.1</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">for</SPAN> part <SPAN class="keyword token">in</SPAN> polygon2<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">for</SPAN> pnt <SPAN class="keyword token">in</SPAN> part<SPAN class="punctuation token">:</SPAN> <SPAN class="comment token"># print pnt</SPAN> <SPAN class="keyword token">if</SPAN> prev_pnt <SPAN class="keyword token">is</SPAN> None<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">pass</SPAN> <SPAN class="keyword token">else</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">if</SPAN> pnt <SPAN class="keyword token">is</SPAN> None<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">pass</SPAN> <SPAN class="keyword token">else</SPAN><SPAN class="punctuation token">:</SPAN> length <SPAN class="operator token">=</SPAN> GetDist<SPAN class="punctuation token">(</SPAN>pnt<SPAN class="punctuation token">,</SPAN> prev_pnt<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">if</SPAN> length <SPAN class="operator token">></SPAN> max_length<SPAN class="punctuation token">:</SPAN> max_length <SPAN class="operator token">=</SPAN> length side <SPAN class="operator token">=</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>Polyline<SPAN class="punctuation token">(</SPAN>arcpy<SPAN class="punctuation token">.</SPAN>Array<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">[</SPAN>prev_pnt<SPAN class="punctuation token">,</SPAN> pnt<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> sr<SPAN class="punctuation token">)</SPAN> prev_pnt <SPAN class="operator token">=</SPAN> pnt length <SPAN class="operator token">=</SPAN> side<SPAN class="punctuation token">.</SPAN>length side <SPAN class="operator token">=</SPAN> side<SPAN class="punctuation token">.</SPAN>segmentAlongLine<SPAN class="punctuation token">(</SPAN>offset<SPAN class="punctuation token">,</SPAN> length<SPAN class="operator token">-</SPAN>offset<SPAN class="punctuation token">,</SPAN> <SPAN class="token boolean">False</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">return</SPAN> side<SPAN class="punctuation token">,</SPAN> length<SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
This was used to generate solar panels on roof tops. See document here (Spanish content):
https://community.esri.com/docs/DOC-10095-evento-spx-esri-colombia-generaci%C3%B3n-de-paneles-solares-en-techos-bogot%C3…
Hust did a little test to see if it would work and I get a result with this code (it will add fields to the input featureclass, so it's better to run this on a copy of your data):
<SPAN class="keyword token">def</SPAN> <SPAN class="token function">main</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="comment token"># will change the input fc (adding fields!)</SPAN> <SPAN class="keyword token">import</SPAN> arcpy fc <SPAN class="operator token">=</SPAN> r<SPAN class="string token">'C:\GeoNet\ShortestEdge\data.gdb\polygons'</SPAN> generalize <SPAN class="operator token">=</SPAN> <SPAN class="number token">0.1</SPAN> <SPAN class="comment token"># change this value according to the tolerance in your data</SPAN> fc_out <SPAN class="operator token">=</SPAN> r<SPAN class="string token">'C:\GeoNet\ShortestEdge\data.gdb\lines_v01'</SPAN> <SPAN class="comment token"># output fields</SPAN> fld_len1 <SPAN class="operator token">=</SPAN> <SPAN class="string token">"ShortestLength1"</SPAN> fld_from_pnt1 <SPAN class="operator token">=</SPAN> <SPAN class="string token">"FromPoint1"</SPAN> fld_to_pnt1 <SPAN class="operator token">=</SPAN> <SPAN class="string token">"ToPoint1"</SPAN> fld_len2 <SPAN class="operator token">=</SPAN> <SPAN class="string token">"ShortestLength2"</SPAN> fld_from_pnt2 <SPAN class="operator token">=</SPAN> <SPAN class="string token">"FromPoint2"</SPAN> fld_to_pnt2 <SPAN class="operator token">=</SPAN> <SPAN class="string token">"ToPoint2"</SPAN> <SPAN class="comment token"># add fields</SPAN> AddField<SPAN class="punctuation token">(</SPAN>fc<SPAN class="punctuation token">,</SPAN> fld_len1<SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"DOUBLE"</SPAN><SPAN class="punctuation token">,</SPAN> None<SPAN class="punctuation token">)</SPAN> AddField<SPAN class="punctuation token">(</SPAN>fc<SPAN class="punctuation token">,</SPAN> fld_from_pnt1<SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"TEXT"</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">100</SPAN><SPAN class="punctuation token">)</SPAN> AddField<SPAN class="punctuation token">(</SPAN>fc<SPAN class="punctuation token">,</SPAN> fld_to_pnt1<SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"TEXT"</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">100</SPAN><SPAN class="punctuation token">)</SPAN> AddField<SPAN class="punctuation token">(</SPAN>fc<SPAN class="punctuation token">,</SPAN> fld_len2<SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"DOUBLE"</SPAN><SPAN class="punctuation token">,</SPAN> None<SPAN class="punctuation token">)</SPAN> AddField<SPAN class="punctuation token">(</SPAN>fc<SPAN class="punctuation token">,</SPAN> fld_from_pnt2<SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"TEXT"</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">100</SPAN><SPAN class="punctuation token">)</SPAN> AddField<SPAN class="punctuation token">(</SPAN>fc<SPAN class="punctuation token">,</SPAN> fld_to_pnt2<SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"TEXT"</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">100</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="comment token"># update cursor</SPAN> feats <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">]</SPAN> flds <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="string token">'SHAPE@'</SPAN><SPAN class="punctuation token">,</SPAN> fld_len1<SPAN class="punctuation token">,</SPAN> fld_from_pnt1<SPAN class="punctuation token">,</SPAN> fld_to_pnt1<SPAN class="punctuation token">,</SPAN> fld_len2<SPAN class="punctuation token">,</SPAN> fld_from_pnt2<SPAN class="punctuation token">,</SPAN> fld_to_pnt2<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">with</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>da<SPAN class="punctuation token">.</SPAN>UpdateCursor<SPAN class="punctuation token">(</SPAN>fc<SPAN class="punctuation token">,</SPAN> flds<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">as</SPAN> curs<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">for</SPAN> row <SPAN class="keyword token">in</SPAN> curs<SPAN class="punctuation token">:</SPAN> polygon <SPAN class="operator token">=</SPAN> row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN> length1<SPAN class="punctuation token">,</SPAN> from_pnt1<SPAN class="punctuation token">,</SPAN> to_pnt1<SPAN class="punctuation token">,</SPAN> line1 <SPAN class="operator token">=</SPAN> GetShortestEdgeData<SPAN class="punctuation token">(</SPAN>polygon<SPAN class="punctuation token">)</SPAN> feats<SPAN class="punctuation token">.</SPAN>append<SPAN class="punctuation token">(</SPAN>line1<SPAN class="punctuation token">)</SPAN> polygon2 <SPAN class="operator token">=</SPAN> polygon<SPAN class="punctuation token">.</SPAN>generalize<SPAN class="punctuation token">(</SPAN>generalize<SPAN class="punctuation token">)</SPAN> length2<SPAN class="punctuation token">,</SPAN> from_pnt2<SPAN class="punctuation token">,</SPAN> to_pnt2<SPAN class="punctuation token">,</SPAN> line2 <SPAN class="operator token">=</SPAN> GetShortestEdgeData<SPAN class="punctuation token">(</SPAN>polygon2<SPAN class="punctuation token">)</SPAN> feats<SPAN class="punctuation token">.</SPAN>append<SPAN class="punctuation token">(</SPAN>line2<SPAN class="punctuation token">)</SPAN> curs<SPAN class="punctuation token">.</SPAN>updateRow<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">(</SPAN>polygon<SPAN class="punctuation token">,</SPAN> length1<SPAN class="punctuation token">,</SPAN> from_pnt1<SPAN class="punctuation token">,</SPAN> to_pnt1<SPAN class="punctuation token">,</SPAN> length2<SPAN class="punctuation token">,</SPAN> from_pnt2<SPAN class="punctuation token">,</SPAN> to_pnt2<SPAN class="punctuation token">,</SPAN> <SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="comment token"># write lines to output fc for visual reference</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>CopyFeatures_management<SPAN class="punctuation token">(</SPAN>feats<SPAN class="punctuation token">,</SPAN> fc_out<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">def</SPAN> <SPAN class="token function">AddField</SPAN><SPAN class="punctuation token">(</SPAN>fc<SPAN class="punctuation token">,</SPAN> fld_name<SPAN class="punctuation token">,</SPAN> fld_type<SPAN class="punctuation token">,</SPAN> fld_length<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">if</SPAN> len<SPAN class="punctuation token">(</SPAN>arcpy<SPAN class="punctuation token">.</SPAN>ListFields<SPAN class="punctuation token">(</SPAN>fc<SPAN class="punctuation token">,</SPAN> fld_name<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="operator token">==</SPAN> <SPAN class="number token">0</SPAN><SPAN class="punctuation token">:</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>AddField_management<SPAN class="punctuation token">(</SPAN>fc<SPAN class="punctuation token">,</SPAN> fld_name<SPAN class="punctuation token">,</SPAN> fld_type<SPAN class="punctuation token">,</SPAN> None<SPAN class="punctuation token">,</SPAN> None<SPAN class="punctuation token">,</SPAN> fld_length<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">def</SPAN> <SPAN class="token function">GetShortestEdgeData</SPAN><SPAN class="punctuation token">(</SPAN>polygon<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> min_length <SPAN class="operator token">=</SPAN> <SPAN class="number token">99999</SPAN> prev_pnt <SPAN class="operator token">=</SPAN> None side <SPAN class="operator token">=</SPAN> None sr <SPAN class="operator token">=</SPAN> polygon<SPAN class="punctuation token">.</SPAN>spatialReference <SPAN class="keyword token">for</SPAN> part <SPAN class="keyword token">in</SPAN> polygon<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">for</SPAN> pnt <SPAN class="keyword token">in</SPAN> part<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">if</SPAN> prev_pnt <SPAN class="keyword token">is</SPAN> None<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">pass</SPAN> <SPAN class="keyword token">else</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">if</SPAN> pnt <SPAN class="keyword token">is</SPAN> None<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">pass</SPAN> <SPAN class="keyword token">else</SPAN><SPAN class="punctuation token">:</SPAN> length <SPAN class="operator token">=</SPAN> GetDist<SPAN class="punctuation token">(</SPAN>pnt<SPAN class="punctuation token">,</SPAN> prev_pnt<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">if</SPAN> length <SPAN class="operator token"><</SPAN> min_length<SPAN class="punctuation token">:</SPAN> min_length <SPAN class="operator token">=</SPAN> length line <SPAN class="operator token">=</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>Polyline<SPAN class="punctuation token">(</SPAN>arcpy<SPAN class="punctuation token">.</SPAN>Array<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">[</SPAN>prev_pnt<SPAN class="punctuation token">,</SPAN> pnt<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> sr<SPAN class="punctuation token">)</SPAN> prev_pnt <SPAN class="operator token">=</SPAN> pnt length <SPAN class="operator token">=</SPAN> line<SPAN class="punctuation token">.</SPAN>length from_pnt <SPAN class="operator token">=</SPAN> line<SPAN class="punctuation token">.</SPAN>firstPoint to_pnt <SPAN class="operator token">=</SPAN> line<SPAN class="punctuation token">.</SPAN>lastPoint <SPAN class="keyword token">return</SPAN> length<SPAN class="punctuation token">,</SPAN> str<SPAN class="punctuation token">(</SPAN>from_pnt<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> str<SPAN class="punctuation token">(</SPAN>to_pnt<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> line <SPAN class="keyword token">def</SPAN> <SPAN class="token function">GetDist</SPAN><SPAN class="punctuation token">(</SPAN>pnt1<SPAN class="punctuation token">,</SPAN> pnt2<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">import</SPAN> math <SPAN class="keyword token">return</SPAN> math<SPAN class="punctuation token">.</SPAN>hypot<SPAN class="punctuation token">(</SPAN>pnt2<SPAN class="punctuation token">.</SPAN>X <SPAN class="operator token">-</SPAN> pnt1<SPAN class="punctuation token">.</SPAN>X<SPAN class="punctuation token">,</SPAN> pnt2<SPAN class="punctuation token">.</SPAN>Y <SPAN class="operator token">-</SPAN> pnt1<SPAN class="punctuation token">.</SPAN>Y<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">if</SPAN> __name__ <SPAN class="operator token">==</SPAN> <SPAN class="string token">'__main__'</SPAN><SPAN class="punctuation token">:</SPAN> main<SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
It will do this on the input polygon and a generalized polygon (set the variable generalize on line 5 with a proper value):
It also creates an output featureclass with the shortest edges.
Thanks everyone for your quick responses and great answers!
Solution is no longer needed (unfortunately), but for curiosity's sake, I was attempting to identify houses with long driveways (right of way access) by finding land parcel shapes with a short perimeter edge to represent a driveway edge. I couldn't find any other data source to indicate these so this is the best solution I could come up with.
Signed in members can post, follow updates, and more. New here? Register a free account.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.