Hatred's Log Place

DON'T PANIC!

Mar 15, 2016 - 3 minute read - programming c++

std::cout, std::cerr и std::clog

Сначала немного информации из мира С.

При запуске приложения (речь идёт о POSIX) вместе с ним открывается 3 файловых дескритоптора:

  • 0 - ассоциирован со стандартным вводом (stdin)
  • 1 - ассоциирован со стандартным выводом (stdout)
  • 2 - ассоциирован со стандартным выводом в поток ошибок (stderr)

В стандартной библиотеки Си используется FILE*-based буфферизируемый доступ к файлам и терминалу. В stdio.h объявлены следующие глобальные символы, которые отражают стандартные потоки ввода вывода:

  • stdin
  • stdout
  • stderr

Соответственно их свободно можно использовать вместе с семейством функций fread()/fprintf(), обеспечивая буфферизированный доступ.

Сами файловые дескрипторы POSIX объявляет через макросы в unistd.h:

  • STDIN_FILENO
  • STDOUT_FILENO
  • STDERR_FILENO

Соответственно их свободно можно использовать со всем семейством функций read(), write() и, даже, select()/epoll() и fcntl() (например, при помощи fcntl(O_NONBLOCK)+select+read можно реализовать аналог [getch()](http://www.codenet.ru/progr/cpp/spr/175.php) из старого доброго Borland C++). Доступ через эти функции не буфферизирован.

Доступ к одному потоку разными механизмами в одной программе лучше не осуществлять: буферизация это уровень библиотеки C и внутреннего устройства FILE. write() или read() ближе к системным вызовам и ничего про это знать не обязаны. Как результат можете получить перемешивание текста даже в однопоточном приложении. Это не отменяет того файла, что сам fwrite() может, в конце концов, вызвать write().

На этом экскурс закончим и вернёмся в C++.

В C++ для работы с потоками служит библиотека [iostream](http://www.cplusplus.com/reference/istream/iostream/). Причём доступ к конкретному стриму может быть как буфферизируемым так и не буфферизируемым (зависит от потребностей).

Библиотека декларирует объекты, связанные со стандартными потоками:

  • std::cin - стандартный ввод
  • std::cout - стандартный вывод
  • std::cerr - стандартный вывод ошибок и
  • std::clog - для логирования

Про std::cin особо гооврить (пока?) не будем - он один, в своём роде. А вот про оставшиеся три стоит.

Итак, начнём с std::cout и std::cerr. В C++ они, помимо того, что связаны с разными дескрипторами, несколько отличаются поведением:

  • std::cout - буферизируемый
  • std::cerr - не буферизируемый

Такое отличие явственно следует из семантики использования: ошибку нужно увидеть сразу без ожидания каких-то дополнительных действий со стороны программиста типа std::flush или std::endl (он, кстати, делает и flush, поэтому, для большей производительности строки в нормальном выводе стоит заканчивать ‘
n’, а не std::endl).

Ок, а что за std::clog? А это всего-лишь std::cerr + буферизация. И снова, семантика использования проста: диагностика может чуть и подождать, что бы не понижать производительность вывода, но смешиваться с нормальным выводом не есть хорошо, мы, ведь, можем использовать приложения в пайпе и, желательно, разделить диагностику и ошибки от обычного вывода.

Собственно, немного обобщая:

  • std::cout - используется для обычного вывода результатов работы программы на экран, эти данные могут быть переданы дальше по пайпу для обработки.
  • std::cerr - вывод сообщений об ошибке в обработке, что бы не подмешивались в основной поток и не ломали логику работы других программ в пайпе. При этом сообщение выводим максимально скоро.
  • std::clog - используем для разного рода диагностических сообщений, но когда использование std::cerr замедляет вывод из-за более частого дёргания системных вызовов, при этом, не подмешиваемся в основной поток и не мешаем работе других приложений в пайплайне.

Хорошим тоном, так же, является вывод справки по программе в std::cout, если вызвано с параметрами -h|--help - тогда её удобно смотреть в, например, less без дополнительных телодвижений, а вот справку по опциям, в случае неправильной установки какого-то параметра (или пропуска обязательного), лучше выводить (тут особой разницы не вижу) в std::cerr или std::clog.

И, на последок, лекция по поводу тормозов iostream и вообще, а как оно там внутри устроено:

Mar 5, 2016 - 3 minute read - programming c++

Source Specific Multicast и Asio

Недавно на ru.SO проскочил вопрос: как можно подключиться к SSM ( Source Specific Multicast) группе?

Нюанс в том, что для этого используется опция MCAST_JOIN_SOURCE_GROUP для которой нет объекта-обёртки. Но, как оказалось, такой объект пишется самостоятельно на раз-два. Под катом я продублирую свой ответ, как пример подхода реализации нужного функционала. Пример не самый идеологически правильный, но, как оказалось, рабочий. Автор сам предложил свой вариант с захватом сырого хендла. Такой подход тоже имеет смысл в некоторых ситуациях((у меня случилось однажды так подружить сетевые абстракции Asio и libev, реализовав, тем самым, реактор на Asio :simple_smile:)).

Mar 5, 2016 - 6 minute read - туризм

С юга на север по Ливадийскому хребту

23 февраля решили отпраздновать очередным снегоступингом.

По предложению Кирилла рассматривали варианты посещения южных отрогов Ливадийского хребта.

Маршрут изначально рассматривался как:

Фокино-г.Халаза-г.Горбуша-г.Лысый дед-Молёный мыс

но в результате был скорректирован до:

Душкино-падь Светланка-г.Круглая-г.Пидан-Лукьяновка.

Собралось три человека: я, Кирилл, Саня. В роли адового тропильщика в этот раз Кирилл.

Feb 17, 2016 - 3 minute read - туризм maps

GeoCrop и популярные привязки

Если у вас на входе привязанный GeoTIFF, то проблем нет никаких, но если у вас просто растр (.png, .jpeg, .gif) и привязка для него, то есть нюансы. Вообще, GeoCrop умеет работать с любыми данными, с которыми умеет общаться GDAL. Но в в некоторых случаях не всё получается гладко, так, например, только сегодня он научился читать файл проекции для world-привязок (пара .prj+.pgw).

На просторах интернета можно встретить различные описания привязок, самые популярные:

Ozi Explorer

GDAL не умеет только шифрованные OZFX, а так привязанная карта представляет собой пару .map+растр, где растр - это, обычно, .gif, .jpg или .png, реже - .bmp. При наличии такой привязки geocrop можно вызвать без дополнительных приготовлений: geocrop -f VRT -s 50k K-53-026-A.map K-53-026-A.vrt

Обратите внимание, что передаётся map файл, а не растр.

World files

Т.к. сама привязка состоит из двух файлов (.prj+.pgw), то не так просто сказать, что и откуда читать. Согласно документации .pgw, .pngw или .wld файл((Описание формата: http://www.gdal.org/frmt_various.html#WLD)) подтягивается автоматически, если на входе карта в PNG (про другие форматы - ниже), а вот .prj файл нужно читать самому. Для этого в последней версии GeoCrop сделана небольшая эвристика:

  • Если растр содержит пустую проекцию, то производится попытка прочитать проекцию (формат WKT или PROJ.4) из файла с таким же именем, но расширением .prj и .prf.
  • Либо файл проекции можно жестко задать при помощи новой опции -p srs_def

Т.е. при наличии привязки в виде world files GeoCrop так же можно вызвать без дополнительных приготовлений так: geocrop -f VRT -s 50k K-53-026-A.png K-53-026-A.vrt если файл проекции находится в K-53-026-A.prj или K-53-026-A.prf, или так: geocrop -f VRT -s 50k -p K-53-026-A.wkt K-53-026-A.png K-53-026-A.vrt

Обратите внимание, что в обоих случаях в качестве входного источника передаётся сам растр, а не его привязка.

Если у вас растры отличные от PNG:

  • BMP - привязка ищется в .bpw, .bmpw или .wld.
  • GIF - привязка ищется в .gfw, .gifw или .wld.
  • TIFF - если это GeoTIFF со встроенной привязкой, то она и используется, если это просто растр, то привязка ищется в .tfw, .tifw/.tiffw или .wld, а так же в MapInfo .tab файле.
  • JPEG - привязка ищется в .jgw, .jpgw/.jpegw или .wld, а так же MapInfo .tab файле.

Полный и актуальный список всегда можно посмотреть тут: http://www.gdal.org/formats_list.html

Global Mapper

В данный момент GDAL не поддерживает данный формат, а значит не поддерживает и GeoCrop. Ищите способ как сконвертировать его во что-то удобочитаемое.

Вообще .gmw файлы достаточно простые для разбора, так что, возможно, появится у меня и их поддержка. Тем более, что для тех же карт GGC там сразу зашита информация об обрезке (только странно, что они сразу не сделали рамку прозрачной).

Feb 17, 2016 - 2 minute read - туризм maps programming

Новый режим в GeoCrop

Теперь в GeoCrop появился новый режим: генерация полигона для обрезки рамки в формате CSV+WKT. Вывод на stdout, так что можно сохранить в любой удобный файл из скрипта, после чего использовать как аргумент для -cutline у gdalwarp в какой-то более сложной команде. Вызова gdalwarp при этом не происходит.

Активируется режим опцией -g (от [g]enerate). Указывать выходной файл при этом не нужно - он будет проигнорирован.

Так же, теперь появилась возможность указывать файл с описанием проекции: -p srs_file. Сама проекция должна быть в формате WKT или PROJ.4. Эта опция перезаписывает определение проекции в текущем файле. Полезна для преобразования файлов с привязками в виде world-файлов. Более того, если проекция в файле пустая, а опция не указана то произведётся попытка прочитать её автоматически из файла с таким же именем, но с расширением .prj или .prf (какой первый попадётся). Так что популярные карты ГГЦ с такими привязками теперь можно конвертировать так же просто, как и с привязками Ozi Explorer.

Чуть раньше реализована функциональность по передаче дополнительных параметров gdalwarp. Для этого нужно завершить опции приложения двойным минусом --, опции после него будут переданы gdalwarp как есть без изменений: geocrop -f VRT -s 200k K-53-07.map K-53-07.vrt – -overwrite опция -overwrite будет передана gdalwarp. Помимо этого, теперь можно переопределить и сам исполняемый файл gdalwarp - опция -w GDALWARP.

Кроме того изменился формат опций, стало возможным указывать выходной формат (опция -f FMT, как следствие, образовались такие возможности: post/2016/02/11/bystro_i_nenavjazchivo_gotovim_kartu_dlja_otkrytija_v_qmapshack) или только обрезать рамку, не делая кроп (опция -n).

Feb 11, 2016 - 3 minute read - туризм maps

QMapShack

Внезапно QMapShack стал юзабельным!

Но немного истории. QMapShack это революционное развитие QLandkarteGT от того же автора. Просто архитектурно QLandkarteGT перестал соответствовать требованиям.

Итак, как минимум следующие фичи теперь доступны в QMS (принятая аббревиатура для QMapShack в расслылке)(((!) отмечены фичи уникальные, по сравнению с QLGT, а (-), то, что убрано, (?) - спорные изменения)):

  • Открытие серии файлов с геоданными, переданных, как аргументы приложения. Это не относится с картам (?) - они берутся только из директорий, которые вы настроили в программе (аналогично произвольная карта не может быть открыта через File -> Open Map, такого пункта просто нет).
  • Поддерживаются ВСЕ форматы карт, которые поддерживаются GDAL (!). Но делается это не напрямую, а через формирование .vrt файла. Сей унифицированный способ отменил отдельное открытие GeoTIFF - теперь нужно и для него формировать vrt-файл. К счастью теперь это делается через внутренний инструмент vrtbuilder и позволяет в большинстве случаев обойтись без утомительной конвертации в GeoTIFF, например привязок OziExplorer((В случае привязок Ozi, нужно открывать .map файл, в случае привязок .pgw+.prj открывать нужно одноимённую картинку))((К сожалению, на карты и привязки с http://loadmap.net он упорно ругается)). Вообще список теперь достаточно вменяемый:
    • Векторые карты:
      • .img - веркторные карты Garmin в non-NT формате. NT-формат не поддерживается и поддерживаться не планируется.
    • Растровые карты:
      • .vrt - враппер для всех типов GDAL.
      • .jnx - Garmin Birds Eye.
      • .rmap - CompeGPS Map Container
    • Онлайн карты:
      • .wmts - WMTSCapabilities.xml с любого картографического сервера, переименованный в уникальное имя. Дальше есть подробности.
      • .tms - описание правил использования TMS серверов. Через такие файлы можно подключить всякие OpenStreetMap, OpenCycleMap и так далее. Встроенный мастер позволит сгенерировать такие файлы для некоторых популярных сервисов.
    • DEM рельеф:
      • .vrt - как и прочие растровые карты
  • (!) Более развитые средства управления геоданными. Каждый файл GPX воспринимается как отдельный контейнер-проект. Данные между ними можно копировать. Теперь можно объединить несколько треков в один (!).
  • (!) Больше информации по трекам: можно задать тип активности, можно посмотреть графики высоты от расстояния, скорости от расстояния, или прогресса пути от времени.
  • (!) Более развитые средства редактирования треков. Правда точки так и не удаляются, но можно скрыть их, спрямив, например, трек (убрав топтание на месте, при остановке на обед или заделку колеса на велосипеде).
  • (?) Более активное использование мыши в окне отображения карты. В контекстном меню находится большинство полезных пунктов, типа создания путевой точки или трека. Да и вообще больше динамики в интерфейсе, точнее в области карты.
  • (!!!) Выделение, печать или сохранение произвольной области карты. Костыльное решение я делал для QLGT, но его не приняли. Там можно было распечатать только видимую часть карты.

А вот теперь каких инструментов не хватает в QMS, но есть в QLGT:

  1. Инструмент привязки карты по точкам (в визуальной форме). Не знаю, будет ли сделан, но таск завёл.
  2. Экспорт выделенного куска карты в JNX. Потребность сомнительная, но пару раз пригождалась.

Ну и ссылки:

Feb 11, 2016 - 2 minute read - туризм maps

Быстро и ненавязчиво готовим карту для открытия в QMapShack

Для примера будет рассмотрен сервис http://loadmap.net, который предоставляет карты с привязками в формате OziExplorer.

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

Теперь про самый смак: QMS умеет открывать .vrt файлы. VRT файл это XML документ, с описанием привязки и различных преобразований, понятные движку GDAL. Так вот, в ходе беглого исследования оказалось, что мой способ резки рамки применим к VRT файлам: данное преобразование просто сохраняется внутри и применяется при открытии! Если добавить сюда тот факт, что переконвертации самого растра не происходит и просто формируется дополнительный маленький XML файл, то счастье становится полным.

Рассматривать вопрос сборки программы я подробно не буду, скажу только, что нужны dev пакеты для libgdal и libproj4. Устанавливать программу не нужно - просто скопируйте в удобное место, у меня это ~/bin. Сборка и работа на Windows не проверялась.

Вот, преамбула завершилась… Основная часть будет короче :)

  1. Скачиваем растровый файл карты, допустим это 500-метровка K-53-027-A, тогда файл будет K-53-027-A.png

  2. Скачиваем файл привязки K-53-027-A.map

  3. Обрезаем рамку и формируем VRT:

    ~/bin/geocrop -s 50k -f VRT K-53-027-A.map K-53-027-A.vrt
    

    Обратите внимание на параметр -s - он задаёт масштаб листа в виде делителя, т.е. опущена 1:, а буква обозначает степень десятки на которое нужно домножить: 50k (кило) = 50 * 10^3 = 50000 и масштаб тогда 1:50000, т.е. пятисотметровка.

Feb 11, 2016 - 6 minute read - туризм

Читинза под снегом 2

//Их было четверо…
Они шли, шли, шли и, наконец, пришли!//

Наконец-то первый полноценный снегоступный ПВД за сезон. То несросты, то переносы, но всё-таки собрались: Я, Коля, Кирилл и Гена.

А вообще, пробую завести ещё одну традицию: снегоступинг на Читинзу во второй половине января или начале февраля. В прошлом году была первая серия.

Как обычно, выехали на первой электричке в субботу, домой возвращались на крайней в воскресенье.

Маршрут изначально намечали:

Партизан (пл.98 км) - руч.Просечный - С-В хребет - вершина 1156 м - трверс на Читинзу - Читинза - С-З хребет - р.Постышевка - Наречное.

Но в электричке скорректировали его до:

Красноармейский - Ручьи - С-С-В хребет (классика) - Читинза - траверс на Смольную - Смольная - С-В хребет - вершина 734 м - руч.Прав.Лесопильный - Тигровой

Небольшая сводка:

День Протопали,
км
Набор высоты,
м
Сброс высоты,
м
Время в движении,
ч
Средняя скорость,
км/ч
Начало движения,
ч
Конец движения,
ч
16.9 1434 554 06:25 2.0 10:00 18:34
Вс 14.2 201 1091 04:33 3.1 09:04 14:38
Всего 31 1635 1645 10:58 2.8



Подкатом немного текста и фотографий.

Feb 9, 2016 - 1 minute read -

Электродвигатели "на пальцах"

Не могу не пропиарить цикл статей по управлению и устройству различных электродвигателей (ДПТ, АД, СД, всякие шаговики и так далее):

Да и вообще рекомендую блог к подписке: НПФ ВЕКТОР

Feb 3, 2016 - 1 minute read - туризм

Про снегоступы

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

  • Гуляешь по парку? Пожалуйста - walking!
  • Чуть сложнее? Да на здоровье - hikking!
  • Уже несёшь дом за спиной? Всегда рады - backpacking!
  • Идёшь в лыжный поход? Нет проблем - randonnee skiing (или ski touring)!
  • Hillwalking, mountaineering, и так далее.

Под каждую нишу своё снаряжение, подготовленные тропы, гиды и так далее.

При чём тут снегоступы? Оказывается и для них есть свои названия:

  • Наш жаргонный “снегоступинг” - это snowshoeing,
  • а “снегоступер” - snowshoer.

В статье на Snowshoe|википедии про это есть. Уж не знаю, существуют ли подготовленные снегоступные трассы, но если ответ положительный - я не удивлюсь :)

Jan 31, 2016 - 1 minute read - туризм

Как дышать на холоде

Хорошая статья на тему (автор - полярник):

Правда не знал, что -20, даже при ветре, это экстремально холодно :)

По способам: всё правильно. К примеру, дыхание ртом, когда язык загибаешь к нёбу. Про этот способ несколько лет назад сказал мой друг Олег. С тех пор и пользуюсь. Балаклава с “намордником” тоже решает. Правда скулы нужно не забывать закрывать, а то легкие не застудишь, а ряху обморозишь.

Jan 31, 2016 - 4 minute read - туризм

Малый траверс Ботанического хребта и г.Острая по С-З гребню

Кто не понял - название шутка. Привет Спайдеру :wink:

На воробей сходить никого сблатовать не получилось. Пришлось ноги напрячь, хотя бы где-то в районе города. Результат:

  1. Время: 6:15
    1. в движении: 5:06
  2. Километраж: 16.2 км
  3. Средняя скорость: 3.17 км/час
  4. Общий набор высоты: 1076 м
  5. Общий сброс высоты: 939 м

К слову сказать - до Острой не дошёл, но об этом дальше.

Jan 29, 2016 - 4 minute read - programming c++ projects

Обновление Qt Creator

Пока LOG, Habrahabr и другие гудят по поводу смены лицензионной политики в части Qt (переход на LPGL3) и QtC (переход с LGPL2.1 на GPL3 /именно GPL/ с исключением для плагинов), у меня дошли руки обновить PPA: https://launchpad.net/~adrozdoff/+archive/ubuntu/qtcreator-git

Ну и несколько интересных (для меня) изменений, которые стали доступны в этом билде. Добро пожаловать под кат.