def repGeomString(shp): return str(round(shp.area)) + '|' + str(round(shp.centroid.X, 2)) + '|' + str(round(shp.centroid.Y, 2))
def fasterFindID(fc): """Records geometrical attributes of all features, then returns a dictionary: overlapDict: key = OID; value = identical overlap OIDs. The parameter fc is assumed to be the product of an overlap operation like Union or Intersect.""" # this creates a representation of a geometry string by concatenating various attributes to create a "unique" identifier def repGeomString(shp): return str(round(shp.area)) + '|' + str(round(shp.centroid.X, 2)) + '|' + str(round(shp.centroid.Y, 2)) # two dictionaries to keep track of duplicate geometries and their OIDs geomDictByOID = {} # key = OID; value = represented geometry string uniqueGeoms = {} # key = represented geometry string; value = list of OIDs with same geometry oidFieldName = arcpy.Describe(fc).oidFieldName nullCentroids = [] # gather geometries, and if centroid null, append to list with arcpy.da.SearchCursor(fc, ("OID@", "SHAPE@")) as cursor: for row in cursor: try: # get full k,v pair of OID and geometries geomDictByOID[row[0]] = repGeomString(row[1]) # initialize empty list as value of unique geometry key uniqueGeoms[repGeomString(row[1])] = [] except: nullCentroids.append(row[0]) # if null centroids exist, convert features to point and reread centroids # post-conversion, centroids will exist... for some reason if len(nullCentroids) > 0: # Format to string tuple for SQL query, and remove trailing comma for len = 1 if len(nullCentroids) > 1: nullCentroidsFormat = str(tuple(nullCentroids)) else: nullCentroidsFormat = str(tuple(nullCentroids)).replace(',', '') arcpy.MakeFeatureLayer_management(fc, 'nLyr', '"{0}" IN {1}'.format(oidFieldName, nullCentroidsFormat)) nullCentroidsPts = arcpy.FeatureToPoint_management('nLyr', arcpy.Describe(fc).name + 'NullCentroids') # loop through null centroid features and read new centroids with arcpy.da.SearchCursor(nullCentroidsPts, ("OID@", "SHAPE@")) as cursor: for row in cursor: # get full k,v pair of OID and geometries geomDictByOID[row[0]] = repGeomString(row[1]) # initialize empty list as value of unique geometry key uniqueGeoms[repGeomString(row[1])] = [] # for each geometry key in uniqueGeoms, append all OIDs that match for oid, g in geomDictByOID.iteritems(): uniqueGeoms.append(oid) # create dictionary that relates each oid to its overlaps overlapDict = {} for oid, g in geomDictByOID.iteritems(): if len(uniqueGeoms) > 1: overlapDict[oid] = [k for k in uniqueGeoms if k != oid] # Delete potentially large dicts del geomDictByOID del uniqueGeoms return overlapDict
All I'm really interested in is which shapes are identical to each other after a union operation on buffers.
#Flatten this puppy! shatteredFC = fgdbPath + "\\shattered" arcpy.Union_analysis(dissolveFC, shatteredFC, "ALL", "1 FEET", "GAPS"); showGpMessage() singlePartFC = fgdbPath + "\\single_part" arcpy.MultipartToSinglepart_management(shatteredFC, singlePartFC); showGpMessage() searchRows = arcpy.da.SearchCursor(singlePartFC, ["SHAPE@","*"]) polyIdDict = {} polyIdValue = 1 decimalTolerance = 2 for searchRow in searchRows: shapeFieldValue = searchRow[searchRows.fields.index("SHAPE@")] xCentroidValue = round(shapeFieldValue.centroid.X, decimalTolerance) yCentroidValue = round(shapeFieldValue.centroid.Y, decimalTolerance) areaValue = round(shapeFieldValue.area, decimalTolerance) axyValue = (xCentroidValue,yCentroidValue,areaValue) catagoryNameValue = searchRow[searchRows.fields.index("CATEGORY")] releaseYearValue = searchRow[searchRows.fields.index("RELEASE_YR")] retentionPctValue = searchRow[searchRows.fields.index("RETENTION_PCNT")] forestedFlagValue = searchRow[searchRows.fields.index("FORESTED")] if axyValue not in polyIdDict: polyIdDict[axyValue] = polyIdValue, [catagoryNameValue], [releaseYearValue],[retentionPctValue],[forestedFlagValue] polyIdValue = polyIdValue + 1 else: polyIdDict[axyValue][1].append(catagoryNameValue) polyIdDict[axyValue][2].append(releaseYearValue) polyIdDict[axyValue][3].append(retentionPctValue) polyIdDict[axyValue][4].append(forestedFlagValue) del searchRow, searchRows #Sort the thing the way we want it for axyValue in polyIdDict: polyIdDict[axyValue][1].sort() #catagory name polyIdDict[axyValue][2].sort(reverse=True) #release year polyIdDict[axyValue][3].sort(reverse=True) #retention percent polyIdDict[axyValue][4].sort() #forested arcpy.AddField_management(singlePartFC, "POLY_ID", "LONG"); showGpMessage() arcpy.AddField_management(singlePartFC, "LCL_RSN", "TEXT", "", "", "150"); showGpMessage() arcpy.AddField_management(singlePartFC, "RELEASE_YR_MAX", "SHORT"); showGpMessage() arcpy.AddField_management(singlePartFC, "RETENTION_PCNT_MAX", "SHORT"); showGpMessage() arcpy.AddField_management(singlePartFC, "FORESTED_MAX", "TEXT", "", "", "1"); showGpMessage() arcpy.AddField_management(singlePartFC, "LCL_RP_FLG", "SHORT"); showGpMessage() arcpy.AddField_management(singlePartFC, "LCL_UP_FLG", "SHORT"); showGpMessage() arcpy.AddField_management(singlePartFC, "LCL_US_FLG", "SHORT"); showGpMessage() arcpy.AddField_management(singlePartFC, "LCL_WT_FLG", "SHORT"); showGpMessage() updateRows = arcpy.da.UpdateCursor(singlePartFC, ["SHAPE@","*"]) for updateRow in updateRows: shapeFieldValue = updateRow[updateRows.fields.index("SHAPE@")] xCentroidValue = round(shapeFieldValue.centroid.X, decimalTolerance) yCentroidValue = round(shapeFieldValue.centroid.Y, decimalTolerance) areaValue = round(shapeFieldValue.area, decimalTolerance) axyValue = (xCentroidValue,yCentroidValue,areaValue) updateRow[updateRows.fields.index("POLY_ID")] = polyIdDict[axyValue][0] updateRow[updateRows.fields.index("LCL_RSN")] = ",".join(i for i in sorted(set(polyIdDict[axyValue][1]))) updateRow[updateRows.fields.index("RELEASE_YR_MAX")] = polyIdDict[axyValue][2][0] updateRow[updateRows.fields.index("RETENTION_PCNT_MAX")] = polyIdDict[axyValue][3][0] updateRow[updateRows.fields.index("FORESTED_MAX")] = polyIdDict[axyValue][4][0] if "RIPARIAN_AREA" in polyIdDict[axyValue][1] or "RMZ" in polyIdDict[axyValue][1]: updateRow[updateRows.fields.index("LCL_RP_FLG")] = 1 if "WETLAND" in polyIdDict[axyValue][1] or "WMZ" in polyIdDict[axyValue][1]: updateRow[updateRows.fields.index("LCL_WT_FLG")] = 1 if 'SLOPE_STABILITY_ISSUE' in polyIdDict[axyValue][1] or 'SLOPE_STABILITY_POTENTIAL' in polyIdDict[axyValue][1] or 'SLOPE_STABILITY_VERIFIED' in polyIdDict[axyValue][1] or 'UNSTABLE_SLOPES' in polyIdDict[axyValue][1]: updateRow[updateRows.fields.index("LCL_US_FLG")] = 1 #A bit of a work around just for SPS - untl the new schema is completed... if 'AREA_REGULATION' in polyIdDict[axyValue][1] and polyIdDict[axyValue][3][0] < 50: updateRow[updateRows.fields.index("RETENTION_PCNT_MAX")] = 50 updateRows.updateRow(updateRow) del updateRow, updateRows
Angemeldete Mitglieder können Beiträge verfassen, Updates folgen und mehr. Neu hier? Registriere ein kostenloses Konto.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.