Когда коту делать нечего, он яйца лижет; когда у меня нет срочных дел, я программирую и делаю что-нибудь в сфере своих интересов.
Одной из таких сфер является картография.
Впервые я сделал карту в период работы в ЦПКиО им. М. Горького, потому что работать по большим чертежам неудобно, и хорошо бы иногда делать собственные фрагменты той или иной местности.
Изначально я, конечно, не знал о разных системах координат и переходах из одной в другую, МГГТ и прочих, но постепенно втянулся. Со временем карты пришлось переделать из геоцентрической в нормальную декартову местную систему координат.
О всяких примитивных вещах, типа выдёргивания из кадастрового плана территории квартала координат объектов по регулярным выражениям 🤦, я рассказывать пока не хочу. А вот на другом месте работы я построил карту электросетевых связей объектов на основании табличек отдела электрохозяйства.
На самом деле всё довольно просто.
Для начала заносим в базу нужные нам объекты недвижимости с их геометрией и структурированным адресом, и выгружаем координаты в формате 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 рисовать дуги при генерации геометрии, потому что прямые линии не вполне удобны.
В итоге это может выглядеть так:

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