-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStreet Tools.pyt
199 lines (153 loc) · 6.41 KB
/
Street Tools.pyt
1
# -*- coding: utf-8 -*-import arcpyfrom arcgis.features import FeatureLayerfrom time import sleepfrom street_tools.segments import SegmentModel, SegmentCollectionclass Toolbox(object): def __init__(self): """Define the toolbox (the name of the toolbox is the name of the .pyt file).""" self.label = "Street Tools" self.alias = "StreetTools" # List of tool classes associated with this toolbox self.tools = [CrossStreetsTool]class CrossStreetsTool(object): def __init__(self): """Define the tool (tool name is the name of the class).""" self.label = "Find Cross Streets" self.description = "Find Cross Streets" self.canRunInBackground = False def getParameterInfo(self): """Define parameter definitions""" params = [] # input fields input_layer = arcpy.Parameter( displayName="Input features", name="Input Features", datatype="GPFeatureLayer", parameterType="Required", direction="Input") # input_layer.value = "Street segments" params.append(input_layer) street_name = arcpy.Parameter( displayName="Street Name Field", name="Street Name Field", datatype="Field", parameterType="Required", direction="Input") street_name.parameterDependencies = [input_layer.name] params.append(street_name) # output fields start_left = arcpy.Parameter( displayName="Start Left", name="Start Left", datatype="GPString", parameterType="Optional", direction="Output") start_right = arcpy.Parameter( displayName="Start Right", name="Start Right", datatype="GPString", parameterType="Optional", direction="Output") end_left = arcpy.Parameter( displayName="End Left", name="End Left", datatype="GPString", parameterType="Optional", direction="Output") end_right = arcpy.Parameter( displayName="End Right", name="End Right", datatype="GPString", parameterType="Optional", direction="Output") for out_param in [start_left, start_right, end_left, end_right]: out_param.enabled = False params.append(out_param) return params def isLicensed(self): """Set whether tool is licensed to execute.""" return True def updateParameters(self, parameters): """Modify the values and properties of parameters before internal validation is performed. This method is called whenever a parameter has been changed.""" input_layer = parameters[0] street_name = parameters[1] def get_layer_names(): p = arcpy.mp.ArcGISProject('current') if not p: return [] maps_list = p.listMaps() if not maps_list: return [] layers_list = maps_list[0].listLayers() if not layers_list: return [] return [x.name for x in layers_list] def get_field_names(layer): fields_list = arcpy.ListFields(layer.dataSource) return [x.name for x in fields_list] # try to autofill the values if not input_layer.altered: layer_names_list = get_layer_names() if layer_names_list and "Street segments" in layer_names_list: input_layer.value = "Street segments" if not street_name.altered and input_layer.altered and input_layer.value is not None: fields_names_list = get_field_names(input_layer.value) if "STREET_NAME" in fields_names_list: street_name.value = "STREET_NAME" return def updateMessages(self, parameters): """Modify the messages created by internal validation for each tool parameter. This method is called after internal validation.""" return def execute(self, parameters, messages): """The source code of the tool.""" # get tge parameters input_layer = parameters[0].value street_name = parameters[1].valueAsText start_left = parameters[2] start_right = parameters[3] end_left = parameters[4] end_right = parameters[5] # configure the SegmentCollection class SegmentCollection.featLayer = FeatureLayer(input_layer.dataSource) SegmentCollection.aprxLayerName = input_layer.name SegmentCollection.selectAttrList = ['OBJECTID', street_name] SegmentCollection.editAttrList = [street_name] # configure the SegmentModel class SegmentModel.setFieldNames(['OBJECTID', street_name]) # read the selected segments segments_collection = SegmentCollection() segments_collection.readSelected(1, 1) arcpy.AddMessage(f"{len(segments_collection.members)} segments selected.") if not segments_collection.members: arcpy.AddError(f"Segments not found.") return for segment in segments_collection.members: arcpy.AddMessage(f"=== Processing OBJECTID {segment.id} ===") # select it where_clause = f"OBJECTID = {segment.id}" result = arcpy.SelectLayerByAttribute_management(input_layer, "NEW_SELECTION", where_clause) while result.status < 4: sleep(0.2) # read the candidates arcpy.management.SelectLayerByLocation( input_layer, "BOUNDARY_TOUCHES", input_layer, None, "NEW_SELECTION", "NOT_INVERT") tran_collection = SegmentCollection() tran_collection.readSelected() # find the cross streets sl, sr, el, er = segment.find_cross_streets(tran_collection) # unselect arcpy.SelectLayerByAttribute_management(input_layer, "CLEAR_SELECTION") arcpy.AddMessage(f"Start Left = {sl}") arcpy.AddMessage(f"Start Right = {sr}") arcpy.AddMessage(f"End Left = {el}") arcpy.AddMessage(f"End Right = {er}") # output start_left.value = sl start_right.value = sr end_left.value = el end_right.value = er # restore the selection segments_collection.selectMembers() return