Выполнение сетевого анализа

В Python вы можете выполнять сетевой анализ с помощью модуля Network Analyst, arcpy.nax. Этот модуль позволяет применять 6 типов анализа. Для каждого типа анализа (также называемого расчетом) вы работаете с двумя объектами, определенными для этого анализа: объект, который позволяет инициализировать анализ, задавать параметры анализа, загружать входные данные и выполнять анализ, и другой объект, который позволяет работать с результатами анализа после его выполнения. На рисунке ниже представлены объекты ServiceArea и ServiceAreaResult, которые используются для выполнения анализа области обслуживания. На рисунке показаны свойства и методы, доступные для каждого объекта. Свойства позволяют изменять параметры анализа, а методы позволяют выполнять действия, такие как загрузка входных данных или выполнение анализа.

Свойства и методы, доступные для объектов ServiceArea и ServiceAreaResult

Примечание:

В этом разделе в качестве примера приводится анализ области обслуживания, однако представленные здесь сведения можно применить к любому типу сетевого анализа.

Для проведения сетевого анализа, выполните следующие пять шагов:

  1. Инициализация анализа
  2. Настройка свойств для анализа
  3. Загрузка входных данных
  4. Расчет анализа
  5. Работа с результатами

Инициализация анализа

Для инициализации анализа необходимо предоставить набор сетевых данных, моделирующий транспортную сеть, в которой будет выполняться анализ. Вы можете указать набор сетевых данных, используя его полный путь к каталогу или имя слоя набора сетевых данных, созданного из набора сетевых данных с помощью функции MakeNetworkDatasetLayer.

Подсказка:

Для лучшей производительности используйте имя слоя набора сетевых данных при инициализации анализа. При использовании пути каталога набор сетевых данных открывается каждый раз при инициализации анализа. Открытие набора сетевых данных занимает много времени, так как наборы данных содержат расширенные структуры данных и таблицы, которые считываются и кэшируются. Слой набора сетевых данных открывает набор данных один раз и работает лучше, когда используется тот же слой.

В следующем фрагменте кода показано, как инициализировать анализ области обслуживания:

import arcpy
nd_path = "C:/data/NorthAmerica.gdb/Routing/Routing_ND"
nd_layer_name = "NorthAmerica"
# Create a network dataset layer. The layer will be referenced using its name.
arcpy.nax.MakeNetworkDatasetLayer(nd_path, nd_layer_name)
# Instantiate a ServiceArea analysis object.
service_area = arcpy.nax.ServiceArea(nd_layer_name)

Настройка свойств для анализа

После инициализации анализа необходимо задать свойства для анализа. Чтобы определить свойства, поддерживаемые объектом анализа, и понять, как данное свойство может влиять на анализ, см. раздел справки по конкретному объекту (доступен в категории Классы справки). Многие свойства задаются с помощью объектов перечисления Python, набора символических имен, представляющих некоторые постоянные значения. Например, единицы времени для анализа могут быть установлены как минуты с помощью элемента Minutes из перечисления arcpy.nax.TimeUnits. В разделе справки для объекта описывается, должно ли свойство быть задано как перечисление. Там также указывается имя перечисления, которое следует использовать.

Наиболее важным свойством, которое следует задать для любого анализа, является режим передвижения. Чтобы задать режим передвижения, сначала необходимо получить список режимов передвижения, поддерживаемых набором сетевых данных. Для этого используйте функцию GetTravelModes. В списке поддерживаемых режимов передвижения выберите имя режима. Функция GetTravelModes возвращает словарь, в котором ключом является имя режима передвижения, а значением – объект режима передвижения.

В приведенном ниже фрагменте кода показано, как задать свойства для анализа области обслуживания. Фрагмент кода предполагает, что объект анализа области обслуживания уже инициализирован.

# Get the desired travel mode for the analysis. nd_travel_modes = arcpy.nax.GetTravelModes(nd_layer_name) travel_mode = nd_travel_modes["Driving Time"]
# Set properties. service_area.timeUnits = arcpy.nax.TimeUnits.Minutes service_area.defaultImpedanceCutoffs = [5, 10, 15] service_area.travelMode = travel_mode service_area.outputType = arcpy.nax.ServiceAreaOutputType.Polygons service_area.geometryAtOverlap = arcpy.nax.ServiceAreaOverlapGeometry.Split

Загрузка входных данных

Перед выполнением анализа необходимо загрузить входные местоположения, которые будут использоваться для анализа. В зависимости от типа анализа необходимо загрузить одно или несколько местоположений в один или несколько типов входных данных, поддерживаемых этим анализом. Например, для выполнения анализа области обслуживания необходимо загрузить в тип данных ServiceAreaInputDataType.Facilities один или несколько объектов обслуживания. Это местоположения, вокруг которых создаются полигоны области обслуживания и линии области обслуживания.

Вы можете загрузить входные данные двумя способами. Если входные местоположения уже доступны в виде классов пространственных объектов или таблиц, их можно загрузить в объект анализа с помощью метода load. Если вы считываете входные местоположения из других источников данных, таких как CSV-файл, содержащий значения широты и долготы, или если у вас входные значения такие как точечные объекты ArcPy, вы можете загрузить входные данные в объект анализа с помощью метода insertCursor.

В следующем фрагменте кода показано, как загрузить объекты из класса пространственных объектов с помощью метода load при выполнении анализа области обслуживания:

input_facilities = "C:/data/io.gdb/Facilities"
service_area.load(arcpy.nax.ServiceAreaInputDataType.Facilities, input_facilities)

В следующем фрагменте кода показано, как загрузить объекты из файла CSV с помощью метода insertCursor при выполнении анализа области обслуживания: Предполагается, что service_area уже инициализирован.

# Read the CSV file with the following content. csv_file = "facilities.csv"
"""
ID,FacilityName,X,Y 1,Store 3,-117.101911,32.634351 2,Store 5,-116.979706,32.562102 3,Store 6,-116.971414,32.654230
"""
cursor_fields = ["Name", "SHAPE@XY"] with service_area.insertCursor(arcpy.nax.ServiceAreaInputDataType.Facilities, cursor_fields) as cur:
    with open(csv_file, "r", encoding="utf-8", newline="") as facilities:
        csv_reader = csv.reader(facilities)        # Assume the first line is the header and skip it.        next(csv_reader)        for row in csv_reader:
            location = (float(row[2]), float(row[3]))            cur.insertRow([row[1], location])

При выполнении анализа сначала необходимо найти расположение всех входных данных в транспортной сети. Этот процесс может быть длительным, если имеется большое количество входных объектов. Если необходимо перезагрузить один и тот же набор входных объектов для разных анализов, например, необходимо выполнить анализ зоны обслуживания для 8 и 10 часов утра, но применить один и тот же набор объектов в обоих анализах, можно оптимизировать общую производительность, предварительно рассчитав информацию, используемую анализом для определения местоположения входных объектов. Это можно сделать с помощью функции CalculateLocations. Если у входных данных есть поля местоположения (из функции CalculateLocations), используйте метод fieldMappings с параметром use_location_fields, установленным как True, и используйте сопоставление для этих полей при загрузке входных данных для вашего анализа. Анализ будет выполнен быстрее, потому что не будет выполняться повторная обработка.

Дополнительные сведения о полях местоположения сети и способе размещения входных данных в сети

Подсказка:

Использование CalculateLocations рекомендуется только при перезагрузке одних и тех же входных данных для различных анализов. Если входные данные загружаются только один раз, выполнение CalculateLocations не обеспечивает повышения производительности.

В следующем фрагменте кода показано, как использовать поля местоположения в сети при загрузке входных данных:

# Run the Calculate Locations tool to calculate network location fields arcpy.nax.CalculateLocations(    input_facilities, nd_layer_name, "5000 Meters",    [["Streets", "SHAPE"], ["Streets_ND_Junctions", "NONE"]],     travel_mode=travel_mode
)
# Initialize a Service Area analysis service_area = arcpy.nax.ServiceArea(nd_layer_name)
# Create a fieldMappings object for my Service Area with the use_location_fields 
# parameter set to True field_mappings = service_area.fieldMappings(    arcpy.nax.ServiceAreaInputDataType.Facilities, True)
# Map the names of my facilities to the Service Area's Name field field_mappings["Name"].mappedFieldName = "FacilityName"
# Map the network location fields. These lines are not strictly necessary 
# because the location fields will be mapped from the input table by default if 
# the fields are present. field_mappings["SourceID"].mappedFieldName = "SourceID"
field_mappings["SourceOID"].mappedFieldName = "SourceOID"
field_mappings["PosAlong"].mappedFieldName = "PosAlong"
field_mappings["SideOfEdge"].mappedFieldName = "SideOfEdge"
# Load the facilities using the field mappings service_area.load(arcpy.nax.ServiceAreaInputDataType.Facilities,                   input_facilities, field_mappings)

Расчет анализа

Для выполнения анализа вызовите метод solve. Этот метод возвращает объект результата, который можно использовать для работы с результатами анализа, например, для экспорта результатов в класс пространственных объектов.

Если анализ не нашел никаких результатов, например, если маршрут не может быть найден между входными остановками, метод solve не вызывает исключение Python. Чтобы определить, дал ли анализ допустимый результат, используйте свойство solveSucceeded объекта result.

Лицензия:

Для успешной работы solve необходима лицензия на дополнительный модуль Network Analyst. Проверьте эту лицензию до вызова метода solve.

В следующем фрагменте кода показано, как выполнить анализ:

# Check out the Network Analyst extension license. arcpy.CheckOutExtension("network")
# Solve the analysis. result = service_area.solve()

Работа с результатами

После выполнения анализа для работы с результатами используется объект result, полученный из метода solve. Объект result позволяет определить, был ли анализ успешным или неудачным (с использованием свойства solveSucceeded), а также было ли получено частичное решение (с использованием свойства isPartialSolution). Если анализ не удался, можно определить причину с помощью метода solverMessages. Чтобы экспортировать результаты в класс пространственных объектов, используйте метод export.

В следующем фрагменте кода показано, как выполнить анализ и экспортировать результаты в класс пространственных объектов:

# Solve the analysis. result = service_area.solve()
# Export the results to a feature class. If the analysis failed print all the 
# messages. if result.solveSucceeded:
    result.export(arcpy.nax.ServiceAreaOutputDataType.Polygons, output_polygons) else:
    arcpy.AddError("Analysis failed")    # Print all the warning messages.    for message in result.solverMessages(arcpy.nax.MessageSeverity.Warning):
        arcpy.AddWarning(message[-1])    # Print all the error messages.    for message in result.solverMessages(arcpy.nax.MessageSeverity.Error):
        arcpy.AddError(message[-1])

Для отображения только определенной информации из результата, например, общего времени и расстояния от маршрута, используйте метод searchCursor для выполнения перебора объектов результата. Это может быть быстрее, чем экспортировать результаты сначала в класс пространственных объектов, а затем извлекать информацию из класса пространственных объектов.

В следующем фрагменте кода показано, как распечатать общее время и расстояние из данных анализа маршрута с помощью метода searchCursor:

# Solve the analysis. result = route.solve()
with result.searchCursor(arcpy.nax.RouteOutputDataType.Routes, ["Name", "Total_Minutes", "Total_Miles"]) as cur:
    for row in cur:
        print(f"Summary for route: '{row[0]}'")        print(f"Total time: {row[1]} minutes.")        print(f"Total distance: {row[2]} miles.")