class NetworkDatasetRandomPoints(object): ### # Initialize the tool. ### def __init__(self): self.label = "Create Random Points on a Network Dataset" self.description = "Create a series of random points on a network dataset." self.canRunInBackground = False arcpy.env.overwriteOutput = True self.kfHelper = KFunctionHelper() ### # Get input from the users. ### def getParameterInfo(self): # Network dataset. networkDataset = arcpy.Parameter( displayName="Existing Network Dataset", name = "network_dataset", datatype="Network Dataset Layer", parameterType="Required", direction="Input") # Output location. outLocation = arcpy.Parameter( displayName="Path to Output Random Point Feature Class", name="out_location", datatype="DEWorkspace", parameterType="Required", direction="Input") outLocation.value = arcpy.env.workspace # The random point feature class to create. outPointClass = arcpy.Parameter( displayName="Output Random Point Feature Class Name", name = "output_point_feature_class", datatype="GPString", parameterType="Required", direction="Output") # Num points or long. useField = arcpy.Parameter( displayName="Use a Data Field for Point Generation", name = "use_field", datatype="GPBoolean", parameterType="Optional", direction="Input") # Number of random points to generate. numPoints = arcpy.Parameter( displayName="Number of Points", name = "num_points", datatype="GPLong", parameterType="Optional", direction="Input") # Number of points field. numPointsFieldName = arcpy.Parameter( displayName="Number of Points Field", name = "num_points_field", datatype="GPString", parameterType="Optional", direction="Input") return [networkDataset, outLocation, outPointClass, useField, numPoints, numPointsFieldName] ### # Check if the tool is available for use. ### def isLicensed(self): return True ### # Set the parameter defaults. ### def updateParameters(self, parameters): networkDataset = parameters[0].value outPointClass = parameters[2].value useField = parameters[3].value if networkDataset is not None and outPointClass is None: # Default name for the output table. ndDesc = arcpy.Describe(networkDataset) parameters[2].value = ndDesc.name + "_Random_Points" # Num points/num points field is based on the useField checkbox. parameters[4].enabled = not useField parameters[5].enabled = useField # Set the source of the fields (the network dataset). if useField == True and networkDataset is not None: parameters[5].filter.list = self.kfHelper.getEdgeSourceFieldNames(networkDataset) ### # If any fields are invalid, show an appropriate error message. ### def updateMessages(self, parameters): networkDataset = parameters[0].value useField = parameters[3].value numPoints = parameters[4].value numPointsFieldName = parameters[5].value if numPoints is not None: if numPoints <= 0: parameters[2].setErrorMessage("The number of points must be greater than 0.") else: parameters[2].clearMessage() if useField: if numPointsFieldName is None: parameters[5].setErrorMessage("Number of points field is required.") else: parameters[5].clearMessage() # Check that there is a single edge source if a field is used. if networkDataset is not None: if self.kfHelper.getNumEdgeSources(networkDataset) != 1: parameters[5].setErrorMessage("If using a field, only a single edge source is supported.") else: parameters[5].clearMessage() else: if numPoints is None: parameters[4].setErrorMessage("Number of points is required.") else: parameters[4].clearMessage() ### # Execute the tool. ### def execute(self, parameters, messages): networkDataset = parameters[0].value outPath = parameters[1].value outPointClass = parameters[2].value useField = parameters[3].value numPoints = parameters[4].value numPointsFieldName = parameters[5].value wsPath = arcpy.env.workspace ndDesc = arcpy.Describe(networkDataset) messages.addMessage("Network Dataset: {0}".format(ndDesc.catalogPath)) messages.addMessage("Location to Output Random Point Feature Class: {0}".format(outPath)) messages.addMessage("Output Random Point Feature Class: {0}".format(outPointClass)) messages.addMessage("Use a Data Field for Point Generation: {0}".format(useField)) messages.addMessage("Number of Points: {0}".format(numPoints)) messages.addMessage("Number of Points Field: {0}".format(numPointsFieldName)) if useField: # Use the single edge source for the constraining feature. esFullPath = self.kfHelper.getEdgeSourcePath(networkDataset) # Create a series of random points on the new line class. messages.addMessage("Creating point feature class. Name: {0} Path: {1}" .format(outPointClass, outPath)) # Use the field name for the number of points (e.g. AADT). arcpy.CreateRandomPoints_management(out_path=outPath, out_name=outPointClass, constraining_feature_class=esFullPath, number_of_points_or_field=numPointsFieldName) else: # All the edge sources that make up the network dataset are combined into # a single feature class. lineClassName = "TEMP_LINES_{0}".format(ndDesc.name) lineClassFullPath = os.path.join(wsPath, lineClassName) arcpy.CreateFeatureclass_management(out_path=wsPath, out_name=lineClassName, geometry_type="POLYLINE", spatial_reference=ndDesc.spatialReference) with arcpy.da.InsertCursor(lineClassName, ["SHAPE@"]) as insCursor: # Get the edge sources that make up the network. edgeSources = ndDesc.edgeSources for edgeSource in edgeSources: edgePath = os.path.join(ndDesc.path, edgeSource.name) with arcpy.da.SearchCursor(edgePath, ["SHAPE@"]) as cursor: for row in cursor: insCursor.insertRow([row[0]]) # Combine all the line segments into a single line. singleLineName = "TEMP_SINGLE_LINE_{0}".format(ndDesc.name) singleLineFullPath = os.path.join(wsPath, singleLineName) arcpy.Dissolve_management(lineClassFullPath, singleLineFullPath) # Create a series of random points on the new line class. messages.addMessage("Creating point feature class. Name: {0} Path: {1}" .format(outPointClass, outPath)) arcpy.CreateRandomPoints_management(out_path=outPath, out_name=outPointClass, constraining_feature_class=singleLineFullPath, number_of_points_or_field=numPoints) # Clean up the temporary feature class. arcpy.Delete_management(lineClassFullPath) arcpy.Delete_management(singleLineFullPath)
class NetworkDatasetRandomPoints(object): ### # Initialize the tool. ### def __init__(self): self.label = "Create Random Points on a Network Dataset" self.description = "Create a series of random points on a network dataset." self.canRunInBackground = False arcpy.env.overwriteOutput = True self.kfHelper = KFunctionHelper() ### # Get input from the users. ### def getParameterInfo(self): # Network dataset. networkDataset = arcpy.Parameter( displayName="Existing Network Dataset", name="network_dataset", datatype="Network Dataset Layer", parameterType="Required", direction="Input") # Output location. outLocation = arcpy.Parameter( displayName="Path to Output Random Point Feature Class", name="out_location", datatype="DEWorkspace", parameterType="Required", direction="Input") outLocation.value = arcpy.env.workspace # The random point feature class to create. outPointClass = arcpy.Parameter( displayName="Output Random Point Feature Class Name", name="output_point_feature_class", datatype="GPString", parameterType="Required", direction="Output") # Num points or long. useField = arcpy.Parameter( displayName="Use a Data Field for Point Generation", name="use_field", datatype="GPBoolean", parameterType="Optional", direction="Input") # Number of random points to generate. numPoints = arcpy.Parameter(displayName="Number of Points", name="num_points", datatype="GPLong", parameterType="Optional", direction="Input") # Number of points field. numPointsFieldName = arcpy.Parameter( displayName="Number of Points Field", name="num_points_field", datatype="GPString", parameterType="Optional", direction="Input") return [ networkDataset, outLocation, outPointClass, useField, numPoints, numPointsFieldName ] ### # Check if the tool is available for use. ### def isLicensed(self): return True ### # Set the parameter defaults. ### def updateParameters(self, parameters): networkDataset = parameters[0].value outPointClass = parameters[2].value useField = parameters[3].value if networkDataset is not None and outPointClass is None: # Default name for the output table. ndDesc = arcpy.Describe(networkDataset) parameters[2].value = ndDesc.name + "_Random_Points" # Num points/num points field is based on the useField checkbox. parameters[4].enabled = not useField parameters[5].enabled = useField # Set the source of the fields (the network dataset). if useField == True and networkDataset is not None: parameters[5].filter.list = self.kfHelper.getEdgeSourceFieldNames( networkDataset) ### # If any fields are invalid, show an appropriate error message. ### def updateMessages(self, parameters): networkDataset = parameters[0].value useField = parameters[3].value numPoints = parameters[4].value numPointsFieldName = parameters[5].value if numPoints is not None: if numPoints <= 0: parameters[2].setErrorMessage( "The number of points must be greater than 0.") else: parameters[2].clearMessage() if useField: if numPointsFieldName is None: parameters[5].setErrorMessage( "Number of points field is required.") else: parameters[5].clearMessage() # Check that there is a single edge source if a field is used. if networkDataset is not None: if self.kfHelper.getNumEdgeSources(networkDataset) != 1: parameters[5].setErrorMessage( "If using a field, only a single edge source is supported." ) else: parameters[5].clearMessage() else: if numPoints is None: parameters[4].setErrorMessage("Number of points is required.") else: parameters[4].clearMessage() ### # Execute the tool. ### def execute(self, parameters, messages): networkDataset = parameters[0].value outPath = parameters[1].value outPointClass = parameters[2].value useField = parameters[3].value numPoints = parameters[4].value numPointsFieldName = parameters[5].value wsPath = arcpy.env.workspace ndDesc = arcpy.Describe(networkDataset) messages.addMessage("Network Dataset: {0}".format(ndDesc.catalogPath)) messages.addMessage( "Location to Output Random Point Feature Class: {0}".format( outPath)) messages.addMessage( "Output Random Point Feature Class: {0}".format(outPointClass)) messages.addMessage( "Use a Data Field for Point Generation: {0}".format(useField)) messages.addMessage("Number of Points: {0}".format(numPoints)) messages.addMessage( "Number of Points Field: {0}".format(numPointsFieldName)) if useField: # Use the single edge source for the constraining feature. esFullPath = self.kfHelper.getEdgeSourcePath(networkDataset) # Create a series of random points on the new line class. messages.addMessage( "Creating point feature class. Name: {0} Path: {1}".format( outPointClass, outPath)) # Use the field name for the number of points (e.g. AADT). arcpy.CreateRandomPoints_management( out_path=outPath, out_name=outPointClass, constraining_feature_class=esFullPath, number_of_points_or_field=numPointsFieldName) else: # All the edge sources that make up the network dataset are combined into # a single feature class. lineClassName = "TEMP_LINES_{0}".format(ndDesc.name) lineClassFullPath = os.path.join(wsPath, lineClassName) arcpy.CreateFeatureclass_management( out_path=wsPath, out_name=lineClassName, geometry_type="POLYLINE", spatial_reference=ndDesc.spatialReference) with arcpy.da.InsertCursor(lineClassName, ["SHAPE@"]) as insCursor: # Get the edge sources that make up the network. edgeSources = ndDesc.edgeSources for edgeSource in edgeSources: edgePath = os.path.join(ndDesc.path, edgeSource.name) with arcpy.da.SearchCursor(edgePath, ["SHAPE@"]) as cursor: for row in cursor: insCursor.insertRow([row[0]]) # Combine all the line segments into a single line. singleLineName = "TEMP_SINGLE_LINE_{0}".format(ndDesc.name) singleLineFullPath = os.path.join(wsPath, singleLineName) arcpy.Dissolve_management(lineClassFullPath, singleLineFullPath) # Create a series of random points on the new line class. messages.addMessage( "Creating point feature class. Name: {0} Path: {1}".format( outPointClass, outPath)) arcpy.CreateRandomPoints_management( out_path=outPath, out_name=outPointClass, constraining_feature_class=singleLineFullPath, number_of_points_or_field=numPoints) # Clean up the temporary feature class. arcpy.Delete_management(lineClassFullPath) arcpy.Delete_management(singleLineFullPath)