Wednesday, February 3, 2016

ArcGIS polygon to lines and feature vertices to points without an ArcGIS advanced license

I've started taking a little time to create python functions, using standard license code, that replicate some of ArcGIS's tools that are only available with an advanced license. So far, I've created functions for the Polygon To Line and the Feature Vertices To Points tools. Each make use of cursors and geometries to get the job done. The two functions take an input feature class's full catalog path, a workspace (file geodatabase or in_memory), and the file name for the new feature class, and return the full path to the function's output, which has been generated in the indicated workspace. Both also make use of my UniqueFileName function mentioned in a previous blog.

Which tools should I code next?

The code:

#polygons to lines
def PolygonToLines (inFc, workspace, fcName):

    outFc = UniqueFileName (workspace, fcName)
    try:
        #let esri do it (advanced license)
        arcpy.FeatureToLine_management (inFc, outFc)
        return outFc
    except:
        pass
    #no advanced license
    array = arcpy.Array ()
    sr = arcpy.Describe (inFc).spatialReference
    outPath, outName = os.path.split (outFc)
    arcpy.CreateFeatureclass_management (outPath,
                                         outName,
                                         "POLYLINE",
                                         spatial_reference = sr)
    with arcpy.da.InsertCursor (outFc, "SHAPE@") as iCurs:
        with arcpy.da.SearchCursor (inFc, "SHAPE@") as sCurs:
            for geom, in sCurs:
                for i in range (geom.partCount):
                    lastPart = None
                    part = geom.getPart (i)
                    for pnt in part:
                        if not pnt:
                            lastPart = None
                            continue
                        x = pnt.X
                        y = pnt.Y
                        if not lastPart:
                            lastPart = (x, y)
                            continue
                        thisPart = (x, y)
                        lastPoint = arcpy.Point ()
                        lastPoint.X = lastPart [0]
                        lastPoint.Y = lastPart [1]
                        thisPoint = arcpy.Point ()
                        thisPoint.X = thisPart [0]
                        thisPoint.Y = thisPart [1]
                        array.add (lastPoint)
                        array.add (thisPoint)
                        polyline = arcpy.Polyline (array)
                        array.removeAll ()
                        lastPart = thisPart
                        row = (polyline,)
                        iCurs.insertRow (row)
    del iCurs
    del sCurs
    return outFc


#feature vertices to points
def VerticesToPoints (inFc, workspace, fcName):

    outFc = UniqueFileName(workspace, fcName)
    try:
        #let esri do it (advanced license)
        arcpy.FeatureVerticesToPoints_management (inFc, outFc)
        return outFc
    except:
        pass
    #no advanced license
    sr = arcpy.Describe (inFc).spatialReference
    outPath, outName = os.path.split (outFc)
    arcpy.CreateFeatureclass_management (outPath,
                                         outName,
                                         "POINT",
                                         spatial_reference = sr)
    with arcpy.da.InsertCursor (outFc, "SHAPE@") as iCurs:
        with arcpy.da.SearchCursor (inFc, "SHAPE@") as sCurs:
            for geom, in sCurs:
                for i in range (geom.partCount):
                    part = geom.getPart (i)
                    for pnt in part:
                        if not pnt:
                            continue
                        row = (pnt,)
                        iCurs.insertRow (row)
    del iCurs
    del sCurs
    return outFc


#generate a unique ArcGIS file name
def UniqueFileName(location = "in_memory",
                   name = "file",
                   extension = ""):
    
    if extension:
        outName = os.path.join (location, name + "." + extension)
    else:
        outName = os.path.join (location, name)
    i = 0
    while arcpy.Exists (outName):
        i += 1
        if extension:
            outName = os.path.join (location,
                                    "{0}_{1}.{2}".format (name, i,
                                                          extension))
        else:
            outName = os.path.join (location,
                                    "{0}_{1}".format (name, i))
    return outName
profile for Emil Brundage at Geographic Information Systems Stack Exchange, Q&A for cartographers, geographers and GIS professionals

6 comments:

  1. Awesome Emil! Was very helpful for me.
    Thanks a lot for sharing it!

    ReplyDelete
  2. Hi, I've never used python before and I'm trying to figure stuff out... I was extremely happy to find your code online, but I don't quite know how to use it! Exactly where am I supposed to enter my input and output feature names in your code?

    ReplyDelete
    Replies
    1. Hey Alice, feel free to email me at emilharold@gmail.com and we'll figure it out.

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Hi Emil, a very nice article
    I want to ask something, how to define local data to run this code?

    arcpy.CreateFeatureclass_management (outPath,
    outName,
    "POINT",
    spatial_reference = sr)



    I tried it this way but it did not work.

    arcpy.CreateFeatureclass_management (C:\SIL\feature vertices_to_POINT.mdb,
    File_Name_Test,
    "POINT",
    spatial_reference = GCS_WGS_1984)

    ReplyDelete
  5. This comment has been removed by a blog administrator.

    ReplyDelete