I am trying to see what polylines are within any one polygon. That is, I'd like to print a list of what circuits a county contains.
To do this, I'm trying to iterate through some KMZs (after converting them to layers).
I then intersect the polygons (counties) with the polylines (circuits) and create a temp layer that should contain all the counties that contain lines in them.
I then use Search Cursor to print what polygons (counties) contain polylines (circuits).
Unfortunately, instead of combining all the polygon and polyline data into one attribute table, it iterates through each KMZ, creates a temp layer, then deletes it. It then prints the final temp layer KMZ comparison.
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.listMaps("Map")[0]
county = ["Dude County"]
projectfilepath = "C:\\Users\\User\\Documents\\ArcGIS\\Projects\\ARCPY_test\\"
datafilepath = "C:\\Users\\User\\Documents\\ArcGIS\Data\\"
to_KMZs_filepath = "Circuits_KMZs\\"
parcel = "Counties_(v17a)"
gdb = datafilepath + to_KMZs_filepath
counties = m.listLayers(parcel)
import os
for dirpath, dirnames, filenames in os.walk(rootdir):
for file in filenames:
if file.endswith("kmz"):
try:
arcpy.conversion.KMLToLayer(
in_kml_file = m.addDataFromPath(os.path.join(gdb,file)),
output_folder = projectfilepath,
output_data = file + "_LAYER",
include_groundoverlay="NO_GROUNDOVERLAY"
)
line = m.listLayers(file + "\Polylines")
arcpy.analysis.Intersect(
in_features = [counties, line],
out_feature_class = r"memory\temp_intersect",
output_type = "POINT"
)
except Exception:
arcpy.AddMessage(os.path.join(rootdir,file))
fields = ["LABEL", "NAME_1"]
with arcpy.da.SearchCursor(r"memory\temp_intersect", fields) as u_cursor:
for label, name_1 in u_cursor:
if label in county:
rows = arcpy.SearchCursor(r"memory\temp_intersect", fields="NAME_1")
for row in rows:
print("{0}".format(row.getValue("NAME_1")))
Hi,
Do you just need to indent from the "fields" line down? With the search cursor outside of the for loop it'll keep overwriting the "memory\temp_intersect" output for each KML and then just run the search cursor over the final KML layer that is intersected. Although this would print out the values for each KML separately which it doesn't sound like you want the output to be.
If you do want it all in one final search cursor, you could output each temp intersect layer with a different name (so it's not overwritten every time), then add a merge above the "fields" line to bring them all together, and use the merged layer as the input into your cursor?
@JoshuaSharp-Hewardis correct with nesting the code though I'd avoid nesting cursors that iterate over the same dataset. You could actually simplify this to use one cursor and utilize a dictionary. I assume that you want to get a count for each county in the counties dataset so something like this will get a total:
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.listMaps("Map")[0]
county = ["Dude County"]
projectfilepath = "C:\\Users\\User\\Documents\\ArcGIS\\Projects\\ARCPY_test\\"
datafilepath = "C:\\Users\\User\\Documents\\ArcGIS\Data\\"
to_KMZs_filepath = "Circuits_KMZs\\"
parcel = "Counties_(v17a)"
gdb = datafilepath + to_KMZs_filepath
counties = m.listLayers(parcel)
import os
fields = ["LABEL", "NAME_1"]
totals = {}
for dirpath, dirnames, filenames in os.walk(rootdir):
for file in filenames:
if file.endswith("kmz"):
try:
arcpy.conversion.KMLToLayer(
in_kml_file = m.addDataFromPath(os.path.join(gdb,file)),
output_folder = projectfilepath,
output_data = file + "_LAYER",
include_groundoverlay="NO_GROUNDOVERLAY"
)
line = m.listLayers(file + "\Polylines")
tmp_int = arcpy.analysis.Intersect(
in_features = [counties, line],
out_feature_class = r"memory\temp_intersect",
output_type = "POINT"
)
with arcpy.da.SearchCursor(tmp_int, fields) as s_cursor:
for label, name_1 in s_cursor:
if label in county: # remove this conditional and adjust the indents below for it to include all counties in the intersect
print(f"{name_1}")
# add to dictionary for totals.
if not totals.get(label):
totals[label] = 1
else:
totals[label] = totals[label] + 1
except Exception:
arcpy.AddMessage(os.path.join(rootdir, file))
# print the final message
for k, v in totals.items():
print(f'County: {k} has {v} polylines')
Thank you @JoshuaSharp-Heward and @Anonymous User! Unfortunately, the code still writes over the "memory\temp_intersect" layer no matter how I modify it. The final "memory\temp_intersect" layer is merely a copy of the counties layer.
I'm not trying to count the polylines, but list them out by name, per county.
So, if I enter the name of county (in the LABEL field), arcpy will spit out all the names of the circuits (in the NAME_1 field) that pass through that county.
Have you confirmed that the intersect outputs what you want it to when you run it manually? I've updated the user above's code to store unique names for the input county/counties and print them at the end.
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.listMaps("Map")[0]
county = ["Dude County"]
projectfilepath = "C:\\Users\\User\\Documents\\ArcGIS\\Projects\\ARCPY_test\\"
datafilepath = "C:\\Users\\User\\Documents\\ArcGIS\Data\\"
to_KMZs_filepath = "Circuits_KMZs\\"
parcel = "Counties_(v17a)"
gdb = datafilepath + to_KMZs_filepath
counties = m.listLayers(parcel)
import os
fields = ["LABEL", "NAME_1"]
names = {}
for dirpath, dirnames, filenames in os.walk(rootdir):
for file in filenames:
if file.endswith("kmz"):
try:
arcpy.conversion.KMLToLayer(
in_kml_file = m.addDataFromPath(os.path.join(gdb,file)),
output_folder = projectfilepath,
output_data = file + "_LAYER",
include_groundoverlay="NO_GROUNDOVERLAY"
)
line = m.listLayers(file + "\Polylines")
tmp_int = arcpy.analysis.Intersect(
in_features = [counties, line],
out_feature_class = r"memory\temp_intersect",
output_type = "POINT"
)
with arcpy.da.SearchCursor(tmp_int, fields) as s_cursor:
for label, name_1 in s_cursor:
if label in county: # remove this conditional and adjust the indents below for it to include all counties in the intersect
print(f"{name_1}")
if label not in names: #if county not present as key in dictionary add it and add first name_1 value as a list
names[label]= [name_1]
print(f"Added {label} and {name_1} to names dictionary")
else:
if name_1 not in names[label]: #if county present as key and name_1 not in list of names, add it
names[label].append(name_1)
print(f"Adding {name_1} to {label} in dictionary")
else: #if name already in list of names for county key in dict, don't add it
print(f"Not adding {name_1} as already present in dictionary")
except Exception:
arcpy.AddMessage(os.path.join(rootdir, file))
# print the final message
for k, v in totals.items():
print(f'County: {k} | names: {v}')
The temp layers will always be overwritten with the above code because the output name is the same every time it's run, what we're doing here is extracting the information we want from the temporary layer, storing it to a dictionary outside of the for loop (so it's persisted) and then looping through the dictionary values at the end.
Can you not just merge all the features together and do a spatial join with a merge rule of 'join'? that would create a field which contains a list (you choose the delimiter also) of line attributes which intersect.
@JoshuaSharp-Hewardthank you! Your codes speeds things up, but still results in the same issue: the temp file is just a copy of the county files.
@DavidPikeI'm trying your idea, but coming up pretty short:
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.listMaps("Map")[0]
county = ["Dude County"]
projectfilepath = "C:\\Users\\User\\Documents\\ArcGIS\\Projects\\ARCPY_test\\"
datafilepath = "C:\\Users\\User\\Documents\\ArcGIS\Data\\"
to_KMZs_filepath = "Circuits_KMZs\\"
parcel = "Counties_(v17a)"
gdb = datafilepath + to_KMZs_filepath
counties = m.listLayers(parcel)
import os
for dirpath, dirnames, filenames in os.walk(gdb):
for file in filenames:
if file.endswith("kmz"):
arcpy.conversion.KMLToLayer(
in_kml_file = m.addDataFromPath(os.path.join(gdb,file)),
output_folder = projectfilepath,
output_data = file + "_LAYER",
include_groundoverlay="NO_GROUNDOVERLAY")
for lyr in m.listLayers(file + "_LAYER\Polylines"):
m.moveLayer(lyr, counties, "BEFORE")
if arcpy.Exists("group_for_merge") == False:
m.createGroupLayer("group_for_merge")
if arcpy.Exists("group_for_merge") == True:
lyr_to_move = "*Polylines*"
for lyr in m.listLayers(lyr_to_move):
groupLayer = "group_for_merge"
lyr = m.listLayers(lyr_to_move)[0]
mapGroupLayer = m.listLayers(groupLayer)[0]
m.addLayerToGroup(mapGroupLayer, lyr)
arcpy.management.Delete(lyr_to_move, "lyr")
# Create FieldMappings object to manage merge output fields
fieldMappings = arcpy.FieldMappings()
# Add all fields from both oldStreets and newStreets
fieldMappings.addTable(lyr_to_move)
# Add input fields "STREET_NAM" & "NM" into new output field
fldMap_circuitName = arcpy.FieldMap()
fldMap_circuitName.addInputField(lyr_to_move, "NAME")
# Set name of new output field "Street_Name"
circuitName = fldMap_circuitName.outputField
circuitName.name = "Circuit_Name"
fldMap_circuitName.outputField = circuitName
# Add output field to field mappings object
fieldMappings.addFieldMap(fldMap_circuitName)
# Remove all output fields from the field mappings, except fields
# "Street_Class", "Street_Name", & "Distance"
for field in fieldMappings.fields:
if field.name not in ["Circuit_Name"]:
fieldMappings.removeFieldMap(fieldMappings.findFieldMapIndex(field.name))
# Use Merge tool to move features into single dataset
circuitsMerge = gdb
arcpy.management.Merge(lyr_to_move, circuitsMerge, fieldMappings,
addSourceInfo)
arcpy.analysis.SpatialJoin(counties, lyr_to_move,
out_feature_class="mergeSpatialJoin",
join_operation="JOIN_ONE_TO_MANY",
join_type="KEEP_ALL")
From your code, there isnt really any other indication what your intention is for this temp layer so is there more code to this that is using the tmp_int? If you want to save each temp file that is created in your iteration, you need to give them unique names so they don't overwrite each iteration.
iter = 0
for file in filenames:
if file.endswith("kmz"):
try:
arcpy.conversion.KMLToLayer(
in_kml_file = m.addDataFromPath(os.path.join(gdb,file)),
output_folder = projectfilepath,
output_data = file + "_LAYER",
include_groundoverlay="NO_GROUNDOVERLAY"
)
line = m.listLayers(file + "\Polylines")
tmp_int = arcpy.analysis.Intersect(
in_features = [counties, line],
out_feature_class = fr"memory\temp_intersect_{iter}",
output_type = "POINT"
)
...
iter += 1
Thank you Jeff, I'm trying to see what polylines are within any one polygon. (I'd like to print a list of what circuits any one county contains.)
ok, if you want more than one county, you need to remove this conditional, which is limiting to "Dude County"
if label in county: # remove this conditional and adjust the indents below for it to include all counties in the intersect