НА ГЛАВНУЮ СТРАНИЦУ

МНОГОЗНАЧНЫЕ ЛИНИИ: МАРШРУТНОСТЬ И ТРЕХМЕРНОСТЬ

- Как всё устроено

- Как создать линию со значениями?

- Детали многозначности

- Инструментарий

- Ах, время, время! Tempo, tiempo...

Как всё устроено

Забавное свойство, эта маршрутность! Вроде выдумка простая, а развлекаться можно бесконечно - никогда не знаешь, где значения, разбросанные по линии, могут пригодиться. Случалось и корректировать километры трассы, и анимировать карту парусного путешествия, и привязывать вертолетную видеосъемку ландшафта с помощью этих Routes-конструкций. Стоит почитать отзывы в журналах: трассы ураганов... пролеты птиц... даже пути светил! Словом, полезная вещь, стоит с ней подружиться. Ну а трехмерные линии вряд ли нуждаются в рекламе :)

Если вы еще не встречались с PolylineM(Z), то вам стоит освоить азы: здесь рассказано простыми словами, что это. Зачем оно нужно, как использовать по делу маршрутные темы, как строить по такой теме события, начинающим предлагается прочесть тут. В этой же статье попробуем вместе порассуждать, как создавать линии со значениями, как их редактировать, как избежать проблем при работе с ними.

В чем суть маршрутной темы? Она очень проста: это та же полилиния, но только каждому узлу (вертексу) приписано некое значение, кроме координат. То же самое можно сказать и о трехмерной линии.

Знатоки спросят: "Что за значение, какого именно типа?". Десятичное число, точнее не скажу. В шейп-файле, наверно, оно одинарной точности, как и координаты в ArcView. Другие значения, естественно, не допускаются. "Да, но нужны ли другие типы? Целое число нелогично, логическое смешно, символьное - нонсенс..." Конечно, десятичное со всеми возможными знаками! Однако тип значения не так очевиден, как кажется - если порассуждать, то... очень полезным было бы например, время: оно часто в дороге куда более первично, чем километраж! Но его нет в ESRI- интерпретации. Не беда, голь на выдумки хитра - ниже будет рецепт, как имитировать время по маршруту.

Итак, значения расписаны для узлов, а что между ними? Между ними ничего. Полилиния ГИС, как известно, состоит из точек-узлов, между ними "пусто". Ничего не задано, ничего не описано. Значения "между" просто-напросто интерполируются в нужный момент.

"Как именно?" - поинтересуются знатоки. - не знаю, описано ли это где-нибудь изобретателями, но опыт подсказывает, что используется самый простой "линейный" способ. "А," скажут знатоки - догадываемся, к чему это приводит!" Правильно, к заметным неточностям. Точнее, к несоответствиям ожидаемому: там, где есть резкие изменения ряда значений, надо быть поосторожнее с выводами на основе маршрутных тем. Например, если темп движения урагана был 40 км/ч, а в одном из узлов стал вдруг 80, это не означает, что именно здесь эта громада резко ускорилась! Такое заключение даст заметную ошибку прогноза: логичнее будет ускорение распределить между предыдущей точкой и последующей, сглаживая расчет значений. Возможно, будущие ГИС будут учитывать и это, а пока всякие там сглаживания вам придется изобретать самим: значения в маршрутах рассчитываются именно линейно, безо всяких хитростей."

Как создать линию со значениями?

По сути мы имеем всего лишь механизм, реализующий кусочно-линейную зависимость. Зато эта машинка встроена в громадину ArcXxxx, и готова к работе. Подходит ли она к вашей задаче? Вам решать, а здесь займемся техническими подробностями. Имеется линия, например, трубопровода, как "вбить" значения километража в каждый ее узелок? "Нет ничего проще" - пишется обычно на нашем сайте, но здесь приходится признать крепость орешка. Дело не в том, что операций "нет в штате" - средств как раз предостаточно. Высшая математика? И она ни при чем, школьной арифметики вполне хватает. Однако несмотря на кажущуюся простоту, есть много тонкостей, да и логика дается с ходу не всем. Создать маршрутную тему в первый раз - замысловатая головоломка, и не стоит хвататься сразу за молоток, сначала давайте порассуждаем над гвоздями ;)

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

Идем дальше: как процедура поймет, в каком порядке точки соединять? Если вы уже создавали линии из точек, то ответ вы знаете - в ГИС предпочтителен порядок, заданный явно. Следовательно, должна быть еще одна колонка: порядковый номер точки. Другой не совсем "честный", но весьма практичный путь: сборка по физическому порядку: так работают многие простые скрипты сборки. Если у вас есть уверенность, что ваши точки были отрисованы одна за другой, то можете опираться и на этот принцип: вам решать.

"Почему нельзя собрать линию по геометрическому признаку?" - возмутятся знатоки. В общем случае, наверно, можно бы, рисовка линии часто очевидна. Есть и такие скрипты, которые пытаются сцепить точки, исходя из расчета расстояний между ними. Ведь это по сути анализ близости, соседства, и для ГИС такая задача по традиции решается отдельно и кропотливо, специальными средствами, часто интерактивным путем. ГИС-специалисты знают, что такие задачи разумно выделять в отдельные процедуры, и есть смысл избегать простых скриптов, которые обещают вам быстрое интуитивное "счастье". Тем более, что все они успешны лишь на малых объемах исходных данных. Задача соседства итеративная, и каждый раз, чтобы найти соседнюю точку, программа вынуждена будет "обегать" весь файл. Такие средства не входят в пакеты ESRI, и я тоже не буду их рекомендовать - отыщете и поразвлекаетесь сами.

Одним словом, при казалось бы "простой" сборке одной линии проблем хватает. В общем ГИС- случае, разумеется, линий может быть много. Как быть? Выручит еще одна колонка - номер линии, по ней проводится группировка точек. Тонкий момент: могут ли значения по линии не просто возрастать, как на первом рисунке, но и менять поведение, как показано здесь?

Разумеется, километраж по трассе таким быть не должен... Но кто постановил, что значения по маршруту отражают лишь километраж? Это мог бы быть диаметр трубы, ширина дорожного полотна, оценка загрязнения по профилю. Ясно, что для природного, да и технического параметра это нормальное поведение. Поддерживается ли оно ГИС- реализацией? И да, и нет. Сама по себе линия может содержать любые наборы значений. Несложно в любой узелок вписать любое значение - и ваша маршрутная линия будет "переменная". Штатные средства ArcView, например, не конфликтуют с таким подходом: разброс событий по такой линии просто построит для значения 6.8 два "события", окаймляющих максимальную семерку, две виртуальные точки, а не одну.

Однако другие ГИС-средства относятся к переменным маршрутам весьма сердито: ESRI изначально ввели маршрутные линии именно для отображения километража. Множество штатных инструментов по сборке и редактированию линий опираются на дистанцию по линии, зависят от рисовки линии, помогают отслеживать однообразие поведения значений. Например, в ArcMap типовая раскраска линий в явном виде объявляет участки, где значение не растет вдоль по линии, а понижается - аномалиями. Штатный инструмент калибровки линий (Calibrate) откровенно глючит, если такие аномалии есть. Словом, в целом средства ESRI упрямо поддерживают метафору километража, и применять маршрутные линий для хранения переменных значений вы можете, но на свой страх и риск.

Сторонние инструменты по построению, анализу, расчету могут также давать сбои - все зависит от того, чего они ждут, на какие значения рассчитывают. Во избежание таких проблем можно предназначить PolylineM - для нарастающих значений, PolylineZ - для всех остальных видов, как оно и было задумано.

Хорошо, если значения нужно рассчитывать только вдоль линии, а если они разбросаны в некоей полосе? Как их свести, аппроксимировать в линию? Вроде бы алгоритм сборки значений очевиден: строится ближайший поперечник, точка "притягивается" к линии и дело в шляпе, но... что будет на концах линий? Совсем не ясно, как их рассчитывать, если набор точек ограничен. Что ставить по краям, нули-пропуски значений? То же что и в ближних узлах? Интерполировать линейно от середины? Вопрос... В ответственных случаях, наверно, лучше задавать краевые значения вручную, не пуская дело на самотек, чтобы хоть как-то взять поведение концов линии под контроль.

Возможны конфликты и "по течению" линий: на рисунке показаны два варианта построения. Из них вариант а) правильный по логике значений б) "ближайший", то есть правильный геометрически. Вручную все такие моменты не отследишь, но порой оператору просто необходимо вмешиваться. Ведь перпендикуляр это всего лишь упрощение реального отношения близости точки к линии. Для поперечного разреза, например, значение из точки на линию профиля проецируется всегда перпендикулярно, а для тальвега на природном рельефе это вовсе не правило. Словом, процесс построения тоже, получается, должен быть интерактивным. Как избежать ручного труда? Совет может быть такой: по возможности, делайте линии "с нуля", по всему множеству точек заново... И тщательно отбирайте точки-узлы. Отбрасывайте слишком близкие, например, подобные 4.8 и 5.0 на рисунке - они по сути ведь скрытые дубликаты. Как бороться с геометрическими дубликатами, кстати, вопрос немаловажный в контексте сборки элементов. Об этом есть отдельные разговоры в разделе "Топология".

Детали многозначности

Чем отличаются PolylineM От PolylineZ? Если вы внимательно следили за логикой изложения, то уже поняли, что они очень cхожи. Просто в файлах M одна ячейка на каждый узел, для хранения М-значений, а файлы Z содержат еще одну - для "любых" Z значений. На схемах объектов можно увидеть, что PolylineZ являются потомками PolylineM, а значит, наследуют их свойства, дополняя их. Нигде не документировано, но несложно убедиться, что PolylineZ могут быть использованы и как обычные маршрутные файлы тоже. Забавно иметь файл по трассе с километражом, содержащий также и значение высоты местности, например. Как сделать такой? Забавная задачка "на дом" для любознательных, а мы не будем на ней останавливаться.

Как редактировать отдельные значения - М или Z - вручную? Поскольку схема хранения значений проста, вписать M/Z, по идее, не должно быть сложно. Если ячейка есть, то надо получить к ней доступ, и дальше останется вбить значение вручную. Причем, скорее всего, средства для M и Z будут рядом - принципы-то одинаковые, и любому программисту большой соблазн сочинить всё "заодно". Можно пробовать применять одни и те же инструменты или методы, даже если это не документировано... В общем, пора к делу и перейти.

Инструментарий

Штатные средства ArcView 3.x, как кажется с первого взгляда, не позволяют создавать и редактировать шейп-файлы со значениями. Изощрённый EdiTools? Ну разумеется! Однако для данной задачи Yanko Chukanski предлагает как раз не самый изощрённый, а довольно простой инструмент. Он может сделать только сборку готовых узлов, одной командой - Convert Points -> PolylineM(Z), по выбору, M или Z. Собрать точки с полосы в нем не получится, он построит линию по заданным точкам-узлам.

Есть еще удобные скрипты сборки, например, в коллекции Алексея Петринчука. Скрипт pz2lz.ave строит трехмерные линии из точек. Требует указать колонку-источник высот, и номер (идентификатор) линии. Порядок точек в линии указать не просит, так как пользуется физическим порядком шейп-файла. В финале выдает PolylineZ.... А как же M-значения? Скрипт простой, всего несколько строк, и я позволил себе забавный эксперимент - заменил в нём все вхождения буквы "Z" на "M" (включая название самого файла). И что же? Скрипт pm2lm.ave чудесным образом работает, и порождает PolylineM. Это подтверждает лаконичность произведений Алексея, и иллюстрирует сказанное выше: методы работы со значениями M и Z аналогичны до предела.

Как "собрать" значения с широкой полосы вдоль линии? Попробуем упростить постановку задачи: как передать нужные значения узлам линии от других, соседних точек? Кажется, в ГИС встроен такой механизм... Правильно, это Spatial Join. Он еще менее точен, чем перпендикулярный способ, и с ним надо быть осторожнее, критически подходить к отбору соединяемых точек. Но и перпендикулярный подход поможет наладить умелая рука программиста: например, можно взять другой скрипт Алексея: add_vertex.ave проецирует точки с заданной окрестности на линию, создавая дополнительные узлы. Притягивая точки он использует стандартную процедуру UserSnapPoint, связи с чем работает быстро и без осечек.

Как же редактировать значения линий в ArcView? Начинающие постоянно спотыкаются об эти шейп-файлы - они не открываются на редактирование. Пробуем подумать... 3D файлы ведь были изобретены для модуля 3D Analyst, подключаем его и... дело в шляпе! Тема оживает. В свойствах шейпа можно добраться и до значения в узелках. Что забавно, одновременно "открываются" и маршрутные темы, которые ни по какой документации не имеют отношения к 3D - Очевидно, работает упомянутый принцип "заодно". Точкам можно задавать любое значение, никак не связанное с остальными, и даже обнулять. Можно двигать линию, но нельзя менять её форму, оттягивая отдельные узлы. Это кажется странным, но если вдуматься, вполне логичное запрещение.

Как быть в ArcMap? Сборку многозначных линий и тут наладил Янко Чукански - его старый добрый EdiTools, как известно, функционирует и в ArcMap под именем GeoWizards. Другие операции с M-линиями доступны через мощный набор аркинфо/аркэдитор: создание линий с нуля, подправка расстояний, калибровка по удаленным точкам, пересчет расстояний... Эти функции доступны через панель "Route Editing" или раздел "Linear Referencing" в ToolBox. Однако, как можно догадаться уже по названиям, эти инструменты работают лишь для маршрутов: изначально они и были задуманы для километража, еще во времена ArcINFO, когда о трехмерности никто в ГИС и не помышлял. Тестирование показывает, что воспользоваться наиболее мощным и нужным инструментом калибровки для переменных значений нельзя: обработка ситуации, представленной на третьем рисунке, выдает что-то бредовое. Калибровка ArcMap явно заточена под нарастающие значения.

К чести ArcMap можно сказать, что маршруты зато встроены плотно в ядро пакета. В свойствах слоя появляется соответствующая закладка "Routes", дающая дополнительные удобства. 3D Analyst теперь не нужен для правки вертексов: включив редактирование, можно вписывать значения в любой узел, двигать линию и даже отдельные узлы. Вряд ли стоит увлекаться этим: даже простой километраж несколькими вольными взмахами мыши будет испорчен.

А как же развитый путь создания Z-линий, из разбросанных точек, с интерполяцией и все такое? Этот подход пока не развит в ArcMap. По крайней мере, штатный набор ничего не предлагает на этот счёт, а из независмимых скриптов комплект, аналогичный описанному выше арквьюшному, составить пока не удается. Каждый трехмерщик выкручивается, как может - кто рисует вручную по точкам, кто арквьюшничает исподтишка, кто интерполирует свои полилинии в программах СAD и DTM, кто угрюмо точит свой уникальный инструмент :) Время покажет, что нибудь-придумается.

"Ах, время, время! Tempo, tiempo..."

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

Итак, задача стояла вполне гисовская - "раскатать" видеоряды, отснятые с вертолета, по карте местности. Не для забавы, разумеется, а с тем, чтобы эксперт-составитель карты мог в любой момент перемотать пленку и увидеть ландшафт в том или ином четко определенном месте. Что для этого нужно? Заложить в линию время. Дальше можно распечатать метки времени по муршруту полета через подходящие равные промежутки и положить рядом с телевизором, можно работать с электронной картой. Треки полета и реперные точки видеопоследовательностей имелись. Надо признать, что если бы рекогносцировщики догадались синхронизировать время на видеокамере с прибором GPS, задача была бы намного легче. Однако полевикам так трудно порой внушить тонкости регистрации событий... Так или иначе, треки до ГИС дошли уже как простые шейп-файлы (голубые линии на схеме). Динамика движения вертолета была неизвестна. В довершение бед в фильме время было проставлено не на всех клипах (батарейка села). Зато дотошные исследователи представили ручной хронометраж всех реперных моментов видеосъемки, тщательно привязав их к местности по надежным ориентирам.

Сначала были расставлены реперные "видео-точки" с известным положением по маршруту - на схеме они показаны малиновыми звездочками. Затем трасса полета была разбита по узлам, и все точки сведены в единую таблицу. Для построения маршрутного шейп - файла время было пересчитано в десятичные минуты от начала полета. Полная таблица точек, таким образом, содержала колонку "время" в числовом формате: правда, для реперных узлов это время было зафиксировано, а для остальных строк в колонке стояли пробелы. Поскольку инструменты не позволяют строить маршрутную тему по такой полупустой таблице, то нужен интерполирующий инструмент. В ArcMap есть штатные процедуры цельно-линейной интерполяции - Calibrate Route, в ArcView был использован самодельный скрипт. Так или иначе полет был восстановлен как маршрутная тема с нарастающим значением минут - точность вполне приемлемая. Затем, для удобства пользования по маршрутной теме расставили целоминутный хронометраж, надписали время в привычном формате часы-минуты (желтые цифры на схеме) и распечатали эту схему для экспертов-составителей карт на фоне космоснимка. Прокручивая виртуальный пролет, эксперты получили возможность в любой момент довольно точно знать, где "находятся". Проще говоря, с помощью маршрутных механизмов видео- последовательности были "натянуты" на линии как резиновые, надёжно геореференсированы путем "пришпиливания" к реперным точкам.

Разумеется, рассчитанное время не отражало идеально темп движения вертолета, но позволило привязать ленту к местности с достаточной точностью. Эта привязка помогла расставить по трассе и фотографии через маршрутную тему, как события - Events. Всё это позволило быстро создать предполевые заготовки карт, не вывозя на место весь дорогостоящий коллектив экспертов.

Словом, маршрутные линии - удобная конструкция! Спасибо ESRI и всем кто дочитал до конца. Уф-ф... Как же трехмерные линии, подробности их составления и применения? Пожалуй, в следующий раз :)

Geologic