<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Discriminate convex vs concave vertices within each polygon feature in ArcGIS Pro Questions</title>
    <link>https://community.esri.com/t5/arcgis-pro-questions/discriminate-convex-vs-concave-vertices-within/m-p/1238189#M63028</link>
    <description>&lt;P&gt;Starting from Dan's suggestion of convexHull(), which seemed good:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;with arcpy.da.UpdateCursor("TestPolygons", ["SHAPE@", "IntegerField"]) as cursor:
    for shp, n in cursor:
        n = len(shp[0]) - len(shp.convexHull()[0])  # only for singlepart polygons
        cursor.updateRow([shp, n])&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;This works well for simple geometries:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JohannesLindner_0-1670325926043.png" style="width: 400px;"&gt;&lt;img src="https://community.esri.com/t5/image/serverpage/image-id/57736i82DF4C7F611AA7D4/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JohannesLindner_0-1670325926043.png" alt="JohannesLindner_0-1670325926043.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;But it starts to break down for more complex geometries, where convex vertices are not always on the convex hull:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JohannesLindner_1-1670326259996.png" style="width: 400px;"&gt;&lt;img src="https://community.esri.com/t5/image/serverpage/image-id/57737i4AF3A8D9C52C1080/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JohannesLindner_1-1670326259996.png" alt="JohannesLindner_1-1670326259996.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I was ready to start fussing with angles between polylines when I realized that you can quite simply say whether a vertex is concave or convex: cretae a triangle of the vertex and its neighbours. If that triangle is inside the polygon, the vertex is convex, else it's concave.&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JohannesLindner_2-1670329512390.png" style="width: 400px;"&gt;&lt;img src="https://community.esri.com/t5/image/serverpage/image-id/57739i4366B80612B6B4E2/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JohannesLindner_2-1670329512390.png" alt="JohannesLindner_2-1670329512390.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;def get_concave_vertex_count(polygon):
    n = 0
    for part in polygon:
        for i, vertex in enumerate(part):
            prev_vertex = part[i-1]
            try:
                next_vertex = part[i+1]
            except IndexError:
                next_vertex = part[0]
            triangle = arcpy.Polygon(arcpy.Array([prev_vertex, vertex, next_vertex]))
            n += triangle.touches(polygon)  # touch: only boundaries intersect
    return n


with arcpy.da.UpdateCursor("PolygonLayer", ["SHAPE@", "ConcaveVertices"]) as cursor:
    for shp, n in cursor:
        n = get_concave_vertex_count(shp)
        cursor.updateRow([shp, n])&lt;/LI-CODE&gt;</description>
    <pubDate>Tue, 06 Dec 2022 12:33:27 GMT</pubDate>
    <dc:creator>JohannesLindner</dc:creator>
    <dc:date>2022-12-06T12:33:27Z</dc:date>
    <item>
      <title>Discriminate convex vs concave vertices within each polygon feature</title>
      <link>https://community.esri.com/t5/arcgis-pro-questions/discriminate-convex-vs-concave-vertices-within/m-p/1237810#M62992</link>
      <description>&lt;P&gt;Using the calculate geometry tool, one can calculate the number of vertices for each polygon in a feature class (&lt;A href="https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/calculate-geometry-attributes.htm)" target="_blank" rel="noopener"&gt;https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/calculate-geometry-attributes.htm)&lt;/A&gt;.&lt;/P&gt;&lt;P&gt;A vertex can be concave or convex, depending on whether the inner angle at the vertex is larger or smaller than 180 degrees.&lt;/P&gt;&lt;P&gt;Does anybody know of a tool which can calculate how many vertices per polygon are convex and how many are concave?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 05 Dec 2022 15:40:17 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-pro-questions/discriminate-convex-vs-concave-vertices-within/m-p/1237810#M62992</guid>
      <dc:creator>teakplantation</dc:creator>
      <dc:date>2022-12-05T15:40:17Z</dc:date>
    </item>
    <item>
      <title>Re: Discriminate convex vs concave vertices within each polygon feature</title>
      <link>https://community.esri.com/t5/arcgis-pro-questions/discriminate-convex-vs-concave-vertices-within/m-p/1237855#M63001</link>
      <description>&lt;P&gt;You could return the difference between the polygon and its convex hull (symmetric difference perhaps)&lt;/P&gt;&lt;P&gt;That will at least give you the start and end points where convexity changes.&amp;nbsp; You could convert to points for further work.&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If you need detailed work, you will have to convert the poly* features to point pairs&lt;/P&gt;&lt;P&gt;I use numpy generally but this idea could be easily translated to cursors.&lt;/P&gt;&lt;LI-CODE lang="python"&gt;import numpy as np
def polyline_angles(bits, fromNorth=False):
    """Polyline/segment angles.

    Parameters
    ----------
    bits : array-like
        XY coordinate pairs, usually a numpy ndarray or list of pairs.
    fromNorth : boolean
        True for North calculated angles.  False for x-axis calculations.
    """
    out = []
    for b in bits:
        dxy = b[1:] - b[:-1]  # -- sequential difference in pair coordinates
        ang = np.degrees(np.arctan2(dxy[:, 1], dxy[:, 0]))
        if fromNorth:
            ang = np.mod((450.0 - ang), 360.)
        out.append(ang)
    return out&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 05 Dec 2022 16:43:49 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-pro-questions/discriminate-convex-vs-concave-vertices-within/m-p/1237855#M63001</guid>
      <dc:creator>DanPatterson</dc:creator>
      <dc:date>2022-12-05T16:43:49Z</dc:date>
    </item>
    <item>
      <title>Re: Discriminate convex vs concave vertices within each polygon feature</title>
      <link>https://community.esri.com/t5/arcgis-pro-questions/discriminate-convex-vs-concave-vertices-within/m-p/1238189#M63028</link>
      <description>&lt;P&gt;Starting from Dan's suggestion of convexHull(), which seemed good:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;with arcpy.da.UpdateCursor("TestPolygons", ["SHAPE@", "IntegerField"]) as cursor:
    for shp, n in cursor:
        n = len(shp[0]) - len(shp.convexHull()[0])  # only for singlepart polygons
        cursor.updateRow([shp, n])&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;This works well for simple geometries:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JohannesLindner_0-1670325926043.png" style="width: 400px;"&gt;&lt;img src="https://community.esri.com/t5/image/serverpage/image-id/57736i82DF4C7F611AA7D4/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JohannesLindner_0-1670325926043.png" alt="JohannesLindner_0-1670325926043.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;But it starts to break down for more complex geometries, where convex vertices are not always on the convex hull:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JohannesLindner_1-1670326259996.png" style="width: 400px;"&gt;&lt;img src="https://community.esri.com/t5/image/serverpage/image-id/57737i4AF3A8D9C52C1080/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JohannesLindner_1-1670326259996.png" alt="JohannesLindner_1-1670326259996.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I was ready to start fussing with angles between polylines when I realized that you can quite simply say whether a vertex is concave or convex: cretae a triangle of the vertex and its neighbours. If that triangle is inside the polygon, the vertex is convex, else it's concave.&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JohannesLindner_2-1670329512390.png" style="width: 400px;"&gt;&lt;img src="https://community.esri.com/t5/image/serverpage/image-id/57739i4366B80612B6B4E2/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JohannesLindner_2-1670329512390.png" alt="JohannesLindner_2-1670329512390.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;def get_concave_vertex_count(polygon):
    n = 0
    for part in polygon:
        for i, vertex in enumerate(part):
            prev_vertex = part[i-1]
            try:
                next_vertex = part[i+1]
            except IndexError:
                next_vertex = part[0]
            triangle = arcpy.Polygon(arcpy.Array([prev_vertex, vertex, next_vertex]))
            n += triangle.touches(polygon)  # touch: only boundaries intersect
    return n


with arcpy.da.UpdateCursor("PolygonLayer", ["SHAPE@", "ConcaveVertices"]) as cursor:
    for shp, n in cursor:
        n = get_concave_vertex_count(shp)
        cursor.updateRow([shp, n])&lt;/LI-CODE&gt;</description>
      <pubDate>Tue, 06 Dec 2022 12:33:27 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-pro-questions/discriminate-convex-vs-concave-vertices-within/m-p/1238189#M63028</guid>
      <dc:creator>JohannesLindner</dc:creator>
      <dc:date>2022-12-06T12:33:27Z</dc:date>
    </item>
  </channel>
</rss>

