QGIS
Когда коту делать нечего, он яйца лижет; когда у меня нет срочных дел, я программирую и делаю что-нибудь в сфере своих интересов.
Одной из таких сфер является картография.
Впервые я сделал карту в период работы в ЦПКиО им. М. Горького, потому что работать по большим чертежам неудобно, и хорошо бы иногда делать собственные фрагменты той или иной местности.
Изначально я, конечно, не знал о разных системах координат и переходах из одной в другую, МГГТ и прочих, но постепенно втянулся. Со временем карты пришлось переделать из геоцентрической в нормальную декартову местную систему координат.
О всяких примитивных вещах, типа выдёргивания из кадастрового плана территории квартала координат объектов по регулярным выражениям 🤦, я рассказывать пока не хочу. А вот на другом месте работы я построил карту электросетевых связей объектов на основании табличек отдела электрохозяйства.
На самом деле всё довольно просто.
Для начала заносим в базу нужные нам объекты недвижимости с их геометрией и структурированным адресом, и выгружаем координаты в формате WKT в CSV вместе с адресами. Так проще потому, что база данных объектов у меня была на Drupal & Openlayers, то есть на PHP+MySQL, а QGIS (как и любой другой известный мне картографический софт) подключаться к MySQL и извлекать пространственные данные не умеет. В Drupal такая выгрузка настраивается довольно просто, и CSV скачивается на компьютер просто при обращении по определенному адресу.
На выходе получается приблизительно такой файл формата CSV (разделенный табулятором).
Address | Korpus | KadNum | KadArea | WKT |
---|---|---|---|---|
░░.░░░░░░░ ░.░░ стр.16 | 3 | ░░:░░:░░░░░░░:1081 | 3771,30 | POLYGON (…) |
░░.░░░░░░░ ░.░░ стр.17 | 6 | ░░:░░:░░░░░░░:1082 | 1723,60 | POLYGON (…) |
░░.░░░░░░░ ░.░░ стр.18 | 112а | ░░:░░:░░░░░░░:1033 | 7881,20 | POLYGON (…) |
░░.░░░░░░░ ░.░░ стр.19 | 118 | ░░:░░:░░░░░░░:1034 | 5304,20 | POLYGON (…) |
░░.░░░░░░░ ░.░░ стр.2 | 112 | ░░:░░:░░░░░░░:1067 | 9909,80 | POLYGON (…) |
░░.░░░░░░░ ░.░░ стр.20 | 26Б | ░░:░░:░░░░░░░:1041 | 349,90 | POLYGON (…) |
░░.░░░░░░░ ░.░░ стр.21 | 118А | ░░:░░:░░░░░░░:1040 | 7947,60 | POLYGON (…) |


При загрузке такого CSV в качестве слоя в QGIS мы получаем контуры зданий (из поля WKT в CSV) и связанные с ними адреса.

Таблички от отдела электрохозяйства с перечнями подстанций выглядели приблизительно так:
N | TPName | Address | Inventory |
---|---|---|---|
5 | ТП-7 (РП 5409) 6 кВ и ТП-7А (РП 5419) 6 кВ | ░░.░░░░░░░ ░.░░ стр.26 | 20123 |
6 | ТП-8 (РП 5424) 6 кВ | ░░.░░░░░░░ ░.░░ стр.58 | 20136 |
7 | ТП-9 (РП 5410) 6 кВ | ░░.░░░░░░░ ░.░░ стр.14 | 20103 |
8 | ТП-11 6 кВ | ░░.░░░░░░░ ░.░░ стр.62 | 20143 |
Тут, очевидно, необходимо дорабатывать текст до придания ему единообразия (в данном примере адреса мною уже приведены к единообразному формату); к примеру, РП-* вынести в отдельную колонку. Но главное тут есть — привязка адреса здания к подстанции. Формат адреса в этой таблице должен строго соответствовать адресу здания из списка с координатами. Я доработал его следующим образом:
N | TPName | Address | Inventory |
---|---|---|---|
5 | ТП-7 | ░░.░░░░░░░ ░.░░ стр.26 | 20123 |
6 | ТП-8 | ░░.░░░░░░░ ░.░░ стр.58 | 20136 |
7 | ТП-9 | ░░.░░░░░░░ ░.░░ стр.14 | 20103 |
8 | ТП-11 | ░░.░░░░░░░ ░.░░ стр.62 | 20143 |
Конечно, в зависимости от потребностей записи «6кВ» и «10кВ», к примеру, можно было бы вынести в отдельную колонку и отображать их на карте, но для примера мы список предельно упростим.
Загружаем его аналогичным образом, однако выбираем отсутствие геометрии, поскольку её в этой таблице просто нет. Картинка ниже сделана до того, как я внёс существенные правки выше, это нужно иметь в виду.

Теперь создадим виртуальный слой.

Этот слой является результатом SQL-запроса к уже загруженным нами таблицам. Источники данных для запроса загружаются кнопкой «Импорт» из уже загруженных слоёв, и им крайне желательно дать короткие имена, потому что именно по ним к этим таблицам будем обращаться.



Запрос:
select Centroid(obj.geometry), obj.Address, tps.Name from obj, tps where obj.Address == tps.Address
Из таблиц obj и tps в новую таблицу мы выбираем поля адреса, имени подстанции и геометрического центра объекта, для которого адрес в таблице зданий совпадает с таблицей трансформаторных подстанций.

Что важно — при редактировании виртуального слоя он каждый раз при нажатии кнопки «Добавить» создаётся заново, и если есть проблемы с системами координат, точки центроидов в видимом поле могут не появиться, и нужно выходить из диалога редактирования виртуального слоя и задавать нужную систему координат вручную. В моём наборе данных использовалась EPSG:4326, та же система будет использоваться и в производных слоях. Чтобы отображать объекты в плоскости, нужно использовать декартову систему координат (МГГТ или любую МСК), или EPSG:3857.
Для созданного виртуального слоя можно и нужно создать подписи, которые будут обозначать подстанции.
Теперь построение связей.
Для начала нужно загрузить CSV «Кабельный журнал высокого напряжения» с атрибутами, который в самом простейшем варианте состоит из двух колонок: пары вида подстанция¹ — подстанция², то есть какая подстанция с какой соединена. Имена подстанций должны соответствовать тем, что указаны в перечне подстанций, иначе их невозможно будет сопоставить.

SELECT SRC, TRGT, make_line(Centroid(objFrom.geometry), centroid(objTo.geometry)) FROM hvolt JOIN tps tpsFrom ON hvolt.SRC == tpsFrom.Name JOIN tps tpsTo ON hvolt.TRGT == tpsTo.Name JOIN obj objFrom ON tpsFrom.Address == objFrom.Address JOIN obj objTo ON tpsTo.Address == objTo.Address
В виртуальный слой попадает три колонки: колонки SRC и TRGT из таблицы «Кабельный журнал высокого напряжения», которую для удобства переименовали в hvolt, а в поле геометрии создаваемого объекта попадает результат работы функции, создающей из двух точек линию. Точки выбираются отдельными запросами (tpsFrom + objFrom для исходной точки, tpsTp + objTo для целевой).
Опционально можно создать подписи к генерируемым линиям, например указав concat('← ',TRGT) в поле подписи (Label), тогда рядом с линией будет показываться направление и цель. Конечно, вместо линии можно отрисовывать стрелку.
Я пока не понимаю, возможно ли в QGis рисовать дуги при генерации геометрии, потому что прямые линии не вполне удобны.
В итоге это может выглядеть так:

Дополнительные слои (например, карта линий низкого напряжения) добавляются аналогично.