<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://wiki.gis-lab.info/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Stopa85</id>
	<title>GIS-Lab - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.gis-lab.info/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Stopa85"/>
	<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/w/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Stopa85"/>
	<updated>2026-04-03T20:50:52Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9A%D0%BE%D0%BD%D1%84%D0%B5%D1%80%D0%B5%D0%BD%D1%86%D0%B8%D1%8F_%C2%AB%D0%9E%D1%82%D0%BA%D1%80%D1%8B%D1%82%D1%8B%D0%B5_%D0%93%D0%98%D0%A1%C2%BB_2012&amp;diff=4922</id>
		<title>Конференция «Открытые ГИС» 2012</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9A%D0%BE%D0%BD%D1%84%D0%B5%D1%80%D0%B5%D0%BD%D1%86%D0%B8%D1%8F_%C2%AB%D0%9E%D1%82%D0%BA%D1%80%D1%8B%D1%82%D1%8B%D0%B5_%D0%93%D0%98%D0%A1%C2%BB_2012&amp;diff=4922"/>
		<updated>2012-04-27T06:55:38Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: /* Место */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Это копилка идей для конференции Открытые ГИС. Она может случится, а может и не случится. Все зависит от активности организаторов.&lt;br /&gt;
&lt;br /&gt;
Обсуждение [http://gis-lab.info/forum/viewtopic.php?f=4&amp;amp;t=9765 на форуме].&lt;br /&gt;
&lt;br /&gt;
== План действий ==&lt;br /&gt;
# Набрать ответственный оргкомитет&lt;br /&gt;
# Проанализировать опыт FOSS4G, GeoStat,... что еще ...&lt;br /&gt;
# Оценка потенциального участия&lt;br /&gt;
# Утвердить название конференции&lt;br /&gt;
# Подобрать варианты места проведения&lt;br /&gt;
# Определиться с тематикой и программой&lt;br /&gt;
# Составить программу&lt;br /&gt;
# Найти спонсоров&lt;br /&gt;
# Найти организацию, которая возьмется собирать взносы&lt;br /&gt;
# Определиться с местом проведения&lt;br /&gt;
# Запустить сайт конференции&lt;br /&gt;
# Пригласить гостей и ключевых докладчиков&lt;br /&gt;
# Прорекламировать конференцию&lt;br /&gt;
# Открытие регистрации, постерные-устные доклады&lt;br /&gt;
# Сбор материалов - редакция, выпуск сборника&lt;br /&gt;
&lt;br /&gt;
== Название конференции ==&lt;br /&gt;
&lt;br /&gt;
Для конференции нужно название :) Название должно быть коротким и звучным. Желательно делать на русском языке (и хорошо бы с английским аналогом). &lt;br /&gt;
&lt;br /&gt;
Варианты (пока все, что приходят в голову):&lt;br /&gt;
# Открытые ГИС: методы, данные, ПО&lt;br /&gt;
# Фестиваль открытых ГИС: методы, данные и ПО // (англ.аналог) - OpenGISFest: data, soft &amp;amp; applications&lt;br /&gt;
# Где карта&lt;br /&gt;
# MorozGeo&lt;br /&gt;
# Русская широта&lt;br /&gt;
# MosOpenGeo&lt;br /&gt;
# Open GIS Conference&lt;br /&gt;
# Открытые геотехнологии&lt;br /&gt;
# Открытая география&lt;br /&gt;
# Геоданные и геотехнологии&lt;br /&gt;
# OpenCarto &lt;br /&gt;
# ГИС-бриз&lt;br /&gt;
# ГИСтограмма&lt;br /&gt;
# Свободные Геоинформационные Технологии ::: Technologia Geospatialis Libera&lt;br /&gt;
# MoscowOpenGis или MosOpenGIS&lt;br /&gt;
# ..ваши варианты&lt;br /&gt;
&lt;br /&gt;
== Таймлайн ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Срок&lt;br /&gt;
! Что должно быть сделано&lt;br /&gt;
|-&lt;br /&gt;
| 13 мая || Выбрать время проведения&lt;br /&gt;
|-&lt;br /&gt;
| 31 мая (?) || Выбрать помещения и забронировать их&lt;br /&gt;
|-&lt;br /&gt;
| 10 июня || Брендирование, потоки, план конференции. Открыть сайт конференции (можно пустой)&lt;br /&gt;
|-&lt;br /&gt;
| 18 июня || Начало приёма докладов, поиск спонсоров&lt;br /&gt;
|-&lt;br /&gt;
| июль-август || Открытие регистрации&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; align=&amp;quot;center&amp;quot; | . . .&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Место ==&lt;br /&gt;
&lt;br /&gt;
Ищем общими усилиями: в интернете, среди знакомых и т.д. Результаты записываем сюда же в таблицу. Потом будем выбирать.&lt;br /&gt;
&lt;br /&gt;
Должно отвечать следующим требованиям:&lt;br /&gt;
&lt;br /&gt;
# г. Москва, ближнее Подмосковье&lt;br /&gt;
# Минимум 3 зала, 2 побольше (100+ человек) и поменьше (20+ человек). Ориентировочно общее количество участников - 200 чел.&lt;br /&gt;
# Wi-fi&lt;br /&gt;
# Наличие проекторов/экранов&lt;br /&gt;
# Для проведения семинаров будут полезны залы со столами, чтобы поставить ноутбуки - наличие/отсутствие можно отмечать в табл в примечаниях&lt;br /&gt;
# Холл для распития чаев и плюшек&lt;br /&gt;
&lt;br /&gt;
С учетом того, что часть участников будет не из Москвы, идеальным будет вариант недорогой гостиницы (интересно, есть такие в Москве/Ближнем Подмосковье ? :)) с конференц-залами. &lt;br /&gt;
&lt;br /&gt;
Варианты где провести:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Название, расположение, сайт !! Стоимость аренды залов!! Кол-во залов/вместимость !! Оборудование (проекторы, экраны, микрофоны)!! Wi-Fi !! Фото !! Примечания&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.google.ru/url?sa=t&amp;amp;rct=j&amp;amp;q=%D0%B8%D0%B3%D1%80%D0%B0%D0%BD%20%D0%B0%D0%B4%D1%80%D0%B5%D1%81&amp;amp;source=web&amp;amp;cd=1&amp;amp;ved=0CDQQFjAA&amp;amp;url=http%3A%2F%2Figras.ru%2F&amp;amp;ei=XF-UT-eLKYabOsG8pfoD&amp;amp;usg=AFQjCNFOa4sTfCZiaWFfdstm7yhdjEa_zg&amp;amp;sig2=eZEivU5rCmjkmCA0XDDJwQ ИГРАН], Москва (м.Полянка) || ... || 1 (60-70 чел) || ... || ... ||[http://images.yandex.ru/yandsearch?rpt=simage&amp;amp;ed=1&amp;amp;text=%D0%98%D0%BD%D1%81%D1%82%D0%B8%D1%82%D1%83%D1%82%20%D0%B3%D0%B5%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%B8%20%D0%A0%D0%90%D0%9D%20%D0%B7%D0%B0%D0%BB%20%D0%B7%D0%B0%D1%81%D0%B5%D0%B4%D0%B0%D0%BD%D0%B8%D0%B9&amp;amp;p=0&amp;amp;img_url=www.eco-plan.ru%2Fgallery%2Fg_2008_05_19_12_36_59_2.jpg фото помещения] || Хорошо:&lt;br /&gt;
* Большая вероятность, что &amp;quot;хозяева&amp;quot; поддержат&lt;br /&gt;
&lt;br /&gt;
Плохо:&lt;br /&gt;
* Скорее всего не хватит места.&lt;br /&gt;
|-&lt;br /&gt;
| [http://nf-conference.ru/ Конференц-центр «На Филипповском»], Москва (Метро: Арбатская, Кропоткинская) || от 9 тыс.руб (20 м&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;) до 36 тыс.руб (200 м&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;) [http://nf-conference.ru/nf-prices.htm Цены] || 8 конференц-залов, на выбор, площадью от 20 до 196 м&amp;lt;sup&amp;gt;&amp;lt;/sup&amp;gt; || Проектор + экран = 5000 - 6000 руб/день, Микрофон 3000 (4500 радио-микрофон) [http://www.nf-conference.ru/File/dogovora/buklet_filipp.pdf Отдельная цена] || бесплатно || [http://nf-conference.ru/nf-photogallery.htm Фотогалерея] || Хорошо: &lt;br /&gt;
* много залов разной вместимости &lt;br /&gt;
* есть оборудование &lt;br /&gt;
* есть питание &lt;br /&gt;
* удобное место &lt;br /&gt;
Плохо: &lt;br /&gt;
* цена &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.alfa-hotel.ru/ Гостиница Измайлово Альфа], Москва (Метро: Партизанская) || 21-35 тыс руб/9 часов [http://www.alfa-hotel.ru/congress/#hall-capacity-anchor Цены] || 9 конференц-залов, на выбор (со столами и без, практически каждый зал трансформируется в тот или иной тип), площадью от 85 до 270 м&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;, вместимость от 50 чел (класс) до 250 чел (тип &amp;quot;театр&amp;quot; - на доклады)|| В стоимость аренды входит 1 микрофон, проектор + экран= 5 000 руб/день (см.в ценах за аренду) || + (то ли бесплатно, то ли [http://www.alfa-hotel.ru/congress/#hall-capacity-anchor 1 500 руб]) || [http://www.alfa-hotel.ru/congress/#hall-capacity-anchor Фотогалерея] || &lt;br /&gt;
* много залов разной вместимости &lt;br /&gt;
* есть оборудование &lt;br /&gt;
* набор скидок  &lt;br /&gt;
* недалеко от центра &lt;br /&gt;
* проживание (пт-сб-вс около 2500/3000 руб двухместный номер)&lt;br /&gt;
* холл для чаев/кофеёв (надо узнавать, можно ли самостоятельно организовывать, т.к. у них дороговато заказывать)&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.aerostar.ru/conferences/ гостиница Аэростар], Москва, Ленинградский проспект, д.37, к. 9 || Зал на 100+ 75 000 рублей/ 8 часов, на 20+ - 25 000 рублей || На 100+ человек - залы Петровский А и Б, 160 м&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; каждый, 1 этаж, вместимость при рассадке театром до 160 человек, 20+ человек - Сокольники/Останкино/Измайлово, 52 м&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;, 1 этаж, вместимость при рассадке театром до 50 человек || В цену аренды включено:&lt;br /&gt;
* аренда зала&lt;br /&gt;
* экран&lt;br /&gt;
* флипчарт&lt;br /&gt;
* ручки+блокноты по числу участников&lt;br /&gt;
* минеральная вода – 1 бутылка на участника&lt;br /&gt;
* до 3 удлинителей&lt;br /&gt;
В цену зала не включено&lt;br /&gt;
* проектор  &lt;br /&gt;
|| Есть. Бесплатно. ||  || &lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Дата проведения и продолжительность ==&lt;br /&gt;
&lt;br /&gt;
Два выходных дня (сб-вс).&lt;br /&gt;
&lt;br /&gt;
* 17-18 ноября (основной вариант)&lt;br /&gt;
* 1-2 декабря (запасной вариант)&lt;br /&gt;
&lt;br /&gt;
== Тематика ==&lt;br /&gt;
Общая тема: всё про геоинформационные системы использующие ПО с открытым исходным кодом.&lt;br /&gt;
&lt;br /&gt;
Секции:&lt;br /&gt;
* Десктоп&lt;br /&gt;
* Веб&lt;br /&gt;
* Базы данных&lt;br /&gt;
* Опыты внедрения&lt;br /&gt;
* Научная секция&lt;br /&gt;
* Открытые данные и ПО - современное состояние в РФ&lt;br /&gt;
&lt;br /&gt;
== Программа ==&lt;br /&gt;
&lt;br /&gt;
День 0 (вечер): Встреча гостей. Pre-party.&lt;br /&gt;
&lt;br /&gt;
День 1. Пленарная часть. Устные доклады (20 мин на доклад, 10 мин на вопросы). В перерывах между основными докладами можно провести секцию со стендовыми докладами.  Банкет! :)&lt;br /&gt;
&lt;br /&gt;
День 2. Семинары и мастер-классы (2x40 мин + 10 мин перерыв; общее время 1,5 часа). &lt;br /&gt;
(Конкурс проектов и работ, выполненных с помощью открытых ГИС. ?)&lt;br /&gt;
&lt;br /&gt;
или наоборот&lt;br /&gt;
&lt;br /&gt;
! Если будет много желающих прийти на семинары, но в один день они все не смогут их посетить физически (один семинар +/- 20 чел.), то, возможно: &lt;br /&gt;
# Не следует разделять на день докладов и день семинаров, а проводить их параллельно разными секциями.&lt;br /&gt;
# Проводить один семинар несколько раз.&lt;br /&gt;
&lt;br /&gt;
Для оценки количества желающих надо будет организовать подсчет голосов на сайте Конференции.&lt;br /&gt;
&lt;br /&gt;
=== Семинары ===&lt;br /&gt;
&lt;br /&gt;
Семинары должны быть практическими с возможностью повторять за тренером. Возможно разделение семинара на две части, для новичков и для продвинутых пользователей.&lt;br /&gt;
&lt;br /&gt;
Возможные темы семинаров:&lt;br /&gt;
&lt;br /&gt;
* Использование R&lt;br /&gt;
* Пространственные базы данных (PostGIS)&lt;br /&gt;
* Программирование для GDAL, обработка ДДЗ высокого разрешения&lt;br /&gt;
* Первые шаги в QGIS&lt;br /&gt;
* Создание модулей расширения для QGIS на Python&lt;br /&gt;
* Обработка атрибутивных данных в QGIS (Pyculator)&lt;br /&gt;
* Sextante на QGIS&lt;br /&gt;
* Использование Network Analysis API в QGIS&lt;br /&gt;
* Создание картографических веб-приложений с OpenLayers, Mapserver&lt;br /&gt;
* OSM&lt;br /&gt;
* GRASS для новичков&lt;br /&gt;
* Использование GRASS в ДЗЗ&lt;br /&gt;
* Использование GRASS в геоморфологии&lt;br /&gt;
* Дешифрирование космических снимков в QGIS/GRASS&lt;br /&gt;
* Вопросы миграции с проприетарных на открытые ГИС&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Интересные темы, которые ждут своих авторов:&lt;br /&gt;
&lt;br /&gt;
* Пространственная статистика, моделирование; R+PostGIS&lt;br /&gt;
* Использование ГИС в мобильных терминалах для полевого сбора данных и навигации&lt;br /&gt;
* Разработка расширений для uDig и gvSIG&lt;br /&gt;
* Основы работы с gvSIG&lt;br /&gt;
* Использование ГИС GRASS в связке с другим СПО (R и т.п.)&lt;br /&gt;
&lt;br /&gt;
Дополнительно хорошая тема: расширенный семинар взаимопомощи или даже несколько? Человек берет 5-7 минут на описание своих проблем и задач, все помогают ему их решить.&lt;br /&gt;
&lt;br /&gt;
=== Участие ===&lt;br /&gt;
К участию приглашаются также и студенты.&lt;br /&gt;
&lt;br /&gt;
Отдельная секция студенческих работ или общая для всех работ?&lt;br /&gt;
&lt;br /&gt;
Перед принятием решения по проведению конференции необходимо провести оценку потенциального участия и составить список потенциальных участников, посредством:&lt;br /&gt;
#опроса на форуме/блоге&lt;br /&gt;
#личного опроса&lt;br /&gt;
#персональной рассылкой с вопросами &amp;quot;Хотите ли вы поучаствовать&amp;quot;, &amp;quot;Можете ли сделать доклад&amp;quot;, &amp;quot;Знаете ли кого-то, кто еще занимается подобным&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Труды ==&lt;br /&gt;
&lt;br /&gt;
Сборник трудов.&lt;br /&gt;
&lt;br /&gt;
Статьи должны присылаться сразу в 2-х форматах: .tex и .pdf.&lt;br /&gt;
&lt;br /&gt;
===Печатать или не печатать?===&lt;br /&gt;
Нужно разобраться с вопросом. Нет ли формальных проблем с только электронной версией материалов? Считается ли электронная публикация - публикацией. Если нет - тогда выпускать только электронно, если есть тогда нужна и печатная версия.&lt;br /&gt;
&lt;br /&gt;
Можно сделать так, спросить людей уже на конференции нужны ли им бумажные материалы и если да, то опубликовать в печатном виде небольшим тиражом.&lt;br /&gt;
&lt;br /&gt;
== Сайт конференции ==&lt;br /&gt;
# Кто будет делать сайт: дизайн и программирование + перевод на англ.язык (надо)?&lt;br /&gt;
# Что на нем должно быть?&lt;br /&gt;
* Вводная и общая информация (о мероприятии, контакты, как добраться, где остановиться)&lt;br /&gt;
* Формы для регистрации, опросники. Общие (делать ли часть инфо общедоступной: например, ФИО, откуда, контакты, возможно, в закрытой форме или просто счетчик зарегистрировавшихся?), отдельные формы регистрации/опросников для семинаров/мастер-классов, сюда же: Если будет так называемый семинар взаимопомощи, то, возможно, нужно предусмотреть какую-то регистрацию на сайте желающих. Так они смогут предварительно разместить свою тему, это будет полезно для планирования общего времени.&lt;br /&gt;
* Тезисы докладов и инфо по авторам (кто/откуда, какие-то контакты), добавить (?) возможность комментировать тезисы, оценивать (?) - с регистрацией на сайте или без?&lt;br /&gt;
* Секции, а затем и полное расписание конференции (со ссылками на абстракты и инфо по авторам)&lt;br /&gt;
* Загрузочные материалы для семинаров или ссылки (данные и литература в т.ч. для предварительной подготовки, если требуется)&lt;br /&gt;
* Карта посетителей и/или карта участников сайта :)&lt;br /&gt;
* Список организаторов, спонсоров, кнопка донейт &lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Реклама конференции ==&lt;br /&gt;
Должна быть активной и всеохватывающей, включая возможность платной рекламы.&lt;br /&gt;
&lt;br /&gt;
# Рассылка по ВУЗам&lt;br /&gt;
# Баннеры и информация на сайтах (GIS-Lab, OSGeo, GISA ...)&lt;br /&gt;
# Рассылка GIS-Lab-news, еще какие-то тематические&lt;br /&gt;
# Реклама в социальных сетях&lt;br /&gt;
&lt;br /&gt;
== Приглашение докладчиков ==&lt;br /&gt;
&lt;br /&gt;
Интересные люди из России и мира, которые могут рассказать о своем опыте и видении настоящего и будущего Открытых ГИС.&lt;br /&gt;
&lt;br /&gt;
Например:&lt;br /&gt;
* Tim Sutton (QGIS)&lt;br /&gt;
* Paul Ramsey (PostGIS/OpenGeo)&lt;br /&gt;
* Frank Warmerdam (GDAL/Google)&lt;br /&gt;
&lt;br /&gt;
Кого еще вы хотели бы видеть?&lt;br /&gt;
* Markus Neteler (GRASS GIS) или кого-либо еще из их команды&lt;br /&gt;
* Carlos H. Grohmann (GRASS GIS)&lt;br /&gt;
&lt;br /&gt;
== Деньги ==&lt;br /&gt;
&lt;br /&gt;
Участие можно сделать платным.&lt;br /&gt;
&lt;br /&gt;
Организационный взнос, например, 100500 копеек.&lt;br /&gt;
&lt;br /&gt;
== Организаторы ==&lt;br /&gt;
Выразили желание помочь с организацией:&lt;br /&gt;
&lt;br /&gt;
# SS_Rebelious&lt;br /&gt;
# Amuriy (реклама)&lt;br /&gt;
# Rhot (перевод материалов на англ.язык)&lt;br /&gt;
# KolesovDmitry (рекламная рассылка по ВУЗам, подготовка сборника трудов)&lt;br /&gt;
# Bishop&lt;br /&gt;
# Evgenia &lt;br /&gt;
# yellow_sky&lt;br /&gt;
# Максим Дубинин (поиск спонсоров)&lt;br /&gt;
&lt;br /&gt;
== Партнеры ==&lt;br /&gt;
* Информационные партнеры&lt;br /&gt;
* Спонсоры/Рекламодатели&lt;br /&gt;
&lt;br /&gt;
[[Категория:Служебные]]&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9A%D0%BE%D0%BD%D1%84%D0%B5%D1%80%D0%B5%D0%BD%D1%86%D0%B8%D1%8F_%C2%AB%D0%9E%D1%82%D0%BA%D1%80%D1%8B%D1%82%D1%8B%D0%B5_%D0%93%D0%98%D0%A1%C2%BB_2012&amp;diff=4883</id>
		<title>Конференция «Открытые ГИС» 2012</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9A%D0%BE%D0%BD%D1%84%D0%B5%D1%80%D0%B5%D0%BD%D1%86%D0%B8%D1%8F_%C2%AB%D0%9E%D1%82%D0%BA%D1%80%D1%8B%D1%82%D1%8B%D0%B5_%D0%93%D0%98%D0%A1%C2%BB_2012&amp;diff=4883"/>
		<updated>2012-04-26T12:03:53Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: /* Место */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Это копилка идей для конференции Открытые ГИС. Она может случится, а может и не случится. Все зависит от активности организаторов.&lt;br /&gt;
&lt;br /&gt;
Обсуждение [http://gis-lab.info/forum/viewtopic.php?f=4&amp;amp;t=9765 на форуме].&lt;br /&gt;
&lt;br /&gt;
== План действий ==&lt;br /&gt;
# Набрать ответственный оргкомитет&lt;br /&gt;
# Проанализировать опыт FOSS4G, GeoStat,... что еще ...&lt;br /&gt;
# Оценка потенциального участия&lt;br /&gt;
# Утвердить название конференции&lt;br /&gt;
# Подобрать варианты места проведения&lt;br /&gt;
# Определиться с тематикой и программой&lt;br /&gt;
# Составить программу&lt;br /&gt;
# Найти спонсоров&lt;br /&gt;
# Найти организацию, которая возьмется собирать взносы&lt;br /&gt;
# Определиться с местом проведения&lt;br /&gt;
# Запустить сайт конференции&lt;br /&gt;
# Пригласить гостей и ключевых докладчиков&lt;br /&gt;
# Прорекламировать конференцию&lt;br /&gt;
# Открытие регистрации, постерные-устные доклады&lt;br /&gt;
# Сбор материалов - редакция, выпуск сборника&lt;br /&gt;
&lt;br /&gt;
== Название конференции ==&lt;br /&gt;
&lt;br /&gt;
Для конференции нужно название :) Название должно быть коротким и звучным. Желательно делать на русском языке (и хорошо бы с английским аналогом). &lt;br /&gt;
&lt;br /&gt;
Варианты (пока все, что приходят в голову):&lt;br /&gt;
# Открытые ГИС: методы, данные, ПО&lt;br /&gt;
# Фестиваль открытых ГИС: методы, данные и ПО // (англ.аналог) - OpenGISFest: data, soft &amp;amp; applications&lt;br /&gt;
# Где карта&lt;br /&gt;
# MorozGeo&lt;br /&gt;
# Русская широта&lt;br /&gt;
# MosOpenGeo&lt;br /&gt;
# Open GIS Conference&lt;br /&gt;
# Открытые геотехнологии&lt;br /&gt;
# Открытая география&lt;br /&gt;
# Геоданные и геотехнологии&lt;br /&gt;
# OpenCarto &lt;br /&gt;
# ГИС-бриз&lt;br /&gt;
# ГИСтограмма&lt;br /&gt;
# Свободные Геоинформационные Технологии ::: Technologia Geospatialis Libera&lt;br /&gt;
# MoscowOpenGis или MosOpenGIS&lt;br /&gt;
# ..ваши варианты&lt;br /&gt;
&lt;br /&gt;
== Таймлайн ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Срок&lt;br /&gt;
! Что должно быть сделано&lt;br /&gt;
|-&lt;br /&gt;
| 13 мая || Выбрать время проведения&lt;br /&gt;
|-&lt;br /&gt;
| 31 мая (?) || Выбрать помещения и забронировать их&lt;br /&gt;
|-&lt;br /&gt;
| 10 июня || Брендирование, потоки, план конференции. Открыть сайт конференции (можно пустой)&lt;br /&gt;
|-&lt;br /&gt;
| 18 июня || Начало приёма докладов, поиск спонсоров&lt;br /&gt;
|-&lt;br /&gt;
| июль-август || Открытие регистрации&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; align=&amp;quot;center&amp;quot; | . . .&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Место ==&lt;br /&gt;
&lt;br /&gt;
Ищем общими усилиями: в интернете, среди знакомых и т.д. Результаты записываем сюда же в таблицу. Потом будем выбирать.&lt;br /&gt;
&lt;br /&gt;
Должно отвечать следующим требованиям:&lt;br /&gt;
&lt;br /&gt;
# г. Москва, ближнее Подмосковье&lt;br /&gt;
# Минимум 3 зала, 2 побольше (100+ человек) и поменьше (20+ человек). Ориентировочно общее количество участников - 200 чел.&lt;br /&gt;
# Wi-fi&lt;br /&gt;
# Наличие проекторов/экранов&lt;br /&gt;
# Для проведения семинаров будут полезны залы со столами, чтобы поставить ноутбуки - наличие/отсутствие можно отмечать в табл в примечаниях&lt;br /&gt;
# Холл для распития чаев и плюшек&lt;br /&gt;
&lt;br /&gt;
С учетом того, что часть участников будет не из Москвы, идеальным будет вариант недорогой гостиницы (интересно, есть такие в Москве/Ближнем Подмосковье ? :)) с конференц-залами. &lt;br /&gt;
&lt;br /&gt;
Варианты где провести:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Название, расположение, сайт !! Стоимость аренды залов!! Кол-во залов/вместимость !! Оборудование (проекторы, экраны, микрофоны)!! Wi-Fi !! Фото !! Примечания&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.google.ru/url?sa=t&amp;amp;rct=j&amp;amp;q=%D0%B8%D0%B3%D1%80%D0%B0%D0%BD%20%D0%B0%D0%B4%D1%80%D0%B5%D1%81&amp;amp;source=web&amp;amp;cd=1&amp;amp;ved=0CDQQFjAA&amp;amp;url=http%3A%2F%2Figras.ru%2F&amp;amp;ei=XF-UT-eLKYabOsG8pfoD&amp;amp;usg=AFQjCNFOa4sTfCZiaWFfdstm7yhdjEa_zg&amp;amp;sig2=eZEivU5rCmjkmCA0XDDJwQ ИГРАН], Москва (м.Полянка) || ... || 1 (60-70 чел) || ... || ... ||[http://images.yandex.ru/yandsearch?rpt=simage&amp;amp;ed=1&amp;amp;text=%D0%98%D0%BD%D1%81%D1%82%D0%B8%D1%82%D1%83%D1%82%20%D0%B3%D0%B5%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%B8%20%D0%A0%D0%90%D0%9D%20%D0%B7%D0%B0%D0%BB%20%D0%B7%D0%B0%D1%81%D0%B5%D0%B4%D0%B0%D0%BD%D0%B8%D0%B9&amp;amp;p=0&amp;amp;img_url=www.eco-plan.ru%2Fgallery%2Fg_2008_05_19_12_36_59_2.jpg фото помещения] || Хорошо:&lt;br /&gt;
* Большая вероятность, что &amp;quot;хозяева&amp;quot; поддержат&lt;br /&gt;
&lt;br /&gt;
Плохо:&lt;br /&gt;
* Скорее всего не хватит места.&lt;br /&gt;
|-&lt;br /&gt;
| [http://nf-conference.ru/ Конференц-центр «На Филипповском»], Москва (Метро: Арбатская, Кропоткинская) || [http://nf-conference.ru/nf-prices.htm Цены] || 8 конференц-залов, на выбор, площадью от 20 до 196 кв.м. || [http://www.nf-conference.ru/File/dogovora/buklet_filipp.pdf Отдельная цена] || ??? || [http://nf-conference.ru/nf-photogallery.htm Фотогалерея] || Хорошо: &lt;br /&gt;
* много залов разной вместимости &lt;br /&gt;
* есть оборудование &lt;br /&gt;
* есть питание &lt;br /&gt;
* удобное место &lt;br /&gt;
Плохо: &lt;br /&gt;
* цена &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.alfa-hotel.ru/ Гостиница Измайлово Альфа], Москва (Метро: Партизанская) || 21-35 тыс руб/9 часов [http://www.alfa-hotel.ru/congress/#hall-capacity-anchor Цены] || 9 конференц-залов, на выбор (со столами и без, практически каждый зал трансформируется в тот или иной тип), площадью от 85 до 270 кв.м., вместимость от 50 чел (класс) до 250 чел (тип &amp;quot;театр&amp;quot; - на доклады)|| В стоимость аренды входит 1 микрофон, проектор + экран= 5 000 руб/день (см.в ценах за аренду) || + (то ли бесплатно, то ли [http://www.alfa-hotel.ru/congress/#hall-capacity-anchor 1 500 руб]) || [http://www.alfa-hotel.ru/congress/#hall-capacity-anchor Фотогалерея] || &lt;br /&gt;
* много залов разной вместимости &lt;br /&gt;
* есть оборудование &lt;br /&gt;
* набор скидок  &lt;br /&gt;
* недалеко от центра &lt;br /&gt;
* проживание (пт-сб-вс около 2500/3000 руб двухместный номер)&lt;br /&gt;
* холл для чаев/кофеёв (надо узнавать, можно ли самостоятельно организовывать, т.к. у них дороговато заказывать)&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.aerostar.ru/conferences/ гостиница Аэростар], Москва, Ленинградский проспект, д.37, к. 9 || Зал на 100+ 75 000 рублей/ 8 часов, на 20+ - 25 000 рублей || На 100+ человек - залы Петровский А и Б, 160 кв.м каждый, 1 этаж, вместимость при рассадке театром до 160 человек, 20+ человек - Сокольники/Останкино/Измайлово, 52 кв.м, 1 этаж, вместимость при рассадке театром до 50 человек || В цену аренды включено:&lt;br /&gt;
* аренда зала&lt;br /&gt;
* экран&lt;br /&gt;
* флипчарт&lt;br /&gt;
* ручки+блокноты по числу участников&lt;br /&gt;
* минеральная вода – 1 бутылка на участника&lt;br /&gt;
* до 3 удлинителей  &lt;br /&gt;
|| Есть. Бесплатно. ||  || &lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Дата проведения и продолжительность ==&lt;br /&gt;
&lt;br /&gt;
Два выходных дня (сб-вс).&lt;br /&gt;
&lt;br /&gt;
* 17-18 ноября (основной вариант)&lt;br /&gt;
* 1-2 декабря (запасной вариант)&lt;br /&gt;
&lt;br /&gt;
== Тематика ==&lt;br /&gt;
Общая тема: всё про геоинформационные системы использующие ПО с открытым исходным кодом.&lt;br /&gt;
&lt;br /&gt;
Секции:&lt;br /&gt;
* Десктоп&lt;br /&gt;
* Веб&lt;br /&gt;
* Базы данных&lt;br /&gt;
* Опыты внедрения&lt;br /&gt;
* Научная секция&lt;br /&gt;
* Открытые данные и ПО - современное состояние в РФ&lt;br /&gt;
&lt;br /&gt;
== Программа ==&lt;br /&gt;
&lt;br /&gt;
День 0 (вечер): Встреча гостей. Pre-party.&lt;br /&gt;
&lt;br /&gt;
День 1. Пленарная часть. Устные доклады (20 мин на доклад, 10 мин на вопросы). В перерывах между основными докладами можно провести секцию со стендовыми докладами.  Банкет! :)&lt;br /&gt;
&lt;br /&gt;
День 2. Семинары и мастер-классы (2x40 мин + 10 мин перерыв; общее время 1,5 часа). &lt;br /&gt;
(Конкурс проектов и работ, выполненных с помощью открытых ГИС. ?)&lt;br /&gt;
&lt;br /&gt;
или наоборот&lt;br /&gt;
&lt;br /&gt;
! Если будет много желающих прийти на семинары, но в один день они все не смогут их посетить физически (один семинар +/- 20 чел.), то, возможно: &lt;br /&gt;
# Не следует разделять на день докладов и день семинаров, а проводить их параллельно разными секциями.&lt;br /&gt;
# Проводить один семинар несколько раз.&lt;br /&gt;
&lt;br /&gt;
Для оценки количества желающих надо будет организовать подсчет голосов на сайте Конференции.&lt;br /&gt;
&lt;br /&gt;
=== Семинары ===&lt;br /&gt;
&lt;br /&gt;
Семинары должны быть практическими с возможностью повторять за тренером. Возможно разделение семинара на две части, для новичков и для продвинутых пользователей.&lt;br /&gt;
&lt;br /&gt;
Возможные темы семинаров:&lt;br /&gt;
&lt;br /&gt;
* Использование R&lt;br /&gt;
* Пространственные базы данных (PostGIS)&lt;br /&gt;
* Программирование для GDAL, обработка ДДЗ высокого разрешения&lt;br /&gt;
* Первые шаги в QGIS&lt;br /&gt;
* Создание модулей расширения для QGIS на Python&lt;br /&gt;
* Обработка атрибутивных данных в QGIS (Pyculator)&lt;br /&gt;
* Sextante на QGIS&lt;br /&gt;
* Использование Network Analysis API в QGIS&lt;br /&gt;
* Создание картографических веб-приложений с OpenLayers, Mapserver&lt;br /&gt;
* OSM&lt;br /&gt;
* GRASS для новичков&lt;br /&gt;
* Использование GRASS в ДЗЗ&lt;br /&gt;
* Использование GRASS в геоморфологии&lt;br /&gt;
* Дешифрирование космических снимков в QGIS/GRASS&lt;br /&gt;
* Вопросы миграции с проприетарных на открытые ГИС&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Интересные темы, которые ждут своих авторов:&lt;br /&gt;
&lt;br /&gt;
* Пространственная статистика, моделирование; R+PostGIS&lt;br /&gt;
* Использование ГИС в мобильных терминалах для полевого сбора данных и навигации&lt;br /&gt;
* Разработка расширений для uDig и gvSIG&lt;br /&gt;
* Основы работы с gvSIG&lt;br /&gt;
* Использование ГИС GRASS в связке с другим СПО (R и т.п.)&lt;br /&gt;
&lt;br /&gt;
Дополнительно хорошая тема: расширенный семинар взаимопомощи или даже несколько? Человек берет 5-7 минут на описание своих проблем и задач, все помогают ему их решить.&lt;br /&gt;
&lt;br /&gt;
=== Участие ===&lt;br /&gt;
К участию приглашаются также и студенты.&lt;br /&gt;
&lt;br /&gt;
Отдельная секция студенческих работ или общая для всех работ?&lt;br /&gt;
&lt;br /&gt;
Перед принятием решения по проведению конференции необходимо провести оценку потенциального участия и составить список потенциальных участников, посредством:&lt;br /&gt;
#опроса на форуме/блоге&lt;br /&gt;
#личного опроса&lt;br /&gt;
#персональной рассылкой с вопросами &amp;quot;Хотите ли вы поучаствовать&amp;quot;, &amp;quot;Можете ли сделать доклад&amp;quot;, &amp;quot;Знаете ли кого-то, кто еще занимается подобным&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Труды ==&lt;br /&gt;
&lt;br /&gt;
Сборник трудов.&lt;br /&gt;
&lt;br /&gt;
Статьи должны присылаться сразу в 2-х форматах: .tex и .pdf.&lt;br /&gt;
&lt;br /&gt;
===Печатать или не печатать?===&lt;br /&gt;
Нужно разобраться с вопросом. Нет ли формальных проблем с только электронной версией материалов? Считается ли электронная публикация - публикацией. Если нет - тогда выпускать только электронно, если есть тогда нужна и печатная версия.&lt;br /&gt;
&lt;br /&gt;
Можно сделать так, спросить людей уже на конференции нужны ли им бумажные материалы и если да, то опубликовать в печатном виде небольшим тиражом.&lt;br /&gt;
&lt;br /&gt;
== Сайт конференции ==&lt;br /&gt;
# Кто будет делать сайт: дизайн и программирование + перевод на англ.язык (надо)?&lt;br /&gt;
# Что на нем должно быть?&lt;br /&gt;
* Вводная и общая информация (о мероприятии, контакты, как добраться, где остановиться)&lt;br /&gt;
* Формы для регистрации, опросники. Общие (делать ли часть инфо общедоступной: например, ФИО, откуда, контакты, возможно, в закрытой форме или просто счетчик зарегистрировавшихся?), отдельные формы регистрации/опросников для семинаров/мастер-классов, сюда же: Если будет так называемый семинар взаимопомощи, то, возможно, нужно предусмотреть какую-то регистрацию на сайте желающих. Так они смогут предварительно разместить свою тему, это будет полезно для планирования общего времени.&lt;br /&gt;
* Тезисы докладов и инфо по авторам (кто/откуда, какие-то контакты), добавить (?) возможность комментировать тезисы, оценивать (?) - с регистрацией на сайте или без?&lt;br /&gt;
* Секции, а затем и полное расписание конференции (со ссылками на абстракты и инфо по авторам)&lt;br /&gt;
* Загрузочные материалы для семинаров или ссылки (данные и литература в т.ч. для предварительной подготовки, если требуется)&lt;br /&gt;
* Карта посетителей и/или карта участников сайта :)&lt;br /&gt;
* Список организаторов, спонсоров, кнопка донейт &lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Реклама конференции ==&lt;br /&gt;
Должна быть активной и всеохватывающей, включая возможность платной рекламы.&lt;br /&gt;
&lt;br /&gt;
# Рассылка по ВУЗам&lt;br /&gt;
# Баннеры и информация на сайтах (GIS-Lab, OSGeo, GISA ...)&lt;br /&gt;
# Рассылка GIS-Lab-news, еще какие-то тематические&lt;br /&gt;
# Реклама в социальных сетях&lt;br /&gt;
&lt;br /&gt;
== Приглашение докладчиков ==&lt;br /&gt;
&lt;br /&gt;
Интересные люди из России и мира, которые могут рассказать о своем опыте и видении настоящего и будущего Открытых ГИС.&lt;br /&gt;
&lt;br /&gt;
Например:&lt;br /&gt;
* Tim Sutton (QGIS)&lt;br /&gt;
* Paul Ramsey (PostGIS/OpenGeo)&lt;br /&gt;
* Frank Warmerdam (GDAL/Google)&lt;br /&gt;
&lt;br /&gt;
Кого еще вы хотели бы видеть?&lt;br /&gt;
* Markus Neteler (GRASS GIS) или кого-либо еще из их команды&lt;br /&gt;
* Carlos H. Grohmann (GRASS GIS)&lt;br /&gt;
&lt;br /&gt;
== Деньги ==&lt;br /&gt;
&lt;br /&gt;
Участие можно сделать платным.&lt;br /&gt;
&lt;br /&gt;
Организационный взнос, например, 100500 копеек.&lt;br /&gt;
&lt;br /&gt;
== Организаторы ==&lt;br /&gt;
Выразили желание помочь с организацией:&lt;br /&gt;
&lt;br /&gt;
# SS_Rebelious&lt;br /&gt;
# Amuriy (реклама)&lt;br /&gt;
# Rhot (перевод материалов на англ.язык)&lt;br /&gt;
# KolesovDmitry (рекламная рассылка по ВУЗам, подготовка сборника трудов)&lt;br /&gt;
# Bishop&lt;br /&gt;
# Evgenia &lt;br /&gt;
# yellow_sky&lt;br /&gt;
# Максим Дубинин (поиск спонсоров)&lt;br /&gt;
&lt;br /&gt;
== Партнеры ==&lt;br /&gt;
* Информационные партнеры&lt;br /&gt;
* Спонсоры/Рекламодатели&lt;br /&gt;
&lt;br /&gt;
[[Категория:Служебные]]&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=1795</id>
		<title>Поиск кратчайшего маршрута c помощью Road graph для QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=1795"/>
		<updated>2012-01-31T04:35:55Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: /* Библиотека QGIS network-analysis */  Поправил ссылку&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Опубликована|road-graph2}}&lt;br /&gt;
{{Аннотация|Статья содержит подробное описание расширения свободной к ГИС Quantum GIS модуля Road Graph.}}&lt;br /&gt;
Road graph — расширение свободной ГИС с открытым исходным кодом Quantum GIS, позволяющее осуществлять поиск оптимального маршрута на заданном графе дорог. Расширение автоматически устанавливается вместе с QGIS, начиная с версии 1.6, автор модуля — Сергей Якушев ([http://gis-lab.info/forum/memberlist.php?mode=viewprofile&amp;amp;u=7751 stopa85]).&lt;br /&gt;
&lt;br /&gt;
Эта статья - расширенное описание модуля, старую, упрощенную версию описания можно найти [http://gis-lab.info/qa/road-graph.html здесь].&lt;br /&gt;
&lt;br /&gt;
Для начала работы нужно установить и активировать модуль и загрузить в QGIS линейный векторный слой по которому нужно проложить маршрут, например из данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. Далее, используя инструменты модуля можно легко найти путь от одной заданной точки к другой, указав их на карте. Маршрут можно оптимизировать по расстоянию (самый короткий) или по времени (самый быстрый). Далее в статье подробно рассматриваются все пункты работы с модулем.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph2.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c активированным Road graph. Загружены слои OSM на Тюменскую область, красным цветом отображается проложенный маршрут.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Установка ===&lt;br /&gt;
&lt;br /&gt;
Road graph является расширением ядра QGIS, поэтому достаточно установить QGIS со всеми зависимостями ([http://gis-lab.info/qa/qgis-osgeo4w.html подробнее]) и в Менеджере модулей («Модули — Управление модулями») активировать модуль Road graph.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-01.png|frame|center|&amp;lt;center&amp;gt;Активация Road graph в Менеджере модулей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
После активации модуль добавляет свою панель в левой части окна QGIS и создает вложенный пункт в меню «Вектор» (новые экспериментальные версии QGIS) или пункт в меню «Модули» (Версии QGIS 1.6, 1.7). Панель может быть скрыта/показана с помощью пункта меню «Вид — Панели — Кратчайший маршрут».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-02.png|frame|center|&amp;lt;center&amp;gt;Панель модуля Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
Основные возможности расширения:&lt;br /&gt;
* расчет маршрута, его протяженности и времени пути&lt;br /&gt;
* оптимизация по критерию расстояния или времени&lt;br /&gt;
* экспорт маршрута в векторный слой&lt;br /&gt;
&lt;br /&gt;
В версиях QGIS 1.6, 1.7 присутствует возможность подсветки направления движения дорог (работает медленно, чаще всего используется в целях проверки настроек). В будущих релизах QGIS данная возможность будет удалена. Эффекта подсветки направления можно легко добиться настраивая стиль отображения слоя.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Road direction.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c подсветкой направления дорог, реализованной при помощи стилей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
В качестве слоя дорог можно использовать любой линейный векторный слой в формате, поддерживаемом QGIS. Две линии, имеющие общую точку считаются связанными между собой. &lt;br /&gt;
&lt;br /&gt;
'''ВНИМАНИЕ''': при редактировании слоя дорог в качестве СК проекта необходимо использовать СК слоя. Это&lt;br /&gt;
вызвано тем, что при пересчете координат между разными СК возникают погрешности, что может приводить к появлению разрывов даже при включенном «прилипании».&lt;br /&gt;
&lt;br /&gt;
В атрибутивной таблице слоя могут присутствовать и использоваться в работе расширения следующие поля:&lt;br /&gt;
* скорость движения по участку дороги — числовое поле&lt;br /&gt;
* направление движения — любой тип, приводимый к строке. Прямое и обратное направления соответствуют односторонней дороге, оба направления — двусторонней.&lt;br /&gt;
&lt;br /&gt;
Если значение какого-либо поля не задано, или поле отсутствует — используется значение по умолчанию, изменить которое можно в [[RoadGraph docs#Настройки модуля|настройках расширения]].&lt;br /&gt;
&lt;br /&gt;
Выбор начальной и конечной точек маршрута выполняется при помощи соответствующих кнопок возле полей ввода. Координаты выбранных точек будут отображены в полях ввода.&lt;br /&gt;
&lt;br /&gt;
Нажатие на кнопку «Рассчитать» запустит поиск кратчайшего маршрута с использованием критерия оптимизации, заданного выпадающим списком «Критерий». Кнопка «Экспорт» служит для экспорта построенного маршрута в новый векторный слой, а при помощи кнопки «Очистить» выполняется очистка полей с координатами начальной и конечной точек, а также из области карты удаляются сами точки и построенный маршрут. Краткую справку по работе с модулем можно получить нажав кнопку «Справка».&lt;br /&gt;
&lt;br /&gt;
==== Настройки модуля ====&lt;br /&gt;
&lt;br /&gt;
Перед использованием рекомендуется выполнить настроку модуля. Для этого вызовите диалог настройки из меню «Вектор — Road graph — Параметры модуля Road graph».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-03.png|frame|center|&amp;lt;center&amp;gt;Диалог настройки Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Здесь задаются предпочитаемые единицы измерения времени и расстояния, топологический порог и настраивается распознавание характера движения по дорогам. Если первые два параметра не требуют дополнительных пояснений, то остальные мы рассмотрим подробнее.&lt;br /&gt;
&lt;br /&gt;
При использовании слоя дорог, в котором присутствуют артефакты в виде небольших разрывов между вершинами полилиний, необходимо установить «топологический порог». Топологический порог (или топологическая толерантность) — это расстояние между двумя соседними вершинами, при котором они интерпретируются как одна и та же вершина графа. Эта величина должна быть как можно меньше (чем меньше — тем лучше). Не стоит полагаться на параметр топологической толерантности как на панацею, лучше если Ваши данные будут приведены к «правильному» виду.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_without_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с нулевой топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_with_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с ненулевой (0.00005) топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Модуль может правильно обрабатывать дороги с разным характером движения: одностроннее или двустороннее. Для этого необходимо, чтобы в атрибутивной таблице слоя присутствовало поле с указанием типа дороги. Его нужно выбрать в выпадающем списке «Поле направления» с настройках модуля и задать значения для прямого, обратного и двустороннего движения. Под прямым направлением понимается движение в порядке создания точек линии, от первой точки к последней. Соответственно, обратное направление это движение от последней точки линии к первой. Эти два варианта задают односторонние дороги.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим настройку на примере данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. В качестве поля направления выбираем «oneway», тогда двусторонней дороге будет соответствовать значение «no», прямому направлению односторонней дороги будет соответствовать значение «yes», a обратному — какое-либо другое значение, например «-1». На вкладке «По умолчанию» для поля «Направление» выбираем «Двустороннее направление», чтобы дороги, не подпадающие под описанную выше схему трактовались как двусторонние. Все, теперь модуль будет различать дороги и строить маршруты с учетом характера движения по дорогам.&lt;br /&gt;
&lt;br /&gt;
Здесь же можно указать в каком поле находится информация о скорости движения по данному участку дороги. Если такое поле присутствует, то становится возможной оптимизация маршрута не только по расстоянию, но и по времени движения.&lt;br /&gt;
&lt;br /&gt;
На вкладке «По умолчанию» задаются значения параметров по умолчанию, которые будут использоваться, если модуль не сможет извлечь информацию из указанных полей или если эти поля отсутствуют.&lt;br /&gt;
&lt;br /&gt;
=== Библиотека QGIS network-analysis ===&lt;br /&gt;
&lt;br /&gt;
В настоящее время, в экспериментальных версиях QGIS базовый функционал плагина вынесен в отдельную библиотеку [[Библиотека_сетевого_анализа_QGIS:_описание_и_примеры|network-analysis]], что делает возможным использование алгоритмов сетевого анализа реализованных в модуле из Консоли Python QGIS, а также в своих расширениях.&lt;br /&gt;
[[Категория:Расширения QGIS]]&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1414</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1414"/>
		<updated>2012-01-23T02:48:25Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: /* Нахождение областей доступности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class='ann'&amp;gt;В статье описаны основные сведения и приемы работы с QGIS network-analysis library — библиотекой сетевого анализа ГИС Quantum GIS. Статья дополнена готовыми скриптами-примерами, которые можно использовать при разработке своих расширений.&amp;lt;/p&amp;gt; &lt;br /&gt;
&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Выполнить анализ графа&lt;br /&gt;
# Использовать результат анализа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с этим графом. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы, имеющие одинаковые координаты, считаются одной и той же вершиной графа. Таким образом, две линии, имеющие общий узел, оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому, при построении графа можно «привязать» к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие — либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ребро будет разбито на две части и будет добавлена новая общая вершина.&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф с двумя дополнительными («привязанными») точками. Красной точке соответствует вершина №5. Зеленой точке соответствует новая добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
В качестве свойств ребер графа могут быть использованы атрибуты векторного слоя и протяженность (длина) ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор задает основные настройки, которые будут использоваться при построении графа по линейному векторному слою, и «руками» строителя [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder] выполняет создание графа типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. В настоящее время, как и в случае с директором, реализован только один строитель: &amp;lt;tt&amp;gt;QgsGraphBuilder&amp;lt;/tt&amp;gt;, создающий граф &amp;lt;tt&amp;gt;QgsGraph&amp;lt;/tt&amp;gt;. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется шаблон проектирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим процесс создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества объектов в слое и размера самого слоя). В &amp;lt;tt&amp;gt;tiedPoints&amp;lt;/tt&amp;gt; записываются координаты «привязанных» точек. После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способом представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:network-analysis-01.png|350px|thumb|left|&amp;lt;center&amp;gt;Исходный граф&amp;lt;/center&amp;gt;]] || &lt;br /&gt;
[[Файл:network-analysis-02.png|350px|thumb|right|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей — это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* только одна вершина не имеет входящих в нее ребер — корень дерева&lt;br /&gt;
* все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь, соединяющий их, единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить вызывая методы shortestTree и dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Рекомендуется пользоваться именно методом &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;. Он работает быстрее и, в общем случае, эффективнее расходует память. Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; может быть полезен в тех случаях когда необходимо совершить обход дерева кратчайших путей.&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер свойства ребра (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры, но возвращает не граф, а кортеж из двух массивов. В первом массиве i-ый элемент содержит индекс дуги, входящей в i-ю вершину, в противном случае — -1. Во втором массиве i-ый элемент содержит расстояние от корня дерева до i-ой вершины, если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности), если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей с использованием графа, полученного в результате вызова метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты). '''ОСТОРОЖНО''': код создает огромное количество объектов [http://doc.qgis.org/api/classQgsRubberBand.html QgsRubberBand], используйте его только для очень маленьких слоев.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То же самое, но с использованием метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -1.37144, 0.543836 )&lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-05.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта — дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения оптимального маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; находится дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B и начинаем спуск по дереву от точки B к точке А. В общем виде алгоритм можно записать так:&lt;br /&gt;
&lt;br /&gt;
# присвоим Т = B&lt;br /&gt;
# пока Т != A цикл&lt;br /&gt;
## добавляем в маршрут точку Т&lt;br /&gt;
## берем ребро, которое входит в точку Т&lt;br /&gt;
## находим точку ТТ, из которой это ребро выходит&lt;br /&gt;
## присваиваем Т = ТТ&lt;br /&gt;
# добавляем в маршрут точку А&lt;br /&gt;
&lt;br /&gt;
На этом построение маршрута закончено. Мы получили инвертированный список вершин (т.е. вершины идут в обратном порядке, от конечной точки к начальной), которые будут посещены при движении по кратчайшему маршруту.&lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|дерево кратчайших путей]] и представьте, что вы можете двигаться только против направления стрелочек. При движении из точки №7 мы рано или поздно попадем в точку №1 (корень дерева) и не сможем двигаться дальше.&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример поиска кратчайшего маршрута для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты) с использованием метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print &amp;quot;Path not found&amp;quot;&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while ( idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А вот пример с использованием метода &amp;lt;tt&amp;gt;dikstra&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print &amp;quot;Path not found&amp;quot;&lt;br /&gt;
else:&lt;br /&gt;
  p = [] &lt;br /&gt;
  curPos = idStop&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-06.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта — кратчайший путь&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
Назовем областью доступности вершины графа А такое подмножество вершин графа, доступных из вершины А, что стоимость оптимального пути от А до элементов этого множества не превосходит некоторого заданного значения.&lt;br /&gt;
&lt;br /&gt;
Более наглядно это определение можно объяснить на следующем примере: «Есть пожарное депо. В какую часть города сможет попасть пожарная машина в за 5 минут, 10 минут, 15 минут?». Ответом на этот вопрос и являются области доступности пожарного депо.&lt;br /&gt;
&lt;br /&gt;
Поиск областей доступности легко реализовать при помощи метода &amp;lt;tt&amp;gt;dijksta&amp;lt;/tt&amp;gt; класса &amp;lt;tt&amp;gt;QgsGraphAnalyzer&amp;lt;/tt&amp;gt;. Достаточно сравнить элементы возвращаемого значения с заданным параметром. Если величина &amp;lt;tt&amp;gt;cost[ i ]&amp;lt;/tt&amp;gt; меньше заданного параметра или равна ему, тогда i-я вершина графа принадлежит множеству доступности, в противном случае — не принадлежит.&lt;br /&gt;
&lt;br /&gt;
Не столь очевидным является нахождение границ доступности. Нижняя граница доступности — множество вершин которые '''еще''' можно достигнуть, а верхняя граница — множество вершин которых '''уже''' нельзя достигнуть. На самом деле все просто: граница доступности проходит по таким ребрам дерева кратчайших путей, для которых вершина-источник ребра доступна, а вершина-цель недоступна.&lt;br /&gt;
&lt;br /&gt;
Вот пример&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( 65.5462, 57.1509 )&lt;br /&gt;
delta = qgis.utils.iface.mapCanvas().getCoordinateTransform().mapUnitsPerPixel() * 1&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
rb.setColor( Qt.green )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() + delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
&lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
upperBound = []&lt;br /&gt;
r = 2000.0&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; len(cost):&lt;br /&gt;
  if cost[ i ] &amp;gt; r and tree[ i ] != -1:&lt;br /&gt;
    outVertexId = graph.arc( tree [ i ] ).outVertex()&lt;br /&gt;
    if cost[ outVertexId ] &amp;lt; r:&lt;br /&gt;
      upperBound.append( i )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
for i in upperBound:&lt;br /&gt;
  centerPoint = graph.vertex( i ).point()&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() + delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() + delta ) )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-04.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Зеленый квадратик — центр области, крастные квадаратики — верхняя граница доступности, вершины '''уже''' не входящие в область.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1330</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1330"/>
		<updated>2012-01-22T12:23:50Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class='ann'&amp;gt;В статье описаны основные сведения и приемы работы с QGIS network-analysis library - библиотекой сетевого анализа ГИС Quantum GIS. Статья дополнена готовыми скриптами-примерами, которые можно использовать при разработке своих расширений QGIS&amp;lt;/p&amp;gt; &lt;br /&gt;
&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества объектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способом представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:network-analysis-01.png|350px|thumb|left|&amp;lt;center&amp;gt;Исходный граф&amp;lt;/center&amp;gt;]] || &lt;br /&gt;
[[Файл:network-analysis-02.png|350px|thumb|right|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Рекомендуется пользоваться именно методом &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;. Он работает быстрее и в общем случае эффективнее расходует память. Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; - может быть полезен, в тех случаях если хотите совершить обход дерева кратчайших путей.&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер свойства ребра (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит индекс дуги входящий в i-ю вершину, в противном случае -1. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты). Осторожно: метод создает огромное количество объектов типа &amp;lt;tt&amp;gt;QgsRubberBand&amp;lt;/tt&amp;gt;, пользуйтесь этим методом только для очень маленьких слоев.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -1.37144, 0.543836 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Файл:network-analysis-05.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения оптимального маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Алгоритм можно записать так:&lt;br /&gt;
&lt;br /&gt;
# Присвоим Т = B&lt;br /&gt;
# Пока Т &amp;lt;&amp;gt; A Цикл&lt;br /&gt;
## Добавим в маршрут точку Т&lt;br /&gt;
## Берем ребро, которое входит в точку Т&lt;br /&gt;
## Находим точку ТТ, из которой это ребро выходит&lt;br /&gt;
## Присваиваем Т = ТТ&lt;br /&gt;
# Добавим в маршрут точку А&lt;br /&gt;
На этом построение маршрута закончено. Вы получили список вершин, в обратном порядке, которые будут посещены при движении по кратчайшему маршруту.&lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|дерево кратчайших путей]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете двигаться дальше .&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dikstra&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Файл:network-analysis-06.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Поиск кратчайшего пути.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
Назовем областью доступности вершины графа А такое подмножество вершин графа доступных из вершины А, что стоимость оптимально пути от А до элементов этого множества не превосходит на перед заданного значения.&lt;br /&gt;
&lt;br /&gt;
Для пояснения этого определения обычно приводят следующий пример: &amp;quot;Есть пожарное депо. В какую часть города сможет попасть пожарная машина в течении 5 минут, 10 минут, 15 минут?&amp;quot;. Ответом на этот вопрос и являются области доступности пожарного депо.&lt;br /&gt;
&lt;br /&gt;
Нахождение области допустимости с помощью метода класса &amp;lt;tt&amp;gt;QgsGraphAnalyzer&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;dijksta&amp;lt;/tt&amp;gt; дело тривиальное. Достаточно сравнить элементы возвращаемого значения с заданным параметром. Если &amp;lt;tt&amp;gt;cost[ i ]&amp;lt;/tt&amp;gt; меньше или равно заданному параметру, тогда вершина принадлежит множеству доступности, иначе не принадлежит. &lt;br /&gt;
&lt;br /&gt;
Не столь очевидным является нахождение границ доступности. Нижняя граница доступности - множество вершин которые &amp;quot;еще&amp;quot; можно достигнуть и верхняя граница - множество точек которых &amp;quot;уже&amp;quot; нельзя достигнуть. На самом деле все просто: истинная граница проходит по таким ребрам дерева кратчайших путей, что вершина-источник ребра доступна, а вершина-цель недоступна.&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( 65.5462, 57.1509 )&lt;br /&gt;
delta = qgis.utils.iface.mapCanvas().getCoordinateTransform().mapUnitsPerPixel() * 1&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
rb.setColor( Qt.green )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() + delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
upperBound = []&lt;br /&gt;
r = 2000.0&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; len(cost):&lt;br /&gt;
  if cost[ i ] &amp;gt; r and tree[ i ] &amp;lt;&amp;gt; -1:&lt;br /&gt;
    outVertexId = graph.arc( tree [ i ] ).outVertex()&lt;br /&gt;
    if cost[ outVertexId ] &amp;lt; r:&lt;br /&gt;
      upperBound.append( i )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for i in upperBound:&lt;br /&gt;
  centerPoint = graph.vertex( i ).point()&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() + delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Файл:network-analysis-04.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Зеленый квадратик - центр области, крастные квадаратики - верхняя граница доступности, вершины &amp;quot;уже&amp;quot; не входящие в область.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1329</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1329"/>
		<updated>2012-01-22T12:16:06Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Скриншоты&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества объектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способом представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:network-analysis-01.png|350px|thumb|left|&amp;lt;center&amp;gt;Исходный граф&amp;lt;/center&amp;gt;]] || &lt;br /&gt;
[[Файл:network-analysis-02.png|350px|thumb|right|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Рекомендуется пользоваться именно методом &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;. Он работает быстрее и в общем случае эффективнее расходует память. Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; - может быть полезен, в тех случаях если хотите совершить обход дерева кратчайших путей.&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер свойства ребра (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит индекс дуги входящий в i-ю вершину, в противном случае -1. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты). Осторожно: метод создает огромное количество объектов типа &amp;lt;tt&amp;gt;QgsRubberBand&amp;lt;/tt&amp;gt;, пользуйтесь этим методом только для очень маленьких слоев.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -1.37144, 0.543836 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Файл:network-analysis-05.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения оптимального маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Алгоритм можно записать так:&lt;br /&gt;
&lt;br /&gt;
# Присвоим Т = B&lt;br /&gt;
# Пока Т &amp;lt;&amp;gt; A Цикл&lt;br /&gt;
## Добавим в маршрут точку Т&lt;br /&gt;
## Берем ребро, которое входит в точку Т&lt;br /&gt;
## Находим точку ТТ, из которой это ребро выходит&lt;br /&gt;
## Присваиваем Т = ТТ&lt;br /&gt;
# Добавим в маршрут точку А&lt;br /&gt;
На этом построение маршрута закончено. Вы получили список вершин, в обратном порядке, которые будут посещены при движении по кратчайшему маршруту.&lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|дерево кратчайших путей]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете двигаться дальше .&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dikstra&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Файл:network-analysis-06.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Поиск кратчайшего пути.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
Назовем областью доступности вершины графа А такое подмножество вершин графа доступных из вершины А, что стоимость оптимально пути от А до элементов этого множества не превосходит на перед заданного значения.&lt;br /&gt;
&lt;br /&gt;
Для пояснения этого определения обычно приводят следующий пример: &amp;quot;Есть пожарное депо. В какую часть города сможет попасть пожарная машина в течении 5 минут, 10 минут, 15 минут?&amp;quot;. Ответом на этот вопрос и являются области доступности пожарного депо.&lt;br /&gt;
&lt;br /&gt;
Нахождение области допустимости с помощью метода класса &amp;lt;tt&amp;gt;QgsGraphAnalyzer&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;dijksta&amp;lt;/tt&amp;gt; дело тривиальное. Достаточно сравнить элементы возвращаемого значения с заданным параметром. Если &amp;lt;tt&amp;gt;cost[ i ]&amp;lt;/tt&amp;gt; меньше или равно заданному параметру, тогда вершина принадлежит множеству доступности, иначе не принадлежит. &lt;br /&gt;
&lt;br /&gt;
Не столь очевидным является нахождение границ доступности. Нижняя граница доступности - множество вершин которые &amp;quot;еще&amp;quot; можно достигнуть и верхняя граница - множество точек которых &amp;quot;уже&amp;quot; нельзя достигнуть. На самом деле все просто: истинная граница проходит по таким ребрам дерева кратчайших путей, что вершина-источник ребра доступна, а вершина-цель недоступна.&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( 65.5462, 57.1509 )&lt;br /&gt;
delta = qgis.utils.iface.mapCanvas().getCoordinateTransform().mapUnitsPerPixel() * 1&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
rb.setColor( Qt.green )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() + delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
upperBound = []&lt;br /&gt;
r = 2000.0&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; len(cost):&lt;br /&gt;
  if cost[ i ] &amp;gt; r and tree[ i ] &amp;lt;&amp;gt; -1:&lt;br /&gt;
    outVertexId = graph.arc( tree [ i ] ).outVertex()&lt;br /&gt;
    if cost[ outVertexId ] &amp;lt; r:&lt;br /&gt;
      upperBound.append( i )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for i in upperBound:&lt;br /&gt;
  centerPoint = graph.vertex( i ).point()&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() + delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Файл:network-analysis-04.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Зеленый квадратик - центр области, крастные квадаратики - верхняя граница доступности, вершины &amp;quot;уже&amp;quot; не входящие в область.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-06.png&amp;diff=1328</id>
		<title>Файл:Network-analysis-06.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-06.png&amp;diff=1328"/>
		<updated>2012-01-22T12:11:08Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Поиск кратчайшего пути&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Поиск кратчайшего пути&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-05.png&amp;diff=1327</id>
		<title>Файл:Network-analysis-05.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-05.png&amp;diff=1327"/>
		<updated>2012-01-22T12:10:35Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Обображение дерева кратчайших путей с вершиной в точке 1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Обображение дерева кратчайших путей с вершиной в точке 1&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1319</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1319"/>
		<updated>2012-01-22T10:15:06Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способом представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:network-analysis-01.png|350px|thumb|left|&amp;lt;center&amp;gt;Исходный граф&amp;lt;/center&amp;gt;]] || &lt;br /&gt;
[[Файл:network-analysis-02.png|350px|thumb|right|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Рекомендуется пользоваться именно методом &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;. Он работает быстрее и в общем случае эффективнее расходует память. Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; - может быть полезен, в тех случаях если хотите совершить обход дерева кратчайших путей.&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер свойства ребра (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит индекс дуги входящий в i-ю вершину, в противном случае -1. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты). Осторожно: метод создает огромное количество объектов типа &amp;lt;tt&amp;gt;QgsRubberBand&amp;lt;/tt&amp;gt;, пользуйтесь этим методом только для очень маленьких слоев.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения оптимального маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Алгоритм можно записать так:&lt;br /&gt;
&lt;br /&gt;
# Присвоим Т = B&lt;br /&gt;
# Пока Т &amp;lt;&amp;gt; A Цикл&lt;br /&gt;
## Добавим в маршрут точку Т&lt;br /&gt;
## Берем ребро, которое входит в точку Т&lt;br /&gt;
## Находим точку ТТ, из которой это ребро выходит&lt;br /&gt;
## Присваиваем Т = ТТ&lt;br /&gt;
# Добавим в маршрут точку А&lt;br /&gt;
На этом построение маршрута закончено. Вы получили список вершин, в обратном порядке, которые будут посещены при движении по кратчайшему маршруту.&lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|дерево кратчайших путей]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете двигаться дальше .&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dikstra&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
Назовем областью доступности вершины графа А такое подмножество вершин графа доступных из вершины А, что стоимость оптимально пути от А до элементов этого множества не превосходит на перед заданного значения.&lt;br /&gt;
&lt;br /&gt;
Для пояснения этого определения обычно приводят следующий пример: &amp;quot;Есть пожарное депо. В какую часть города сможет попасть пожарная машина в течении 5 минут, 10 минут, 15 минут?&amp;quot;. Ответом на этот вопрос и являются области доступности пожарного депо.&lt;br /&gt;
&lt;br /&gt;
Нахождение области допустимости с помощью метода класса &amp;lt;tt&amp;gt;QgsGraphAnalyzer&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;dijksta&amp;lt;/tt&amp;gt; дело тривиальное. Достаточно сравнить элементы возвращаемого значения с заданным параметром. Если &amp;lt;tt&amp;gt;cost[ i ]&amp;lt;/tt&amp;gt; меньше или равно заданному параметру, тогда вершина принадлежит множеству доступности, иначе не принадлежит. &lt;br /&gt;
&lt;br /&gt;
Не столь очевидным является нахождение границ доступности. Нижняя граница доступности - множество вершин которые &amp;quot;еще&amp;quot; можно достигнуть и верхняя граница - множество точек которых &amp;quot;уже&amp;quot; нельзя достигнуть. На самом деле все просто: истинная граница проходит по таким ребрам дерева кратчайших путей, что вершина-источник ребра доступна, а вершина-цель недоступна.&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( 65.5462, 57.1509 )&lt;br /&gt;
delta = qgis.utils.iface.mapCanvas().getCoordinateTransform().mapUnitsPerPixel() * 1&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
rb.setColor( Qt.green )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() + delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
upperBound = []&lt;br /&gt;
r = 2000.0&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; len(cost):&lt;br /&gt;
  if cost[ i ] &amp;gt; r and tree[ i ] &amp;lt;&amp;gt; -1:&lt;br /&gt;
    outVertexId = graph.arc( tree [ i ] ).outVertex()&lt;br /&gt;
    if cost[ outVertexId ] &amp;lt; r:&lt;br /&gt;
      upperBound.append( i )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for i in upperBound:&lt;br /&gt;
  centerPoint = graph.vertex( i ).point()&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() + delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Файл:network-analysis-04.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Зеленый квадратик - центр области, крастные квадаратики - верхняя граница доступности, вершины &amp;quot;уже&amp;quot; не входящие в область.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1309</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1309"/>
		<updated>2012-01-21T22:02:50Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: /* Анализ графа */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способом представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:network-analysis-01.png|350px|thumb|left|&amp;lt;center&amp;gt;Исходный граф&amp;lt;/center&amp;gt;]] || &lt;br /&gt;
[[Файл:network-analysis-02.png|350px|thumb|right|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Рекомендуется пользоваться именно методом &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;. Он работает быстрее и в общем случае эффективнее расходует память. Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; - может быть полезен, в тех случаях если хотите совершить обход дерева кратчайших путей.&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер свойства ребра (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит индекс дуги входящий в i-ю вершину, в противном случае -1. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты). Осторожно: метод создает огромное количество объектов типа &amp;lt;tt&amp;gt;QgsRubberBand&amp;lt;/tt&amp;gt;, пользуйтесь этим методом только для очень маленьких слоев.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Алгоритм можно записать так:&lt;br /&gt;
&lt;br /&gt;
# Присвоим Т = B&lt;br /&gt;
# Пока Т &amp;lt;&amp;gt; A Цикл&lt;br /&gt;
## Добавим в маршрут точку Т&lt;br /&gt;
## Берем ребро, которое входит в точку Т&lt;br /&gt;
## Находим точку ТТ, из которой это ребро выходит&lt;br /&gt;
## Присваиваем Т = ТТ&lt;br /&gt;
# Добавим в маршрут точку А&lt;br /&gt;
На этом построение маршрута закончено. Вы получили список вершин, в обратном порядке, которые будут посещены при движении по кратчайшему маршруту.&lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|дерево кратчайших путей]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете двигаться дальше .&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dikstra&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( 65.5462, 57.1509 )&lt;br /&gt;
delta = qgis.utils.iface.mapCanvas().getCoordinateTransform().mapUnitsPerPixel() * 1&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
rb.setColor( Qt.green )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() + delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
upperBound = []&lt;br /&gt;
r = 2000.0&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; len(cost):&lt;br /&gt;
  if cost[ i ] &amp;gt; r and tree[ i ] &amp;lt;&amp;gt; -1:&lt;br /&gt;
    outVertexId = graph.arc( tree [ i ] ).outVertex()&lt;br /&gt;
    if cost[ outVertexId ] &amp;lt; r:&lt;br /&gt;
      upperBound.append( i )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for i in upperBound:&lt;br /&gt;
  centerPoint = graph.vertex( i ).point()&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() + delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-04.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Зеленый квадратик - центр области, крастные квадаратики - вершины &amp;quot;уже&amp;quot; не входящие в область.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1308</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1308"/>
		<updated>2012-01-21T21:27:26Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: /* Анализ графа */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:network-analysis-01.png|350px|thumb|left|&amp;lt;center&amp;gt;Исходный граф&amp;lt;/center&amp;gt;]] || &lt;br /&gt;
[[Файл:network-analysis-02.png|350px|thumb|right|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Рекомендуется пользоваться именно методом &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;. Он работает быстрее и в общем случае эффективнее расходует память. Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; - может быть полезен, в тех случаях если хотите совершить обход дерева кратчайших путей.&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер свойства ребра (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если i-ая вершина корень дерева или она не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты). Осторожно: метод создает огромное количество объектов типа &amp;lt;tt&amp;gt;QgsRubberBand&amp;lt;/tt&amp;gt;, пользуйтесь этим методом только для очень маленьких слоев.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Алгоритм можно записать так:&lt;br /&gt;
&lt;br /&gt;
# Присвоим Т = B&lt;br /&gt;
# Пока Т &amp;lt;&amp;gt; A Цикл&lt;br /&gt;
## Добавим в маршрут точку Т&lt;br /&gt;
## Берем ребро, которое входит в точку Т&lt;br /&gt;
## Находим точку ТТ, из которой это ребро выходит&lt;br /&gt;
## Присваиваем Т = ТТ&lt;br /&gt;
# Добавим в маршрут точку А&lt;br /&gt;
На этом построение маршрута закончено. Вы получили список вершин, в обратном порядке, которые будут посещены при движении по кратчайшему маршруту.&lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|дерево кратчайших путей]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете двигаться дальше .&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dikstra&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( 65.5462, 57.1509 )&lt;br /&gt;
delta = qgis.utils.iface.mapCanvas().getCoordinateTransform().mapUnitsPerPixel() * 1&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
rb.setColor( Qt.green )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() + delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
upperBound = []&lt;br /&gt;
r = 2000.0&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; len(cost):&lt;br /&gt;
  if cost[ i ] &amp;gt; r and tree[ i ] &amp;lt;&amp;gt; -1:&lt;br /&gt;
    outVertexId = graph.arc( tree [ i ] ).outVertex()&lt;br /&gt;
    if cost[ outVertexId ] &amp;lt; r:&lt;br /&gt;
      upperBound.append( i )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for i in upperBound:&lt;br /&gt;
  centerPoint = graph.vertex( i ).point()&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() + delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-04.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Зеленый квадратик - центр области, крастные квадаратики - вершины &amp;quot;уже&amp;quot; не входящие в область.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1306</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1306"/>
		<updated>2012-01-21T20:50:44Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Скрипт и скриншот. Описание позже&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:network-analysis-01.png|350px|thumb|left|&amp;lt;center&amp;gt;Исходный граф&amp;lt;/center&amp;gt;]] || &lt;br /&gt;
[[Файл:network-analysis-02.png|350px|thumb|right|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Рекомендуется пользоваться именно методом &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;. Он работает быстрее и в общем случае эффективнее расходует память. Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; - может быть полезен, в тех случаях если хотите совершить обход дерева кратчайших путей.&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если i-ая вершина корень дерева или она не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты). Осторожно: метод создает огромное количество объектов типа &amp;lt;tt&amp;gt;QgsRubberBand&amp;lt;/tt&amp;gt;, пользуйтесь этим методом только для очень маленьких слоев.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Алгоритм можно записать так:&lt;br /&gt;
&lt;br /&gt;
# Присвоим Т = B&lt;br /&gt;
# Пока Т &amp;lt;&amp;gt; A Цикл&lt;br /&gt;
## Добавим в маршрут точку Т&lt;br /&gt;
## Берем ребро, которое входит в точку Т&lt;br /&gt;
## Находим точку ТТ, из которой это ребро выходит&lt;br /&gt;
## Присваиваем Т = ТТ&lt;br /&gt;
# Добавим в маршрут точку А&lt;br /&gt;
На этом построение маршрута закончено. Вы получили список вершин, в обратном порядке, которые будут посещены при движении по кратчайшему маршруту.&lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|дерево кратчайших путей]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете двигаться дальше .&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dikstra&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( 65.5462, 57.1509 )&lt;br /&gt;
delta = qgis.utils.iface.mapCanvas().getCoordinateTransform().mapUnitsPerPixel() * 1&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
rb.setColor( Qt.green )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() - delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() + delta, pStart.y() + delta ) )&lt;br /&gt;
rb.addPoint( QgsPoint( pStart.x() - delta, pStart.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
upperBound = []&lt;br /&gt;
r = 2000.0&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; len(cost):&lt;br /&gt;
  if cost[ i ] &amp;gt; r and tree[ i ] &amp;lt;&amp;gt; -1:&lt;br /&gt;
    outVertexId = graph.arc( tree [ i ] ).outVertex()&lt;br /&gt;
    if cost[ outVertexId ] &amp;lt; r:&lt;br /&gt;
      upperBound.append( i )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for i in upperBound:&lt;br /&gt;
  centerPoint = graph.vertex( i ).point()&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas(), True )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() - delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() + delta, centerPoint.y() + delta ) )&lt;br /&gt;
  rb.addPoint( QgsPoint( centerPoint.x() - delta, centerPoint.y() + delta ) )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-04.png|740px|thumb|center|&amp;lt;center&amp;gt;Результат выполнения скрипта. Зеленый квадратик - центр области, крастные квадаратики - вершины &amp;quot;уже&amp;quot; не входящие в область.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-04.png&amp;diff=1305</id>
		<title>Файл:Network-analysis-04.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-04.png&amp;diff=1305"/>
		<updated>2012-01-21T20:45:19Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: загружена новая версия «Файл:Network-analysis-04.png»: убрал коммандную панель. Оставил только окно QGIS&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Скрин скрипта для поиска областей доступности. Зеленый квадратик - центр области, крастные квадатики - вершины которые уже нельзя достигнуть. Так называемая граница сверху.&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-04.png&amp;diff=1304</id>
		<title>Файл:Network-analysis-04.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-04.png&amp;diff=1304"/>
		<updated>2012-01-21T20:43:03Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Скрин скрипта для поиска областей доступности. Зеленый квадратик - центр области, крастные квадатики - вершины которые уже нельзя достигнуть. Так называемая граница сверху.&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1295</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1295"/>
		<updated>2012-01-21T17:44:05Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: /* Анализ графа */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:network-analysis-01.png|350px|thumb|left|&amp;lt;center&amp;gt;Исходный граф&amp;lt;/center&amp;gt;]] || &lt;br /&gt;
[[Файл:network-analysis-02.png|350px|thumb|right|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Рекомендуется пользоваться именно методом &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;. Он работает быстрее и в общем случае эффективнее расходует память. Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; - может быть полезен, в тех случаях если хотите совершить обход дерева кратчайших путей.&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если i-ая вершина корень дерева или она не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты). Осторожно: метод создает огромное количество объектов типа &amp;lt;tt&amp;gt;QgsRubberBand&amp;lt;/tt&amp;gt;, пользуйтесь этим методом только для очень маленьких слоев.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Алгоритм можно записать так:&lt;br /&gt;
&lt;br /&gt;
# Присвоим Т = B&lt;br /&gt;
# Пока Т &amp;lt;&amp;gt; A Цикл&lt;br /&gt;
## Добавим в маршрут точку Т&lt;br /&gt;
## Берем ребро, которое входит в точку Т&lt;br /&gt;
## Находим точку ТТ, из которой это ребро выходит&lt;br /&gt;
## Присваиваем Т = ТТ&lt;br /&gt;
# Добавим в маршрут точку А&lt;br /&gt;
На этом построение маршрута закончено. Вы получили список вершин, в обратном порядке, которые будут посещены при движении по кратчайшему маршруту.&lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|дерево кратчайших путей]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете двигаться дальше .&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dikstra&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1272</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1272"/>
		<updated>2012-01-21T10:12:39Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:network-analysis-01.png|350px|thumb|left|&amp;lt;center&amp;gt;Исходный граф&amp;lt;/center&amp;gt;]] || &lt;br /&gt;
[[Файл:network-analysis-02.png|350px|thumb|right|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Рекомендуется пользоваться именно методом &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;. Он работает быстрее и в общем случае эффективнее расходует память. Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; - может быть полезен, в тех случаях если хотите совершить обход дерева кратчайших путей.&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если это корень дерева или вершина не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты). Осторожно: метод создает огромное количество объектов типа &amp;lt;tt&amp;gt;QgsRubberBand&amp;lt;/tt&amp;gt;, пользуйтесь этим методом только для очень маленьких слоев.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Алгоритм можно записать так:&lt;br /&gt;
&lt;br /&gt;
# Присвоим Т = B&lt;br /&gt;
# Пока Т &amp;lt;&amp;gt; A Цикл&lt;br /&gt;
## Добавим в маршрут точку Т&lt;br /&gt;
## Берем ребро, которое входит в точку Т&lt;br /&gt;
## Находим точку ТТ, из которой это ребро выходит&lt;br /&gt;
## Присваиваем Т = ТТ&lt;br /&gt;
# Добавим в маршрут точку А&lt;br /&gt;
На этом построение маршрута закончено. Вы получили список вершин, в обратном порядке, которые будут посещены при движении по кратчайшему маршруту.&lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|дерево кратчайших путей]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете двигаться дальше .&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dikstra&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1271</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1271"/>
		<updated>2012-01-21T10:08:24Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:network-analysis-01.png|350px|thumb|left|&amp;lt;center&amp;gt;Исходный граф&amp;lt;/center&amp;gt;]] || &lt;br /&gt;
[[Файл:network-analysis-02.png|350px|thumb|right|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Рекомендуется пользоваться именно методом &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;. Он работает быстрее и в общем случае эффективнее расходует память. Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; - может быть полезен, в тех случаях если хотите совершить обход дерева кратчайших путей.&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если это корень дерева или вершина не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Алгоритм можно записать так:&lt;br /&gt;
&lt;br /&gt;
# Присвоим Т = B&lt;br /&gt;
# Пока Т &amp;lt;&amp;gt; A Цикл&lt;br /&gt;
## Добавим в маршрут точку Т&lt;br /&gt;
## Берем ребро, которое входит в точку Т&lt;br /&gt;
## Находим точку ТТ, из которой это ребро выходит&lt;br /&gt;
## Присваиваем Т = ТТ&lt;br /&gt;
# Добавим в маршрут точку А&lt;br /&gt;
На этом построение маршрута закончено. Вы получили список вершин, в обратном порядке, которые будут посещены при движении по кратчайшему маршруту.&lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|дерево кратчайших путей]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете двигаться дальше .&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода &amp;lt;tt&amp;gt;dikstra&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1226</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1226"/>
		<updated>2012-01-19T12:42:42Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-02.png|740px|thumb|center|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer].&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если это корень дерева или вершина не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода shortestTree (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода dijkstra:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода shortestTree получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T &lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|рисунок]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете дальше двигаться.&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода dikstra&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение областей доступности ====&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1225</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1225"/>
		<updated>2012-01-19T12:19:08Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-02.png|740px|thumb|center|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer].&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если это корень дерева или вершина не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода shortestTree (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода dijkstra:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя произвольными точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода shortestTree получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T &lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|рисунок]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете дальше двигаться.&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода dikstra&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1224</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1224"/>
		<updated>2012-01-19T12:17:43Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Восстановил описание от Voltron'а&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-02.png|740px|thumb|center|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer].&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если это корень дерева или вершина не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода shortestTree (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода dijkstra:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода shortestTree получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T &lt;br /&gt;
&lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|рисунок]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете дальше двигаться.&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода dikstra&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1223</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1223"/>
		<updated>2012-01-19T11:59:59Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-02.png|740px|thumb|center|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer].&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если это корень дерева или вершина не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода shortestTree (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода dijkstra:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Рассмотрим задачу нахождения кратчайшего маршрута маршрут из точки A в точку B. Для начала нужно построить дерево кратчайших путей с корнем в точке A, затем нужно &amp;quot;спуститься&amp;quot; из точки B в точку А. &lt;br /&gt;
Посмотрите еще раз на [[Медиа:network-analysis-02.png|рисунок]] и представьте что вы можете двигаться только против направления стрелочек. Двигайтесь из точки №7. Рано или поздно вы попадете в точку №1 (корень дерева) и не сможете дальше двигаться. &lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
 &lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
 &lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
if idStop == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = []&lt;br /&gt;
  while (idStart != idStop ):&lt;br /&gt;
    l = tree.vertex( idStop ).inArc()&lt;br /&gt;
    if len( l ) == 0:&lt;br /&gt;
      break&lt;br /&gt;
    e = tree.arc( l[ 0 ] )&lt;br /&gt;
    p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
    idStop = e.outVertex()&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  p.insert( 0, tStart )&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот пример для метода dikstra&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.835953, 0.15679 )&lt;br /&gt;
pStop = QgsPoint( -1.1027, 0.699986 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
 &lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
 &lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
 &lt;br /&gt;
( tree, cost ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
if tree[ idStop ] == -1:&lt;br /&gt;
  print 'Path not found'&lt;br /&gt;
else:&lt;br /&gt;
  p = [ ] &lt;br /&gt;
  curPos = idStop;&lt;br /&gt;
  while curPos != idStart:&lt;br /&gt;
    p.append( graph.vertex( graph.arc( tree[ curPos ] ).inVertex() ).point() )&lt;br /&gt;
    curPos = graph.arc( tree[ curPos ] ).outVertex();&lt;br /&gt;
  &lt;br /&gt;
  p.append( tStart )&lt;br /&gt;
  &lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor( Qt.red )&lt;br /&gt;
  &lt;br /&gt;
  for pnt in p:&lt;br /&gt;
    rb.addPoint(pnt)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1222</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1222"/>
		<updated>2012-01-19T11:19:35Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Хорошим способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-02.png|740px|thumb|center|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнем в вершине №1&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методом shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer].&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если это корень дерева или вершина не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот так выглядит простейший способ отобразить дерево кратчайших путей для метода shortestTree (только замените координаты начальной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint( -0.743804, 0.22954 )&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
i = 0;&lt;br /&gt;
while ( i &amp;lt; tree.arcCount() ):&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( tree.vertex( tree.arc( i ).outVertex() ).point() )&lt;br /&gt;
  i = i + 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так для метода dijkstra:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
 &lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
 &lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
 &lt;br /&gt;
pStart = QgsPoint(-0.743804,0.22954)&lt;br /&gt;
 &lt;br /&gt;
tiedPoint = director.makeGraph( builder, [ pStart ] )&lt;br /&gt;
&lt;br /&gt;
pStart = tiedPoint[ 0 ]&lt;br /&gt;
&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( pStart )&lt;br /&gt;
&lt;br /&gt;
( tree, costs ) = QgsGraphAnalyzer.dijkstra( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
for edgeId in tree:&lt;br /&gt;
  if edgeId == -1:&lt;br /&gt;
    continue&lt;br /&gt;
  rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
  rb.setColor ( Qt.red )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).inVertex() ).point() )&lt;br /&gt;
  rb.addPoint ( graph.vertex( graph.arc( edgeId ).outVertex() ).point() )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Нахождение кратчайших путей ====&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1221</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1221"/>
		<updated>2012-01-19T10:40:32Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Одним из способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-02.png|740px|thumb|center|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнет в вершине №1&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методам shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer].&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если это корень дерева или вершина не достижима из корня, в противном случае - индекс дуги входящий в i-ю вершину. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) если вершина не достижима.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, после получения дерева кратчайших путей нам доступны два метода его анализа:&lt;br /&gt;
* Обход дерева в глубину (если хотите в ширину)&lt;br /&gt;
* Движение от узла дерева к его корню&lt;br /&gt;
&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1220</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1220"/>
		<updated>2012-01-19T10:37:51Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Одним из способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-02.png|740px|thumb|center|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнет в вершине №1&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей можно получить пользуясь методам shortestTree или методом dijkstra класса [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer].&lt;br /&gt;
 &lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; создает новый графовый объект (всегда QgsGraph) и принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;dijkstra&amp;lt;/tt&amp;gt; имеет аналогичные параметры. Возвращаемое значение - кортеж из двух массивов. В первом массиве i-ый элемент содержит -1 если это корень дерева или вершина не достижима из корня, индекс дуги входящий в i-ю вершину в противном случае. Во втором массиве i-ый элемент содержит дистанцию от корня дерева до i-вершины если вершина достижима из корня или максимально большое число которое может хранить тип С++ double (эквивалент плюс бесконечности) в противном случае.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(tree, cost) = QgsGraphAnalyzer.dijkstra( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, после получения дерева кратчайших путей нам доступны два метода его анализа:&lt;br /&gt;
* Обход дерева в глубину (если хотите в ширину)&lt;br /&gt;
* Движение от узла дерева к его корню&lt;br /&gt;
&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-02.png&amp;diff=1216</id>
		<title>Файл:Network-analysis-02.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-02.png&amp;diff=1216"/>
		<updated>2012-01-19T10:00:56Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: загружена новая версия «Файл:Network-analysis-02.png»: Подрисовал стрелочку к дуге 1-4&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Дерево кратчайших путей&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1215</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1215"/>
		<updated>2012-01-19T09:55:53Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Одним из способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
[[Файл:network-analysis-02.png|740px|thumb|center|&amp;lt;center&amp;gt;Дерево кратчайших путей с корнет в вершине №1&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Таким образом, после получения дерева кратчайших путей нам доступны два метода его анализа:&lt;br /&gt;
* Обход дерева в глубину (если хотите в ширину)&lt;br /&gt;
* Движение от узла дерева к его корню&lt;br /&gt;
&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-02.png&amp;diff=1214</id>
		<title>Файл:Network-analysis-02.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-02.png&amp;diff=1214"/>
		<updated>2012-01-19T09:52:18Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Дерево кратчайших путей&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Дерево кратчайших путей&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1213</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=1213"/>
		<updated>2012-01-19T09:44:24Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: добавлены скриншоты привязки точек&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
[[Файл:network-analysis-01.png|740px|thumb|center|&amp;lt;center&amp;gt;Граф полученный без дополнительных точек&amp;lt;/center&amp;gt;]]&lt;br /&gt;
[[Файл:network-analysis-03.png|740px|thumb|center|&amp;lt;center&amp;gt;Результирующий граф с двумя дополнительными точками. Красной точки соответствует вершина №5. Зеленой точки соответствует вновь добавленная вершина №9&amp;lt;/center&amp;gt;]]&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Одним из способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Таким образом, после получения дерева кратчайших путей нам доступны два метода его анализа:&lt;br /&gt;
* Обход дерева в глубину (если хотите в ширину)&lt;br /&gt;
* Нисходящий спуск.&lt;br /&gt;
&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-03.png&amp;diff=1211</id>
		<title>Файл:Network-analysis-03.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-03.png&amp;diff=1211"/>
		<updated>2012-01-19T09:40:46Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Результирующий граф с двумя &amp;quot;привязанными&amp;quot; точками&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Результирующий граф с двумя &amp;quot;привязанными&amp;quot; точками&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-01.png&amp;diff=1210</id>
		<title>Файл:Network-analysis-01.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Network-analysis-01.png&amp;diff=1210"/>
		<updated>2012-01-19T09:37:39Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Граф - изображение&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Граф - изображение&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=993</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=993"/>
		<updated>2012-01-16T13:14:52Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Два дня голову ломал&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Одним из способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Таким образом, после получения дерева кратчайших путей нам доступны два метода его анализа:&lt;br /&gt;
* Обход дерева в глубину (если хотите в ширину)&lt;br /&gt;
* Нисходящий спуск.&lt;br /&gt;
&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
idStart = tree.findVertex( tStart )&lt;br /&gt;
idStop = tree.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=864</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=864"/>
		<updated>2012-01-14T18:58:59Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Одним из способов представления результата выполнения алгоритма Дейкстры является [http://en.wikipedia.org/wiki/Shortest_path_tree дерево кратчайших путей].&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Таким образом, после получения дерева кратчайших путей нам доступны два метода его анализа:&lt;br /&gt;
* Обход дерева в глубину (если хотите в ширину)&lt;br /&gt;
* Нисходящий спуск.&lt;br /&gt;
&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=836</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=836"/>
		<updated>2012-01-14T15:16:03Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Реализация построения графа из векторного слоя использует шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector]. Директор определяет алгоритм которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], его &amp;quot;руками&amp;quot; строиться граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Одним из способов представления результата выполнения алгоритма Дейкстры является дерево кратчайших путей.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Таким образом, после получения дерева кратчайших путей нам доступны два метода его анализа:&lt;br /&gt;
* Обход дерева в глубину (если хотите в ширину)&lt;br /&gt;
* Нисходящий спуск.&lt;br /&gt;
&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=766</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=766"/>
		<updated>2012-01-13T07:09:11Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Для построения графа из векторного слоя используется шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector], которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], который строит граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра. Одним из способов представления результата выполнения алгоритма Дейкстры является дерево кратчайших путей.&lt;br /&gt;
&lt;br /&gt;
Дерево кратчайших путей - это ориентированный взвешенный граф (точнее дерево) обладающий следующими свойствами:&lt;br /&gt;
* Только одна вершина не имеет входящих в нее ребер - корень дерева&lt;br /&gt;
* Все остальные вершины имеют только одно входящее в них ребро&lt;br /&gt;
* Если вершина B достижима из вершины A, то путь соединяющий их единственный и он же кратчайший (оптимальный) на исходном графе.&lt;br /&gt;
&lt;br /&gt;
Таким образом, после получения дерева кратчайших путей нам доступны два метода его анализа:&lt;br /&gt;
* Обход дерева в глубину (если хотите в ширину)&lt;br /&gt;
* Нисходящий спуск.&lt;br /&gt;
&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=758</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=758"/>
		<updated>2012-01-13T05:03:47Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Для построения графа из векторного слоя используется шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector], которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], который строит граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
&lt;br /&gt;
В основе сетевого анализа лежат задача связности вершин графа и задача поиска кратчайших путей. Для решения этих задач в библиотеке network-analysis реализован [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B алгоритм Дейкстры].&lt;br /&gt;
&lt;br /&gt;
Алгоритм Дейкстры находит оптимальный маршрут от одной из вершин графа до всех остальных и значение оптимизируемого параметра.&lt;br /&gt;
&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=744</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=744"/>
		<updated>2012-01-13T03:58:39Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Для построения графа из векторного слоя используется шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector], которой строит граф по линейному векторному слою и одним строителем [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder], который строит граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно реализовать строителя, который будет строить граф, совместимый с такими библиотеками как [http://www.boost.org/doc/libs/1_48_0/libs/graph/doc/index.html BGL] или [http://networkx.lanl.gov/ networkX].&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. &lt;br /&gt;
&lt;br /&gt;
Конструктор QgsGraphBuilder принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=725</id>
		<title>Поиск кратчайшего маршрута c помощью Road graph для QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=725"/>
		<updated>2012-01-12T19:37:55Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p class=&amp;quot;ann&amp;quot;&amp;gt;Статья содержит подробное описание расширения свободной к ГИС Quantum GIS модуля Road Graph.&amp;lt;/p&amp;gt;&lt;br /&gt;
Road graph — расширение свободной ГИС с открытым исходным кодом Quantum GIS, позволяющее осуществлять поиск оптимального маршрута на заданном графе дорог. Расширение автоматически устанавливается вместе с QGIS, начиная с версии 1.6, автор модуля — Сергей Якушев ([http://gis-lab.info/forum/memberlist.php?mode=viewprofile&amp;amp;u=7751 stopa85]).&lt;br /&gt;
&lt;br /&gt;
Для начала работы нужно установить и активировать модуль и загрузить в QGIS линейный векторный слой по которому нужно проложить маршрут, например из данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. Далее, используя инструменты модуля можно легко найти путь от одной заданной точки к другой, указав их на карте. Маршрут можно оптимизировать по расстоянию (самый короткий) или по времени (самый быстрый). Далее в статье подробно рассматриваются все пункты работы с модулем.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph2.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c активированным Road graph. Загружены слои OSM на Тюменскую область, красным цветом отображается проложенный маршрут.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Установка ===&lt;br /&gt;
&lt;br /&gt;
Road graph является расширением ядра QGIS, поэтому достаточно установить QGIS со всеми зависимостями ([http://gis-lab.info/qa/qgis-osgeo4w.html подробнее]) и в Менеджере модулей («Модули — Управление модулями») активировать модуль Road graph.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-01.png|frame|center|&amp;lt;center&amp;gt;Активация Road graph в Менеджере модулей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
После активации модуль добавляет свою панель в левой части окна QGIS и создает вложенный пункт в меню «Вектор» (новые экспериментальные версии QGIS) или пункт в меню «Модули» (Версии QGIS 1.6, 1.7). Панель может быть скрыта/показана с помощью пункта меню «Вид — Панели — Кратчайший маршрут».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-02.png|frame|center|&amp;lt;center&amp;gt;Панель модуля Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
Основные возможности расширения:&lt;br /&gt;
* расчет маршрута, его протяженности и времени пути&lt;br /&gt;
* оптимизация по критерию расстояния или времени&lt;br /&gt;
* экспорт маршрута в векторный слой&lt;br /&gt;
&lt;br /&gt;
В версиях QGIS 1.6, 1.7 присутствует возможность подсветки направления движения дорог (работает медленно, чаще всего используется в целях проверки настроек). В будущих релизах QGIS данная возможность будет удалена. Эффекта подсветки направления можно легко добиться настраивая стиль отображения слоя.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Road direction.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c подсветкой направления дорог, реализованной при помощи стилей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
В качестве слоя дорог можно использовать любой линейный векторный слой в формате, поддерживаемом QGIS. Две линии, имеющие общую точку считаются связанными между собой. &lt;br /&gt;
&lt;br /&gt;
'''ВНИМАНИЕ''': при редактировании слоя дорог в качестве СК проекта необходимо использовать СК слоя. Это&lt;br /&gt;
вызвано тем, что при пересчете координат между разными СК возникают погрешности, что может приводить к появлению разрывов даже при включенном «прилипании».&lt;br /&gt;
&lt;br /&gt;
В атрибутивной таблице слоя могут присутствовать и использоваться в работе расширения следующие поля:&lt;br /&gt;
* скорость движения по участку дороги — числовое поле&lt;br /&gt;
* направление движения — любой тип, приводимый к строке. Прямое и обратное направления соответствуют односторонней дороге, оба направления — двусторонней.&lt;br /&gt;
&lt;br /&gt;
Если значение какого-либо поля не задано, или поле отсутствует — используется значение по умолчанию, изменить которое можно в [[RoadGraph docs#Настройки модуля|настройках расширения]].&lt;br /&gt;
&lt;br /&gt;
Выбор начальной и конечной точек маршрута выполняется при помощи соответствующих кнопок возле полей ввода. Координаты выбранных точек будут отображены в полях ввода.&lt;br /&gt;
&lt;br /&gt;
Нажатие на кнопку «Рассчитать» запустит поиск кратчайшего маршрута с использованием критерия оптимизации, заданного выпадающим списком «Критерий». Кнопка «Экспорт» служит для экспорта построенного маршрута в новый векторный слой, а при помощи кнопки «Очистить» выполняется очистка полей с координатами начальной и конечной точек, а также из области карты удаляются сами точки и построенный маршрут. Краткую справку по работе с модулем можно получить нажав кнопку «Справка».&lt;br /&gt;
&lt;br /&gt;
==== Настройки модуля ====&lt;br /&gt;
&lt;br /&gt;
Перед использованием рекомендуется выполнить настроку модуля. Для этого вызовите диалог настройки из меню «Вектор — Road graph — Параметры модуля Road graph».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-03.png|frame|center|&amp;lt;center&amp;gt;Диалог настройки Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Здесь задаются предпочитаемые единицы измерения времени и расстояния, топологический порог и настраивается распознавание характера движения по дорогам. Если первые два параметра не требуют дополнительных пояснений, то остальные мы рассмотрим подробнее.&lt;br /&gt;
&lt;br /&gt;
При использовании слоя дорог, в котором присутствуют артефакты в виде небольших разрывов между вершинами полилиний, необходимо установить «топологический порог». Топологический порог (или топологическая толерантность) — это расстояние между двумя соседними вершинами, при котором они интерпретируются как одна и та же вершина графа. Эта величина должна быть как можно меньше (чем меньше — тем лучше). Не стоит полагаться на параметр топологической толерантности как на панацею, лучше если Ваши данные будут приведены к «правильному» виду.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_without_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с нулевой топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_with_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с ненулевой (0.00005) топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Модуль может правильно обрабатывать дороги с разным характером движения: одностроннее или двустороннее. Для этого необходимо, чтобы в атрибутивной таблице слоя присутствовало поле с указанием типа дороги. Его нужно выбрать в выпадающем списке «Поле направления» с настройках модуля и задать значения для прямого, обратного и двустороннего движения. Под прямым направлением понимается движение в порядке создания точек линии, от первой точки к последней. Соответственно, обратное направление это движение от последней точки линии к первой. Эти два варианта задают односторонние дороги.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим настройку на примере данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. В качестве поля направления выбираем «oneway», тогда двусторонней дороге будет соответствовать значение «no», прямому направлению односторонней дороги будет соответствовать значение «yes», a обратному — какое-либо другое значение, например «-1». На вкладке «По умолчанию» для поля «Направление» выбираем «Двустороннее направление», чтобы дороги, не подпадающие под описанную выше схему трактовались как двусторонние. Все, теперь модуль будет различать дороги и строить маршруты с учетом характера движения по дорогам.&lt;br /&gt;
&lt;br /&gt;
Здесь же можно указать в каком поле находится информация о скорости движения по данному участку дороги. Если такое поле присутствует, то становится возможной оптимизация маршрута не только по расстоянию, но и по времени движения.&lt;br /&gt;
&lt;br /&gt;
На вкладке «По умолчанию» задаются значения параметров по умолчанию, которые будут использоваться, если модуль не сможет извлечь информацию из указанных полей или если эти поля отсутствуют.&lt;br /&gt;
&lt;br /&gt;
=== Библиотека QGIS network-analysis ===&lt;br /&gt;
&lt;br /&gt;
В настоящее время, в экспериментальных версиях QGIS базовый функционал плагина вынесен в отдельную библиотеку [[QGIS_network-analysis_library|network-analysis]], что делает возможным использование алгоритмов сетевого анализа реализованных в модуле из Консоли Python QGIS, а также в своих расширениях.&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=724</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=724"/>
		<updated>2012-01-12T19:30:55Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
&lt;br /&gt;
Для назначения свойств ребрам графа могут быть использованы атрибуты векторного слоя и протяженность ребра.&lt;br /&gt;
&lt;br /&gt;
Для построения графа из векторного слоя используется шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector], которой строит граф по линейному векторному слою.&lt;br /&gt;
&lt;br /&gt;
Для вычисления свойств ребер используется паттерн проектрирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. Стандартный строитель [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder] строит граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно написать свою реализацию, которая будет строить граф, совместимый с такими библиотеками как Boost или networkX.&lt;br /&gt;
&lt;br /&gt;
Конструктор строителя принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=723</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=723"/>
		<updated>2012-01-12T19:14:45Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание! Т.к. модуль активно развивается, статья может содержать устаревшую информацию.&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Алгоритм применения библиотеки network-analysis можно записать в трех шагах:&lt;br /&gt;
# Получить граф из географических данных&lt;br /&gt;
# Анализировать граф&lt;br /&gt;
# Использовать результат анализа графа в своих целях, например, визуализировать&lt;br /&gt;
&lt;br /&gt;
=== Получение графа ===&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. &lt;br /&gt;
&lt;br /&gt;
В качестве источника графа может выступать любой линейный векторный слой. Узлы линий образуют множество вершин графа. В качестве ребер графа выступают отрезки линий векторного слоя. Узлы имеющие одинаковые координаты образуют единую вершину графа. Таким образом две линии имеющие общий узел оказываются связанными между собой.&lt;br /&gt;
&lt;br /&gt;
В дополнение к этому при построении графа можно привязать к векторному слою любое количество дополнительных точек. Для каждой дополнительной точки будет найдено соответствие - либо ближайшая вершина графа, либо ближайшее ребро. В последнем случае ближайшее ребро будет разбито на две части и будет добавлена общая вершина.&lt;br /&gt;
&lt;br /&gt;
Для того чтобы назначать ребрам графа характеристики (время движения по ребру, протяженность пути, стоимость) используется паттерн проектирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 стратегия]&lt;br /&gt;
&lt;br /&gt;
Для построения графа из векторного слоя используется шаблон программирования [http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_%28%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29 строитель]. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector], которой строит граф по линейному векторному слою.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим создание графа более подробно.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нужно создать директора&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения. -1 не использовать эту информацию&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа. Стратегия рассчитывает свойства ребра, запрашивая данные у директора, и именно основываясь на свойствах ребер будет выполняться поиск оптимального маршрута. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, вычисляющая время движения по ребру графа на основании длины ребра и поля скорости.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. Стандартный строитель [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder] строит граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно написать свою реализацию, которая будет строить граф, совместимый с такими библиотеками как Boost или networkX.&lt;br /&gt;
&lt;br /&gt;
Конструктор строителя принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также можно задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Анализ графа ===&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Актуальная документация ==&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=715</id>
		<title>Поиск кратчайшего маршрута c помощью Road graph для QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=715"/>
		<updated>2012-01-12T02:17:52Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: добавлена аннтотация&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p class=&amp;quot;ann&amp;quot;&amp;gt;Статья содержит подробное описание расширения свободной ГИС Quantum GIS модуля Road Graph.&amp;lt;/p&amp;gt;&lt;br /&gt;
Road graph — расширение свободной ГИС с открытым исходным кодом Quantum GIS, позволяющее осуществлять поиск оптимального маршрута на заданном графе дорог. Расширение автоматически устанавливается вместе с QGIS, начиная с версии 1.6, автор модуля — Сергей Якушев ([http://gis-lab.info/forum/memberlist.php?mode=viewprofile&amp;amp;u=7751 stopa85]).&lt;br /&gt;
&lt;br /&gt;
Для начала работы нужно установить и активировать модуль и загрузить в QGIS линейный векторный слой по которому нужно проложить маршрут, например из данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. Далее, используя инструменты модуля можно легко найти путь от одной заданной точки к другой, указав их на карте. Маршрут можно оптимизировать по расстоянию (самый короткий) или по времени (самый быстрый). Далее в статье подробно рассматриваются все пункты работы с модулем.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph2.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c активированным Road graph. Загружены слои OSM на Тюменскую область, красным цветом отображается проложенный маршрут.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Установка ===&lt;br /&gt;
&lt;br /&gt;
Road graph является расширением ядра QGIS, поэтому достаточно установить QGIS со всеми зависимостями ([http://gis-lab.info/qa/qgis-osgeo4w.html подробнее]) и в Менеджере модулей («Модули — Управление модулями») активировать модуль Road graph.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-01.png|frame|center|&amp;lt;center&amp;gt;Активация Road graph в Менеджере модулей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
После активации модуль добавляет свою панель в левой части окна QGIS и создает вложенный пункт в меню «Вектор» (новые экспериментальные версии QGIS) или пункт в меню «Модули» (Версии QGIS 1.6, 1.7). Панель может быть скрыта/показана с помощью пункта меню «Вид — Панели — Кратчайший маршрут».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-02.png|frame|center|&amp;lt;center&amp;gt;Панель модуля Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
Основные возможности расширения:&lt;br /&gt;
* расчет маршрута, его протяженности и времени пути&lt;br /&gt;
* оптимизация по критерию расстояния или времени&lt;br /&gt;
* экспорт маршрута в векторный слой&lt;br /&gt;
&lt;br /&gt;
В версиях QGIS 1.6, 1.7 присутствует возможность подсветки направления движения дорог (работает медленно, чаще всего используется в целях проверки настроек). В будущих релизах QGIS данная возможность будет удалена. Эффекта подсветки направления можно легко добиться настраивая стиль отображения слоя.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Road direction.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c подсветкой направления дорог, реализованной при помощи стилей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
В качестве слоя дорог можно использовать любой линейный векторный слой в формате, поддерживаемом QGIS. Две линии, имеющие общую точку считаются связанными между собой. &lt;br /&gt;
&lt;br /&gt;
'''ВНИМАНИЕ''': при редактировании слоя дорог в качестве СК проекта необходимо использовать СК слоя. Это&lt;br /&gt;
вызвано тем, что при пересчете координат между разными СК возникают погрешности, что может приводить к появлению разрывов даже при включенном «прилипании».&lt;br /&gt;
&lt;br /&gt;
В атрибутивной таблице слоя могут присутствовать и использоваться в работе расширения следующие поля:&lt;br /&gt;
* скорость движения по участку дороги — числовое поле&lt;br /&gt;
* направление движения — любой тип, приводимый к строке. Прямое и обратное направления соответствуют односторонней дороге, оба направления — двусторонней.&lt;br /&gt;
&lt;br /&gt;
Если значение какого-либо поля не задано, или поле отсутствует — используется значение по умолчанию, изменить которое можно в [[RoadGraph docs#Настройки модуля|настройках расширения]].&lt;br /&gt;
&lt;br /&gt;
Выбор начальной и конечной точек маршрута выполняется при помощи соответствующих кнопок возле полей ввода. Координаты выбранных точек будут отображены в полях ввода.&lt;br /&gt;
&lt;br /&gt;
Нажатие на кнопку «Рассчитать» запустит поиск кратчайшего маршрута с использованием критерия оптимизации, заданного выпадающим списком «Критерий». Кнопка «Экспорт» служит для экспорта построенного маршрута в новый векторный слой, а при помощи кнопки «Очистить» выполняется очистка полей с координатами начальной и конечной точек, а также из области карты удаляются сами точки и построенный маршрут. Краткую справку по работе с модулем можно получить нажав кнопку «Справка».&lt;br /&gt;
&lt;br /&gt;
==== Настройки модуля ====&lt;br /&gt;
&lt;br /&gt;
Перед использованием рекомендуется выполнить настроку модуля. Для этого вызовите диалог настройки из меню «Вектор — Road graph — Параметры модуля Road graph».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-03.png|frame|center|&amp;lt;center&amp;gt;Диалог настройки Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Здесь задаются предпочитаемые единицы измерения времени и расстояния, топологический порог и настраивается распознавание характера движения по дорогам. Если первые два параметра не требуют дополнительных пояснений, то остальные мы рассмотрим подробнее.&lt;br /&gt;
&lt;br /&gt;
При использовании слоя дорог, в котором присутствуют артефакты в виде небольших разрывов между вершинами полилиний, необходимо установить «топологический порог». Топологический порог (или топологическая толерантность) — это расстояние между двумя соседними вершинами, при котором они интерпретируются как одна и та же вершина графа. Эта величина должна быть как можно меньше (чем меньше — тем лучше). Не стоит полагаться на параметр топологической толерантности как на панацею, лучше если Ваши данные будут приведены к «правильному» виду.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_without_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с нулевой топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_with_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с ненулевой (0.00005) топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Модуль может правильно обрабатывать дороги с разным характером движения: одностроннее или двустороннее. Для этого необходимо, чтобы в атрибутивной таблице слоя присутствовало поле с указанием типа дороги. Его нужно выбрать в выпадающем списке «Поле направления» с настройках модуля и задать значения для прямого, обратного и двустороннего движения. Под прямым направлением понимается движение в порядке создания точек линии, от первой точки к последней. Соответственно, обратное направление это движение от последней точки линии к первой. Эти два варианта задают односторонние дороги.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим настройку на примере данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. В качестве поля направления выбираем «oneway», тогда двусторонней дороге будет соответствовать значение «no», прямому направлению односторонней дороги будет соответствовать значение «yes», a обратному — какое-либо другое значение, например «-1». На вкладке «По умолчанию» для поля «Направление» выбираем «Двустороннее направление», чтобы дороги, не подпадающие под описанную выше схему трактовались как двусторонние. Все, теперь модуль будет различать дороги и строить маршруты с учетом характера движения по дорогам.&lt;br /&gt;
&lt;br /&gt;
Здесь же можно указать в каком поле находится информация о скорости движения по данному участку дороги. Если такое поле присутствует, то становится возможной оптимизация маршрута не только по расстоянию, но и по времени движения.&lt;br /&gt;
&lt;br /&gt;
На вкладке «По умолчанию» задаются значения параметров по умолчанию, которые будут использоваться, если модуль не сможет извлечь информацию из указанных полей или если эти поля отсутствуют.&lt;br /&gt;
&lt;br /&gt;
=== Библиотека QGIS network-analysis ===&lt;br /&gt;
&lt;br /&gt;
В настоящее время, в экспериментальных версиях QGIS базовый функционал плагина вынесен в отдельную библиотеку [[QGIS_network-analysis_library|network-analysis]], что делает возможным использование алгоритмов сетевого анализа реализованных в модуле из Консоли Python QGIS, а также в своих расширениях.&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=714</id>
		<title>Поиск кратчайшего маршрута c помощью Road graph для QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=714"/>
		<updated>2012-01-12T02:11:13Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: /* Установка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Road graph — расширение свободной ГИС с открытым исходным кодом QGIS, позволяющее осуществлять поиск оптимального маршрута на заданном графе дорог. Расширение автоматически устанавливается вместе с QGIS, начиная с версии 1.6, автор модуля — Сергей Якушев ([http://gis-lab.info/forum/memberlist.php?mode=viewprofile&amp;amp;u=7751 stopa85]).&lt;br /&gt;
&lt;br /&gt;
Для начала работы нужно установить и активировать модуль и загрузить в QGIS линейный векторный слой по которому нужно проложить маршрут, например из данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. Далее, используя инструменты модуля можно легко найти путь от одной заданной точки к другой, указав их на карте. Маршрут можно оптимизировать по расстоянию (самый короткий) или по времени (самый быстрый). Далее в статье подробно рассматриваются все пункты работы с модулем.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph2.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c активированным Road graph. Загружены слои OSM на Тюменскую область, красным цветом отображается проложенный маршрут.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Установка ===&lt;br /&gt;
&lt;br /&gt;
Road graph является расширением ядра QGIS, поэтому достаточно установить QGIS со всеми зависимостями ([http://gis-lab.info/qa/qgis-osgeo4w.html подробнее]) и в Менеджере модулей («Модули — Управление модулями») активировать модуль Road graph.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-01.png|frame|center|&amp;lt;center&amp;gt;Активация Road graph в Менеджере модулей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
После активации модуль добавляет свою панель в левой части окна QGIS и создает вложенный пункт в меню «Вектор» (новые экспериментальные версии QGIS) или пункт в меню «Модули» (Версии QGIS 1.6, 1.7). Панель может быть скрыта/показана с помощью пункта меню «Вид — Панели — Кратчайший маршрут».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-02.png|frame|center|&amp;lt;center&amp;gt;Панель модуля Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
Основные возможности расширения:&lt;br /&gt;
* расчет маршрута, его протяженности и времени пути&lt;br /&gt;
* оптимизация по критерию расстояния или времени&lt;br /&gt;
* экспорт маршрута в векторный слой&lt;br /&gt;
&lt;br /&gt;
В версиях QGIS 1.6, 1.7 присутствует возможность подсветки направления движения дорог (работает медленно, чаще всего используется в целях проверки настроек). В будущих релизах QGIS данная возможность будет удалена. Эффекта подсветки направления можно легко добиться настраивая стиль отображения слоя.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Road direction.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c подсветкой направления дорог, реализованной при помощи стилей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
В качестве слоя дорог можно использовать любой линейный векторный слой в формате, поддерживаемом QGIS. Две линии, имеющие общую точку считаются связанными между собой. &lt;br /&gt;
&lt;br /&gt;
'''ВНИМАНИЕ''': при редактировании слоя дорог в качестве СК проекта необходимо использовать СК слоя. Это&lt;br /&gt;
вызвано тем, что при пересчете координат между разными СК возникают погрешности, что может приводить к появлению разрывов даже при включенном «прилипании».&lt;br /&gt;
&lt;br /&gt;
В атрибутивной таблице слоя могут присутствовать и использоваться в работе расширения следующие поля:&lt;br /&gt;
* скорость движения по участку дороги — числовое поле&lt;br /&gt;
* направление движения — любой тип, приводимый к строке. Прямое и обратное направления соответствуют односторонней дороге, оба направления — двусторонней.&lt;br /&gt;
&lt;br /&gt;
Если значение какого-либо поля не задано, или поле отсутствует — используется значение по умолчанию, изменить которое можно в [[RoadGraph docs#Настройки модуля|настройках расширения]].&lt;br /&gt;
&lt;br /&gt;
Выбор начальной и конечной точек маршрута выполняется при помощи соответствующих кнопок возле полей ввода. Координаты выбранных точек будут отображены в полях ввода.&lt;br /&gt;
&lt;br /&gt;
Нажатие на кнопку «Рассчитать» запустит поиск кратчайшего маршрута с использованием критерия оптимизации, заданного выпадающим списком «Критерий». Кнопка «Экспорт» служит для экспорта построенного маршрута в новый векторный слой, а при помощи кнопки «Очистить» выполняется очистка полей с координатами начальной и конечной точек, а также из области карты удаляются сами точки и построенный маршрут. Краткую справку по работе с модулем можно получить нажав кнопку «Справка».&lt;br /&gt;
&lt;br /&gt;
==== Настройки модуля ====&lt;br /&gt;
&lt;br /&gt;
Перед использованием рекомендуется выполнить настроку модуля. Для этого вызовите диалог настройки из меню «Вектор — Road graph — Параметры модуля Road graph».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-03.png|frame|center|&amp;lt;center&amp;gt;Диалог настройки Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Здесь задаются предпочитаемые единицы измерения времени и расстояния, топологический порог и настраивается распознавание характера движения по дорогам. Если первые два параметра не требуют дополнительных пояснений, то остальные мы рассмотрим подробнее.&lt;br /&gt;
&lt;br /&gt;
При использовании слоя дорог, в котором присутствуют артефакты в виде небольших разрывов между вершинами полилиний, необходимо установить «топологический порог». Топологический порог (или топологическая толерантность) — это расстояние между двумя соседними вершинами, при котором они интерпретируются как одна и та же вершина графа. Эта величина должна быть как можно меньше (чем меньше — тем лучше). Не стоит полагаться на параметр топологической толерантности как на панацею, лучше если Ваши данные будут приведены к «правильному» виду.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_without_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с нулевой топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_with_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с ненулевой (0.00005) топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Модуль может правильно обрабатывать дороги с разным характером движения: одностроннее или двустороннее. Для этого необходимо, чтобы в атрибутивной таблице слоя присутствовало поле с указанием типа дороги. Его нужно выбрать в выпадающем списке «Поле направления» с настройках модуля и задать значения для прямого, обратного и двустороннего движения. Под прямым направлением понимается движение в порядке создания точек линии, от первой точки к последней. Соответственно, обратное направление это движение от последней точки линии к первой. Эти два варианта задают односторонние дороги.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим настройку на примере данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. В качестве поля направления выбираем «oneway», тогда двусторонней дороге будет соответствовать значение «no», прямому направлению односторонней дороги будет соответствовать значение «yes», a обратному — какое-либо другое значение, например «-1». На вкладке «По умолчанию» для поля «Направление» выбираем «Двустороннее направление», чтобы дороги, не подпадающие под описанную выше схему трактовались как двусторонние. Все, теперь модуль будет различать дороги и строить маршруты с учетом характера движения по дорогам.&lt;br /&gt;
&lt;br /&gt;
Здесь же можно указать в каком поле находится информация о скорости движения по данному участку дороги. Если такое поле присутствует, то становится возможной оптимизация маршрута не только по расстоянию, но и по времени движения.&lt;br /&gt;
&lt;br /&gt;
На вкладке «По умолчанию» задаются значения параметров по умолчанию, которые будут использоваться, если модуль не сможет извлечь информацию из указанных полей или если эти поля отсутствуют.&lt;br /&gt;
&lt;br /&gt;
=== Библиотека QGIS network-analysis ===&lt;br /&gt;
&lt;br /&gt;
В настоящее время, в экспериментальных версиях QGIS базовый функционал плагина вынесен в отдельную библиотеку [[QGIS_network-analysis_library|network-analysis]], что делает возможным использование алгоритмов сетевого анализа реализованных в модуле из Консоли Python QGIS, а также в своих расширениях.&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=706</id>
		<title>Поиск кратчайшего маршрута c помощью Road graph для QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=706"/>
		<updated>2012-01-11T12:17:56Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Изменение номеров ревизий, на номера версий QGIS&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Road graph — расширение QGIS, позволяющее осуществлять поиск кратчейшего маршрута на заданном графе дорог. Входит в состав QGIS, начиная с версии 1.6, автор модуля — Сергей Якушев ([http://gis-lab.info/forum/memberlist.php?mode=viewprofile&amp;amp;u=7751 stopa85]).&lt;br /&gt;
&lt;br /&gt;
Активировав модуль и загрузив в QGIS линейный векторный слой можно легко найти путь от одной заданной точки к другой, оптимизировав его по расстоянию (самый короткий) или по времени (самый быстрый).&lt;br /&gt;
[[Файл:roadgraph2.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c активированным Road graph. Загружены слои OSM на Тюменскую область, красным цветом отображается проложенный маршрут.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Установка ===&lt;br /&gt;
&lt;br /&gt;
Road graph является расширением ядра QGIS, поэтому достаточно установить QGIS со всеми зависимостями ([http://gis-lab.info/qa/qgis-osgeo4w.html подробнее]) и в Менеджере модулей («Модули — Управление модулями») активировать модуль Road graph.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-01.png|frame|center|&amp;lt;center&amp;gt;Активация Road graph в Менеджере модулей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
После активации модуль добавляет свою панель в левой части окна QGIS и создает вложенный элемент в меню «Вектор».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-02.png|frame|center|&amp;lt;center&amp;gt;Панель модуля Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
Основные возможности расширения:&lt;br /&gt;
* расчет маршрута, его протяженности и времени пути&lt;br /&gt;
* оптимизация по критерию расстояния или времени&lt;br /&gt;
* экспорт маршрута в векторный слой&lt;br /&gt;
&lt;br /&gt;
В версиях QGIS 1.6, 1.7 присутствует возможность подсветки направления движения дорог (работает медленно, чаще всего используется в целях проверки настроек). В будущих релизах QGIS данная возможность будет удалена. Эффекта подсветки направления можно легко добиться настраивая стиль отображения слоя.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Road direction.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c подсветкой направления дорог, реализованной при помощи стилей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
В качестве слоя дорог можно использовать любой линейный векторный слой в формате, поддерживаемом QGIS. Две линии, имеющие общую точку&lt;br /&gt;
считаются связанными между собой. '''ВНИМАНИЕ''': при редактировании слоя дорог в качестве СК проекта необходимо использовать СК слоя. Это&lt;br /&gt;
вызвано тем, что при пересчете координат между разными СК возникают погрешности, что может приводить к появлению разрывов даже при&lt;br /&gt;
включенном «прилипании».&lt;br /&gt;
&lt;br /&gt;
В атрибутивной таблице слоя могут присутствовать и задействоваться следующие поля:&lt;br /&gt;
* скорость движения по участку дороги — числовое поле&lt;br /&gt;
* направление движения — любой тип, приводимый к строке. Прямое и обратное направления соответствуют односторонней дороге, оба направления — двусторонней.&lt;br /&gt;
&lt;br /&gt;
Если значение какого-либо поля не задано, или поле отсутствует — используется значение по умолчанию, изменить которое можно в [[RoadGraph docs#Настройки модуля|настройках расширения]].&lt;br /&gt;
&lt;br /&gt;
Выбор начальной и конечной точек маршрута выполняется при помощи соответствующих кнопок возле полей ввода. Координаты выбранных точек будут отображены в полях ввода.&lt;br /&gt;
&lt;br /&gt;
Нажатие на кнопку «Рассчитать» запустит поиск кратчайшего маршрута с использованием критерия оптимизации, заданного выпадающим списком «Критерий». Кнопка «Экспорт» служит для экспорта построенного маршрута в новый векторный слой, а при помощи кнопки «Очистить» выполняется очистка полей с координатами начальной и конечной точек, а также из области карты удаляются сами точки и построенный маршрут. Краткую справку по работе с модулем можно получить нажав кнопку «Справка».&lt;br /&gt;
&lt;br /&gt;
==== Настройки модуля ====&lt;br /&gt;
&lt;br /&gt;
Перед использованием рекомендуется выполнить настроку модуля. Для этого вызовите диалог настройки из меню «Вектор — Road graph — Параметры модуля Road graph».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-03.png|frame|center|&amp;lt;center&amp;gt;Диалог настройки Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Здесь задаются предпочитаемые единицы измерения времени и расстояния, топологический порог и настраивается распознавание характера движения по дорогам. Если первые два параметра не требуют дополнительных пояснений, то остальные мы рассмотрим подробнее.&lt;br /&gt;
&lt;br /&gt;
При использовании слоя дорог, в котором присутствуют артефакты в виде небольших разрывов между вершинами полилиний, необходимо установить «топологический порог». Топологический порог (или топологическая толерантность) — это расстояние между двумя соседними вершинами, при котором они интерпретируются как одна и та же вершина графа. Эта величина должна быть как можно меньше (чем меньше — тем лучше). Не стоит полагаться на параметр топологической толерантности как на панацею, лучше если Ваши данные будут приведены к «правильному» виду.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_without_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с нулевой топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_with_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с ненулевой (0.00005) топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Модуль может правильно обрабатывать дороги с разным характером движения: одностроннее или двустороннее. Для этого необходимо, чтобы в атрибутивной таблице слоя присутствовало поле с указанием типа дороги. Его нужно выбрать в выпадающем списке «Поле направления» с настройках модуля и задать значения для прямого, обратного и двустороннего движения. Под прямым направлением понимается движение в порядке создания точек линии, от первой точки к последней. Соответственно, обратное направление это движение от последней точки линии к первой. Эти два варианта задают односторонние дороги.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим настройку на примере данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. В качестве поля направления выбираем «oneway», тогда двусторонней дороге будет соответствовать значение «no», прямому направлению односторонней дороги будет соответствовать значение «yes», a обратному — какое-либо другое значение, например «-1». На вкладке «По умолчанию» для поля «Направление» выбираем «Двустороннее направление», чтобы дороги, не подпадающие под описанную выше схему трактовались как двусторонние. Все, теперь модуль будет различать дороги и строить маршруты с учетом характера движения по дорогам.&lt;br /&gt;
&lt;br /&gt;
Здесь же можно указать в каком поле находится информация о скорости движения по данному участку дороги. Если такое поле присутствует, то становится возможной оптимизация маршрута не только по расстоянию, но и по времени движения.&lt;br /&gt;
&lt;br /&gt;
На вкладке «По умолчанию» задаются значения параметров по умолчанию, которые будут использоваться, если модуль не сможет извлечь информацию из указанных полей или если эти поля отсутствуют.&lt;br /&gt;
&lt;br /&gt;
=== Библиотека QGIS network-analysis ===&lt;br /&gt;
&lt;br /&gt;
В настоящее время, в экспериментальных версиях QGIS базовый функционал плагина вынесен в отдельную библиотеку [[QGIS_network-analysis_library|network-analysis]], что делает возможным использование алгоритмов сетевого анализа реализованных в модуле из Консоли Python QGIS, а также в своих расширениях.&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=705</id>
		<title>Поиск кратчайшего маршрута c помощью Road graph для QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=705"/>
		<updated>2012-01-11T08:51:17Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: доисправление картинок (не отображаются подписи)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Road graph — расширение QGIS, позволяющее осуществлять поиск кратчейшего маршрута на заданном графе дорог. Входит в состав QGIS, начиная с r15068 ([http://hub.qgis.org/projects/quantum-gis/repository/revisions/0a76ab4212ab5c5ef63c98f8a978034e2c0c42d2 0a76ab4212]), автор модуля — Сергей Якушев ([http://gis-lab.info/forum/memberlist.php?mode=viewprofile&amp;amp;u=7751 stopa85]).&lt;br /&gt;
&lt;br /&gt;
Активировав модуль и загрузив в QGIS линейный векторный слой можно легко найти путь от одной заданной точки к другой, оптимизировав его по расстоянию (самый короткий) или по времени (самый быстрый).&lt;br /&gt;
[[Файл:roadgraph2.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c активированным Road graph. Загружены слои OSM на Тюменскую область, красным цветом отображается проложенный маршрут.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Установка ===&lt;br /&gt;
&lt;br /&gt;
При использовании более-менее актуальной версии QGIS (&amp;gt;=1.6.0) никаких дополнительных действий по установке модуля выполнять не нужно, так как Road graph является расширением ядра QGIS. Достаточно установить QGIS со всеми зависимостями ([http://gis-lab.info/qa/qgis-osgeo4w.html подробнее]) и в Менеджере модулей («Модули — Управление модулями») активировать модуль Road graph.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-01.png|frame|center|&amp;lt;center&amp;gt;Активация Road graph в Менеджере модулей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
После активации модуль добавляет свою панель в левой части окна QGIS и создает вложенный элемент в меню «Вектор».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-02.png|frame|center|&amp;lt;center&amp;gt;Панель модуля Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля интегрирован в дерево исходных кодов QGIS, получить его можно из [https://github.com/qgis/Quantum-GIS основного репозитория].&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
Основные возможности расширения:&lt;br /&gt;
* расчет маршрута, его протяженности и времени пути&lt;br /&gt;
* оптимизация по критерию расстояния или времени&lt;br /&gt;
* экспорт маршрута в векторный слой&lt;br /&gt;
&lt;br /&gt;
В версиях QGIS 1.6, 1.7 присутствует возможность подсветки направления движения дорог (работает медленно, чаще всего используется в целях проверки настроек). В QGIS 1.8 и старше данная возможность удалена. Эффекта подсветки направления можно легко добиться настраивая стиль отображения слоя.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Road direction.png|700px|thumb|center|&amp;lt;center&amp;gt;QGIS c подсветкой направления дорог, реализованной при помощи стилей&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
В качестве слоя дорог можно использовать любой линейный векторный слой в формате, поддерживаемом QGIS. Две линии, имеющие общую точку&lt;br /&gt;
считаются связанными между собой. '''ВНИМАНИЕ''': при редактировании слоя дорог в качестве СК проекта необходимо использовать СК слоя. Это&lt;br /&gt;
вызвано тем, что при пересчете координат между разными СК возникают погрешности, что может приводить к появлению разрывов даже при&lt;br /&gt;
включенном «прилипании».&lt;br /&gt;
&lt;br /&gt;
В атрибутивной таблице слоя могут присутствовать и задействоваться следующие поля:&lt;br /&gt;
* скорость движения по участку дороги — числовое поле&lt;br /&gt;
* направление движения — любой тип, приводимый к строке. Прямое и обратное направления соответствуют односторонней дороге, оба направления — двусторонней.&lt;br /&gt;
&lt;br /&gt;
Если значение какого-либо поля не задано, или поле отсутствует — используется значение по умолчанию, изменить которое можно в [[RoadGraph docs#Настройки модуля|настройках расширения]].&lt;br /&gt;
&lt;br /&gt;
Выбор начальной и конечной точек маршрута выполняется при помощи соответствующих кнопок возле полей ввода. Координаты выбранных точек будут отображены в полях ввода.&lt;br /&gt;
&lt;br /&gt;
Нажатие на кнопку «Рассчитать» запустит поиск кратчайшего маршрута с использованием критерия оптимизации, заданного выпадающим списком «Критерий». Кнопка «Экспорт» служит для экспорта построенного маршрута в новый векторный слой, а при помощи кнопки «Очистить» выполняется очистка полей с координатами начальной и конечной точек, а также из области карты удаляются сами точки и построенный маршрут. Краткую справку по работе с модулем можно получить нажав кнопку «Справка».&lt;br /&gt;
&lt;br /&gt;
==== Настройки модуля ====&lt;br /&gt;
&lt;br /&gt;
Перед использованием рекомендуется выполнить настроку модуля. Для этого вызовите диалог настройки из меню «Вектор — Road graph — Параметры модуля Road graph».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-03.png|frame|center|&amp;lt;center&amp;gt;Диалог настройки Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Здесь задаются предпочитаемые единицы измерения времени и расстояния, топологический порог и настраивается распознавание характера движения по дорогам. Если первые два параметра не требуют дополнительных пояснений, то остальные мы рассмотрим подробнее.&lt;br /&gt;
&lt;br /&gt;
При использовании слоя дорог, в котором присутствуют артефакты в виде небольших разрывов между вершинами полилиний, необходимо установить «топологический порог». Топологический порог (или топологическая толерантность) — это расстояние между двумя соседними вершинами, при котором они интерпретируются как одна и та же вершина графа. Эта величина должна быть как можно меньше (чем меньше — тем лучше). Не стоит полагаться на параметр топологической толерантности как на панацею, лучше если Ваши данные будут приведены к «правильному» виду.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_without_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с нулевой топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_with_TT.png|700px|thumb|center|&amp;lt;center&amp;gt;Поиск пути с ненулевой (0.00005) топологической толерантностью (в слой дорог введен искусственный артефакт)&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Модуль может правильно обрабатывать дороги с разным характером движения: одностроннее или двустороннее. Для этого необходимо, чтобы в атрибутивной таблице слоя присутствовало поле с указанием типа дороги. Его нужно выбрать в выпадающем списке «Поле направления» с настройках модуля и задать значения для прямого, обратного и двустроннего движения. Под прямым направлением понимается движение в порядке создания точек линии, от первой точки к последней. Соответственно, обратное направление это движение от последней точки линии к первой. Эти два варианта задают односторонние дороги.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим настройку на примере данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. В качестве поля направления выбираем «oneway», тогда двусторонней дороге будет соответствовать значение «no», прямому направлению односторонней дороги будет соответствовать значение «yes», a обратному — какое-либо другое значение, например «123». На вкладке «По умолчанию» для поля «Направление» выбираем «Двустороннее направление», чтобы дороги, не подпадающие под описанную выше схему трактовались как двусторонние. Все, теперь модуль будет различать дороги и строить маршруты с учетом характера движения по дорогам.&lt;br /&gt;
&lt;br /&gt;
Здесь же можно указать в каком поле находится информация о скорости движения по данному участку дороги. Если такое поле присутствует, то становится возможной оптимизация маршрута не только по рассточнию, но и по времени движения.&lt;br /&gt;
&lt;br /&gt;
На вкладке «По умолчанию» задаются значения параметров по умолчанию, которые будут использоваться, если модуль не сможет извлечь информацию из указанных полей или если эти поля отсутствуют.&lt;br /&gt;
&lt;br /&gt;
=== Библиотека QGIS network-analysis ===&lt;br /&gt;
&lt;br /&gt;
В настоящее время, в экспериментальных версиях QGIS базовый функционал плагина вынесен в отдельную библиотеку [[QGIS_network-analysis_library|network-analysis]], что делает возможным использование алгоритмов сетевого анализа реализованных в модуле из Консоли Python QGIS, а также в своих расширениях.&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=702</id>
		<title>Поиск кратчайшего маршрута c помощью Road graph для QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=702"/>
		<updated>2012-01-11T03:19:29Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Чуть вверх первый скриншот&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Road graph — расширение QGIS, позволяющее осуществлять поиск кратчейшего маршрута на заданном графе дорог. Входит в состав QGIS, начиная с r15068 ([http://hub.qgis.org/projects/quantum-gis/repository/revisions/0a76ab4212ab5c5ef63c98f8a978034e2c0c42d2 0a76ab4212]), автор модуля — Сергей Якушев ([http://gis-lab.info/forum/memberlist.php?mode=viewprofile&amp;amp;u=7751 stopa85]).&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph2.png|400px|thumb|center|&amp;lt;center&amp;gt;Внешний вид Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Установка ===&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-01.png|thumb|Активация Road graph в Менеджере модулей]]&lt;br /&gt;
&lt;br /&gt;
При использовании более-менее актуальной версии QGIS никаких дополнительных действий по установке модуля выполнять не нужно, так как Road graph является расширением ядра QGIS. Достаточно установить QGIS со всеми зависимостями ([http://gis-lab.info/qa/qgis-osgeo4w.html подробнее]) и в Менеджере модулей («Модули — Управление модулями») активировать модуль Road graph.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-02.png|thumb|Панель модуля Road graph]]&lt;br /&gt;
&lt;br /&gt;
После активации модуль добавляет свою панель в левой части окна QGIS и создает вложенный элемент в меню «Вектор».&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля интегрирован в дерево исходных кодов QGIS, получить его можно из [https://github.com/qgis/Quantum-GIS основного репозитория].&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
Основные возможности расширения:&lt;br /&gt;
* расчет маршрута, его протяженности и времени пути&lt;br /&gt;
* оптимизация по критерию расстояния или времени&lt;br /&gt;
* экспорт маршрута в векторный слой&lt;br /&gt;
&lt;br /&gt;
В версиях QGIS 1.6, 1.7 присутствует возможность подсветки направления движения дорог (работает медленно, чаще всего используется в целях проверки настроек). В QGIS 1.8 и старше данная возможность удалена. Эффекта подсветки направления можно легко добиться настраивая стиль отображения слоя.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Road direction.png|thumb|QGIS c подсветкой направления дорог, реализованной при помощи стилей]]&lt;br /&gt;
&lt;br /&gt;
В качестве слоя дорог можно использовать любой линейный векторный слой в формате, поддерживаемом QGIS. Две линии, имеющие общую точку&lt;br /&gt;
считаются связанными между собой. '''ВНИМАНИЕ''': при редактировании слоя дорог в качестве СК проекта необходимо использовать СК слоя. Это&lt;br /&gt;
вызвано тем, что при пересчете координат между разными СК возникают погрешности, что может приводить к появлению разрывов даже при&lt;br /&gt;
включенном «прилипании».&lt;br /&gt;
&lt;br /&gt;
В атрибутивной таблице слоя могут присутствовать и задействоваться следующие поля:&lt;br /&gt;
* скорость движения по участку дороги — числовое поле&lt;br /&gt;
* направление движения — любой тип, приводимый к строке. Прямое и обратное направления соответствуют односторонней дороге, оба направления — двусторонней.&lt;br /&gt;
&lt;br /&gt;
Если значение какого-либо поля не задано, или поле отсутствует — используется значение по умолчанию, изменить которое можно в [[RoadGraph docs#Настройки модуля|настройках расширения]].&lt;br /&gt;
&lt;br /&gt;
Выбор начальной и конечной точек маршрута выполняется при помощи соответствующих кнопок возле полей ввода. Координаты выбранных точек будут отображены в полях ввода.&lt;br /&gt;
&lt;br /&gt;
Нажатие на кнопку «Рассчитать» запустит поиск кратчайшего маршрута с использованием критерия оптимизации, заданного выпадающим списком «Критерий». Кнопка «Экспорт» служит для экспорта построенного маршрута в новый векторный слой, а при помощи кнопки «Очистить» выполняется очистка полей с координатами начальной и конечной точек, а также из области карты удаляются сами точки и построенный маршрут. Краткую справку по работе с модулем можно получить нажав кнопку «Справка».&lt;br /&gt;
&lt;br /&gt;
==== Настройки модуля ====&lt;br /&gt;
&lt;br /&gt;
Перед использованием рекомендуется выполнить настроку модуля. Для этого вызовите диалог настройки из меню «Вектор — Road graph — Параметры модуля Road graph».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-03.png|thumb|Диалог настройки Road graph]]&lt;br /&gt;
&lt;br /&gt;
Здесь задаются предпочитаемые единицы измерения времени и расстояния, топологический порог и настраивается распознавание характера движения по дорогам. Если первые два параметра не требуют дополнительных пояснений, то остальные мы рассмотрим подробнее.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_without_TT.png|thumb|Поиск пути с нулевой топологической толерантностью (в слой дорог введен искусственный артефакт)]]&lt;br /&gt;
[[Изображение:RoadGraph_with_TT.png|thumb|Поиск пути с ненулевой (0.00005) топологической толерантностью (в слой дорог введен искусственный артефакт)]]&lt;br /&gt;
При использовании слоя дорог, в котором присутствуют артефакты в виде небольших разрывов между вершинами полилиний, необходимо установить «топологический порог». Топологический порог (или топологическая толерантность) — это расстояние между двумя соседними вершинами, при котором они интерпретируются как одна и та же вершина графа. Эта величина должна быть как можно меньше (чем меньше — тем лучше). Не стоит полагаться на параметр топологической толерантности как на панацею, лучше если Ваши данные будут приведены к &amp;quot;правильному&amp;quot; виду.&lt;br /&gt;
&lt;br /&gt;
Модуль может правильно обрабатывать дороги с разным характером движения: одностроннее или двустороннее. Для этого необходимо, чтобы в атрибутивной таблице слоя присутствовало поле с указанием типа дороги. Его нужно выбрать в выпадающем списке «Поле направления» с настройках модуля и задать значения для прямого, обратного и двустроннего движения. Под прямым направлением понимается движение в порядке создания точек линии, от первой точки к последней. Соответственно, обратное направление это движение от последней точки линии к первой. Эти два варианта задают односторонние дороги.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим настройку на примере данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. В качестве поля направления выбираем &amp;quot;oneway&amp;quot;, тогда двусторонней дороге будет соответствовать значение &amp;quot;no&amp;quot;, прямому направлению односторонней дороги будет соответствовать значение &amp;quot;yes&amp;quot;, a обратному — какое-либо другое значение, например &amp;quot;123&amp;quot;. На вкладке «По умолчанию» для поля «Направление» выбираем «Двустороннее направление», чтобы дороги, не подпадающие под описанную выше схему трактовались как двусторонние. Все, теперь модуль будет различать дороги и строить маршруты с учетом характера движения по дорогам.&lt;br /&gt;
&lt;br /&gt;
Здесь же можно указать в каком поле находится информация о скорости движения по данному участку дороги. Если такое поле присутствует, то становится возможной оптимизация маршрута не только по рассточнию, но и по времени движения.&lt;br /&gt;
&lt;br /&gt;
На вкладке «По умолчанию» задаются значения параметров по умолчанию, которые будут использоваться, если модуль не сможет извлечь информацию из указанных полей или если эти поля отсутствуют.&lt;br /&gt;
&lt;br /&gt;
=== Библиотека QGIS network-analysis ===&lt;br /&gt;
&lt;br /&gt;
В настоящее время, в экспериментальных версиях QGIS базовый функционал плагина вынесен в отдельную библиотеку [[QGIS_network-analysis_library|network-analysis]], что делает возможным использование алгоритмов сетевого анализа реализованных в модуле из Консоли Python QGIS, а также в своих расширениях.&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=701</id>
		<title>Библиотека сетевого анализа QGIS: описание и примеры</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_QGIS:_%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B&amp;diff=701"/>
		<updated>2012-01-11T03:12:27Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Добавлено: Внимание статья находиться на стадии разработки&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style='color:red;'&amp;gt;&amp;lt;big&amp;gt;Внимание статья находиться на стадии разработки&amp;lt;/big&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
QGIS network-analysis library — библиотека входящая в состав свободной ГИС Quantum GIS, которая:&lt;br /&gt;
* может создавать математический граф из географических данных (линейных векторных слоев), пригодный для анализа методами теории графов&lt;br /&gt;
* реализует базовые методы теории графов (в настоящее время только метод Дейкстры)&lt;br /&gt;
&lt;br /&gt;
=== История ===&lt;br /&gt;
&lt;br /&gt;
Библиотека QGIS network-analysis появилась путем экспорта базовых функций из плагина RoadGraph в отдельную библиотеку.&lt;br /&gt;
&lt;br /&gt;
Начиная с [https://github.com/qgis/Quantum-GIS/commit/ee19294562b00c6ce957945f14c1727210cffdf7 ee19294562], появилась возможность использовать функционал библиотеки в своих расширениях, а также из Консоли Python QGIS.&lt;br /&gt;
&lt;br /&gt;
=== Применение ===&lt;br /&gt;
&lt;br /&gt;
Чтобы получить доступ к функциям библиотеки сетевого анализа необходимо импортировать модуль networkanalysis&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первое, что нужно сделать — это подготовить исходные данные, т.е. преобразовать векторный слой в граф. Все дальнейшие действия будут выполняться именно с ним. За построение графа дорог отвечает так называемый Director. В настоящее время бибилотека располагает только одним директором: [http://doc.qgis.org/api/classQgsLineVectorLayerDirector.html QgsLineVectorLayerDirector], которой строит граф по линейному векторному слою.&lt;br /&gt;
&lt;br /&gt;
В конструктор директора передается линейный векторный слой, по которому будет строиться граф, а также информация о характере движения по каждому сегменту дороги (разрешенное направление, одностороннее или двустороннее движение). Рассмотрим эти параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;vl&amp;lt;/tt&amp;gt; — векторный слой, по которому будет строиться граф.&lt;br /&gt;
* &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; — индекс поля атрибутивной таблицы, которое содержит информацию о направлении движения&lt;br /&gt;
* &amp;lt;tt&amp;gt;directDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее прямому направлению движения (т.е. движению в порядке создания точек линии, от первой к последней)&lt;br /&gt;
* &amp;lt;tt&amp;gt;reverseDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее обратному направлению движения (от последней точки к первой)&lt;br /&gt;
* &amp;lt;tt&amp;gt;bothDirectionValue&amp;lt;/tt&amp;gt; — значение поля, соответствующее двустроннему движению (т.е. допускается движение как от первой точки к последней, так и в обратном направлении)&lt;br /&gt;
* &amp;lt;tt&amp;gt;defaultDirection&amp;lt;/tt&amp;gt; — направление движения по умолчанию. Будет использоваться для тех участков дорог, у которых значение поля &amp;lt;tt&amp;gt;directionFieldId&amp;lt;/tt&amp;gt; не задано или не совпадает ни с одним из вышеперечисленных.&lt;br /&gt;
&lt;br /&gt;
Например&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# не использовать информацию о направлении движения из атрибутов слоя, все дороги трактуются как двустронние&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, -1, '', '', '', 3 )&lt;br /&gt;
&lt;br /&gt;
# информация о направлении движения находится в поле с индексом 5. Односторонние дороги с прямым направлением&lt;br /&gt;
# движения имееют значение атрибута &amp;quot;yes&amp;quot;, односторонние дороги с обратным направлением — &amp;quot;1&amp;quot;, и соответственно&lt;br /&gt;
# двусторонние ­дороги — &amp;quot;no&amp;quot;. По умолчанию дороги считаются двусторонними. Такая схема подходит для использования&lt;br /&gt;
# c данными OpenStreetMap&lt;br /&gt;
director = QgsLineVectorLayerDirector( vLayer, 5, 'yes', '1', 'no', 3 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Следующим шагом необходимо создать стратегию назначения свойств ребрам графа. Стратегия рассчитывает свойства ребра, запрашивая данные у директора, и именно основываясь на свойствах ребер будет выполняться поиск оптимального маршрута. Пока в библиотеке реализована только одна стратегия, учитывающая длину маршрута: [http://doc.qgis.org/api/classQgsDistanceArcProperter.html QgsDistanceArcProperter]. При необходимости, можно создать свою стратегию, которая будет учитывать необходимые параметры. Например, в модуле Road graph используется стратегия, учитывающая время движения по ребру графа.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сообщаем директору об используемой стратегии. Один директор может использовать несколько стратегий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь создаем строителя, который собственно и будет строить граф заданного типа. Стандартный строитель [http://doc.qgis.org/api/classQgsGraphBuilder.html QgsGraphBuilder] строит граф типа [http://doc.qgis.org/api/classQgsGraph.html QgsGraph]. При желании можно написать свою реализацию, которая будет строить граф, совместимый с такими библиотеками как Boost или networkX.&lt;br /&gt;
&lt;br /&gt;
Строитель принимает следующие параметры:&lt;br /&gt;
* &amp;lt;tt&amp;gt;crs&amp;lt;/tt&amp;gt; — используемая система координат. Обязательный параметр.&lt;br /&gt;
* &amp;lt;tt&amp;gt;otfEnabled&amp;lt;/tt&amp;gt; — указывает на использование перепроецирования «на лету». По умолчанию &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;topologyTolerance&amp;lt;/tt&amp;gt; — топологическая толерантность. Значение по умолчанию 0.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ellipsoidID&amp;lt;/tt&amp;gt; — используемый эллипсоид. По умолчанию &amp;quot;WGS84&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# задана только используемая СК, все остальные параметры по умолчанию&lt;br /&gt;
builder = QgsGraphBuilder( myCRS )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также необходимо задать одну или несколько точек, которые будет использоваться при анализе. Например так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startPoint = QgsPoint( 82.7112, 55.1672 )&lt;br /&gt;
endPoint = QgsPoint( 83.1879, 54.7079 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Затем строим граф и «привязываем» к нему точки&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ startPoint, endPoint ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Построение графа может занять некоторое время (зависит от количества обектов в слое и размера самого слоя). После построения мы получим граф, пригодный для анализа&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно получить индексы наших точек&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
startId = graph.findVertex( tiedPoints[ 0 ] )&lt;br /&gt;
endId = graph.findVertex( tiedPoints[ 1 ] )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Анализ графа выполняет [http://doc.qgis.org/api/classQgsGraphAnalyzer.html QgsGraphAnalyzer]. Вот так можно получить дерево кратчайших путей с корнем в точке startPoint&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, startId, 0 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; принимает три аргумента:&lt;br /&gt;
* &amp;lt;tt&amp;gt;source&amp;lt;/tt&amp;gt; — исходный граф&lt;br /&gt;
* &amp;lt;tt&amp;gt;startVertexIdx&amp;lt;/tt&amp;gt; — индекс точки на графе (корень дерева)&lt;br /&gt;
* &amp;lt;tt&amp;gt;criterionNum&amp;lt;/tt&amp;gt; — порядковый номер используемой стратегии (отсчет ведется от 0).&lt;br /&gt;
&lt;br /&gt;
На выходе мы получим граф, тип которого зависит от используемого строителя. Отобразить дерево на карте можно при помощи следующего кода&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
id = tree.findVertex( tiedPoint[ 0 ] )&lt;br /&gt;
not_begin = [ id ]&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setWidth( 3 )&lt;br /&gt;
&lt;br /&gt;
while len( not_begin ) &amp;gt; 0:&lt;br /&gt;
  curId = not_begin[ 0 ]&lt;br /&gt;
  not_begin = not_begin[ 1: ]&lt;br /&gt;
  rb.addPoint( tree.vertex( curId ).point() )&lt;br /&gt;
  f = 1&lt;br /&gt;
  for i in tree.vertex( curId ).outArc():&lt;br /&gt;
    if f == 1:&lt;br /&gt;
      not_begin = [ tree.arc( i ).inVertex() ] + not_begin&lt;br /&gt;
      f = 0&lt;br /&gt;
    else:&lt;br /&gt;
      not_begin = not_begin + [ tree.arc( i ).inVertex() ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для получения кратчайшего маршрута между двумя точками используется следующий подход. Обе точки (начальная A и конечная B) «привязываются» к графу на этапе построения, затем при помощи метода &amp;lt;tt&amp;gt;shortestTree&amp;lt;/tt&amp;gt; получаем дерево кратчайших маршрутов с корнем в начальной точке A. В этом же дереве находим конечную точку B. Начинаем спуск по дереву от точки B к точке А. Для этого:&lt;br /&gt;
# добавляем точку B в маршрут&lt;br /&gt;
# берем ребро, которое входит в точку B&lt;br /&gt;
# находим точку Т, из которой это ребро выходит&lt;br /&gt;
# добавляем точку T в маршрут&lt;br /&gt;
# проверям, входят ли какие-то ребра в вершину T. Если входящих ребер нет, то T = A и построение маршрута окончено. В противном случае повторям все действия с п. 2 но уже для точки T&lt;br /&gt;
&lt;br /&gt;
Вот работающий пример для Консоли Python QGIS (только замените координаты начальной и конечной точки на свои, а также выделите слой дорог в списке слоёв карты)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
from qgis.gui import *&lt;br /&gt;
from qgis.networkanalysis import *&lt;br /&gt;
&lt;br /&gt;
vl = qgis.utils.iface.mapCanvas().currentLayer()&lt;br /&gt;
director = QgsLineVectorLayerDirector( vl, -1, '', '', '', 3 )&lt;br /&gt;
properter = QgsDistanceArcProperter()&lt;br /&gt;
director.addProperter( properter )&lt;br /&gt;
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()&lt;br /&gt;
builder = QgsGraphBuilder( crs )&lt;br /&gt;
&lt;br /&gt;
pStart = QgsPoint( 65.4697, 56.989 )&lt;br /&gt;
pStop = QgsPoint( 65.4722, 57.2445 )&lt;br /&gt;
&lt;br /&gt;
tiedPoints = director.makeGraph( builder, [ pStart, pStop ] )&lt;br /&gt;
graph = builder.graph()&lt;br /&gt;
&lt;br /&gt;
tStart = tiedPoints[ 0 ]&lt;br /&gt;
tStop = tiedPoints[ 1 ]&lt;br /&gt;
&lt;br /&gt;
idStart = graph.findVertex( tStart )&lt;br /&gt;
idStop = graph.findVertex( tStop )&lt;br /&gt;
&lt;br /&gt;
tree = QgsGraphAnalyzer.shortestTree( graph, idStart, 0 )&lt;br /&gt;
&lt;br /&gt;
p = []&lt;br /&gt;
while (idStart != idStop ):&lt;br /&gt;
  l = tree.vertex( idStop ).inArc()&lt;br /&gt;
  if len( l ) == 0:&lt;br /&gt;
    break&lt;br /&gt;
  e = tree.arc( l[ 0 ] )&lt;br /&gt;
  p.insert( 0, tree.vertex( e.inVertex() ).point() )&lt;br /&gt;
  idStop = e.outVertex()&lt;br /&gt;
&lt;br /&gt;
p.insert( 0, tStart )&lt;br /&gt;
&lt;br /&gt;
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )&lt;br /&gt;
rb.setColor( Qt.red )&lt;br /&gt;
&lt;br /&gt;
for pnt in p:&lt;br /&gt;
  rb.addPoint(pnt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Актуальная документация ===&lt;br /&gt;
&lt;br /&gt;
Актуальную документацию всегда можно получить в разделе [http://doc.qgis.org/api/group__networkanalysis.html QGIS network analysis library] описания [http://doc.qgis.org/api/index.html QGIS API].&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Roadgraph-03.png&amp;diff=700</id>
		<title>Файл:Roadgraph-03.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Roadgraph-03.png&amp;diff=700"/>
		<updated>2012-01-10T19:26:02Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: загружена новая версия «Файл:Roadgraph-03.png»: Приведение скриншотов к единому стилю&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Настройки модуля Road graph&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=699</id>
		<title>Поиск кратчайшего маршрута c помощью Road graph для QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BA%D1%80%D0%B0%D1%82%D1%87%D0%B0%D0%B9%D1%88%D0%B5%D0%B3%D0%BE_%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%B0_c_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_Road_graph_%D0%B4%D0%BB%D1%8F_QGIS&amp;diff=699"/>
		<updated>2012-01-10T19:23:23Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: Расположение скриншотов&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Road graph — расширение QGIS, позволяющее осуществлять поиск кратчейшего маршрута на заданном графе дорог. Входит в состав QGIS, начиная с r15068 ([http://hub.qgis.org/projects/quantum-gis/repository/revisions/0a76ab4212ab5c5ef63c98f8a978034e2c0c42d2 0a76ab4212]), автор модуля — Сергей Якушев ([http://gis-lab.info/forum/memberlist.php?mode=viewprofile&amp;amp;u=7751 stopa85]).&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph2.png|400px|thumb|center|&amp;lt;center&amp;gt;Внешний вид Road graph&amp;lt;/center&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Установка ===&lt;br /&gt;
&lt;br /&gt;
При использовании более-менее актуальной версии QGIS никаких дополнительных действий по установке модуля выполнять не нужно, так как Road graph является расширением ядра QGIS. Достаточно установить QGIS со всеми зависимостями ([http://gis-lab.info/qa/qgis-osgeo4w.html подробнее]) и в Менеджере модулей («Модули — Управление модулями») активировать модуль Road graph.&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-01.png|thumb|Активация Road graph в Менеджере модулей]]&lt;br /&gt;
&lt;br /&gt;
После активации модуль добавляет свою панель в левой части окна QGIS и создает вложенный элемент в меню «Вектор».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-02.png|thumb|Панель модуля Road graph]]&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля интегрирован в дерево исходных кодов QGIS, получить его можно из [https://github.com/qgis/Quantum-GIS основного репозитория].&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
Основные возможности расширения:&lt;br /&gt;
* расчет маршрута, его протяженности и времени пути&lt;br /&gt;
* оптимизация по критерию расстояния или времени&lt;br /&gt;
* экспорт маршрута в векторный слой&lt;br /&gt;
&lt;br /&gt;
В версиях QGIS 1.6, 1.7 присутствует возможность подсветки направления движения дорог (работает медленно, чаще всего используется в целях проверки настроек). В QGIS 1.8 и старше данная возможность удалена. Эффекта подсветки направления можно легко добиться настраивая стиль отображения слоя.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:Road direction.png|thumb|QGIS c подсветкой направления дорог, реализованной при помощи стилей]]&lt;br /&gt;
&lt;br /&gt;
В качестве слоя дорог можно использовать любой линейный векторный слой в формате, поддерживаемом QGIS. Две линии, имеющие общую точку&lt;br /&gt;
считаются связанными между собой. '''ВНИМАНИЕ''': при редактировании слоя дорог в качестве СК проекта необходимо использовать СК слоя. Это&lt;br /&gt;
вызвано тем, что при пересчете координат между разными СК возникают погрешности, что может приводить к появлению разрывов даже при&lt;br /&gt;
включенном «прилипании».&lt;br /&gt;
&lt;br /&gt;
В атрибутивной таблице слоя могут присутствовать и задействоваться следующие поля:&lt;br /&gt;
* скорость движения по участку дороги — числовое поле&lt;br /&gt;
* направление движения — любой тип, приводимый к строке. Прямое и обратное направления соответствуют односторонней дороге, оба направления — двусторонней.&lt;br /&gt;
&lt;br /&gt;
Если значение какого-либо поля не задано, или поле отсутствует — используется значение по умолчанию, изменить которое можно в [[RoadGraph docs#Настройки модуля|настройках расширения]].&lt;br /&gt;
&lt;br /&gt;
Выбор начальной и конечной точек маршрута выполняется при помощи соответствующих кнопок возле полей ввода. Координаты выбранных точек будут отображены в полях ввода.&lt;br /&gt;
&lt;br /&gt;
Нажатие на кнопку «Рассчитать» запустит поиск кратчайшего маршрута с использованием критерия оптимизации, заданного выпадающим списком «Критерий». Кнопка «Экспорт» служит для экспорта построенного маршрута в новый векторный слой, а при помощи кнопки «Очистить» выполняется очистка полей с координатами начальной и конечной точек, а также из области карты удаляются сами точки и построенный маршрут. Краткую справку по работе с модулем можно получить нажав кнопку «Справка».&lt;br /&gt;
&lt;br /&gt;
==== Настройки модуля ====&lt;br /&gt;
&lt;br /&gt;
Перед использованием рекомендуется выполнить настроку модуля. Для этого вызовите диалог настройки из меню «Вектор — Road graph — Параметры модуля Road graph».&lt;br /&gt;
&lt;br /&gt;
[[Файл:roadgraph-03.png|thumb|Диалог настройки Road graph]]&lt;br /&gt;
&lt;br /&gt;
Здесь задаются предпочитаемые единицы измерения времени и расстояния, топологический порог и настраивается распознавание характера движения по дорогам. Если первые два параметра не требуют дополнительных пояснений, то остальные мы рассмотрим подробнее.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:RoadGraph_without_TT.png|thumb|Поиск пути с нулевой топологической толерантностью (в слой дорог введен искусственный артефакт)]]&lt;br /&gt;
[[Изображение:RoadGraph_with_TT.png|thumb|Поиск пути с ненулевой (0.00005) топологической толерантностью (в слой дорог введен искусственный артефакт)]]&lt;br /&gt;
При использовании слоя дорог, в котором присутствуют артефакты в виде небольших разрывов между вершинами полилиний, необходимо установить «топологический порог». Топологический порог (или топологическая толерантность) — это расстояние между двумя соседними вершинами, при котором они интерпретируются как одна и та же вершина графа. Эта величина должна быть как можно меньше (чем меньше — тем лучше). Не стоит полагаться на параметр топологической толерантности как на панацею, лучше если Ваши данные будут приведены к &amp;quot;правильному&amp;quot; виду.&lt;br /&gt;
&lt;br /&gt;
Модуль может правильно обрабатывать дороги с разным характером движения: одностроннее или двустороннее. Для этого необходимо, чтобы в атрибутивной таблице слоя присутствовало поле с указанием типа дороги. Его нужно выбрать в выпадающем списке «Поле направления» с настройках модуля и задать значения для прямого, обратного и двустроннего движения. Под прямым направлением понимается движение в порядке создания точек линии, от первой точки к последней. Соответственно, обратное направление это движение от последней точки линии к первой. Эти два варианта задают односторонние дороги.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим настройку на примере данных [http://gis-lab.info/projects/osm_shp.html OpenStreetMap]. В качестве поля направления выбираем &amp;quot;oneway&amp;quot;, тогда двусторонней дороге будет соответствовать значение &amp;quot;no&amp;quot;, прямому направлению односторонней дороги будет соответствовать значение &amp;quot;yes&amp;quot;, a обратному — какое-либо другое значение, например &amp;quot;123&amp;quot;. На вкладке «По умолчанию» для поля «Направление» выбираем «Двустороннее направление», чтобы дороги, не подпадающие под описанную выше схему трактовались как двусторонние. Все, теперь модуль будет различать дороги и строить маршруты с учетом характера движения по дорогам.&lt;br /&gt;
&lt;br /&gt;
Здесь же можно указать в каком поле находится информация о скорости движения по данному участку дороги. Если такое поле присутствует, то становится возможной оптимизация маршрута не только по рассточнию, но и по времени движения.&lt;br /&gt;
&lt;br /&gt;
На вкладке «По умолчанию» задаются значения параметров по умолчанию, которые будут использоваться, если модуль не сможет извлечь информацию из указанных полей или если эти поля отсутствуют.&lt;br /&gt;
&lt;br /&gt;
=== Библиотека QGIS network-analysis ===&lt;br /&gt;
&lt;br /&gt;
В настоящее время, в экспериментальных версиях QGIS базовый функционал плагина вынесен в отдельную библиотеку [[QGIS_network-analysis_library|network-analysis]], что делает возможным использование алгоритмов сетевого анализа реализованных в модуле из Консоли Python QGIS, а также в своих расширениях.&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Roadgraph2.png&amp;diff=698</id>
		<title>Файл:Roadgraph2.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Roadgraph2.png&amp;diff=698"/>
		<updated>2012-01-10T19:17:58Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: RoadGraph plugin в действии&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;RoadGraph plugin в действии&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:RoadGraph_with_TT.png&amp;diff=697</id>
		<title>Файл:RoadGraph with TT.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:RoadGraph_with_TT.png&amp;diff=697"/>
		<updated>2012-01-10T19:11:55Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: загружена новая версия «Файл:RoadGraph with TT.png»: приведение скриншотов к единому стилю&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Поиск пути с ненулевой (0.5) топологической толерантностью&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:RoadGraph_without_TT.png&amp;diff=696</id>
		<title>Файл:RoadGraph without TT.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:RoadGraph_without_TT.png&amp;diff=696"/>
		<updated>2012-01-10T19:10:44Z</updated>

		<summary type="html">&lt;p&gt;Stopa85: загружена новая версия «Файл:RoadGraph without TT.png»: приведение скриншотов к единому стилю&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Поиск пути с нулевой топологической толерантностью&lt;/div&gt;</summary>
		<author><name>Stopa85</name></author>
	</entry>
</feed>