Инструменты пользователя

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



// C++ и 2D графика

Навеяно.

Из того, что мне понравилось:

    • Язык: C
    • Реализация: библиотека
    • Реально проста для простых применений. Куча примеров и статей в интернете. Поддерживает достаточно большое число платформ и компиляторов.
    • Язык: C++
    • Реализация: header-only
    • Библиотека отличается феноменальной простотой установки: только один заголовочный файл и всё. Минусом будет только тот факт, что нужно будет указать правильные флаги линковщика для целевой платформы. Но при этом весь базовый функционал для рисования и процессинга изображений присутствует. Дружится с OpenCV. Думаю, стоит рассматривать вариант этой библиотеки, когда нужно что-то по-быстрому нарисовать.
    • Язык: C++
    • Реализация: библиотека
    • С данной библиотекой особо не имел дел. Но примеры представляют её эдаким вариантом SDL, но на C++. Стоит попробовать.

Кроме того, на ресурсе cppreference.com есть свой список библиотек под различные задачи (в дополнение к предыдущему посту), и, в частности, для графики.

ЗЫ по ссылке выше есть интересная библиотечка для пользовательского интерфейса (GUI): nana, стоит пощупать. А так же для TUI: cwidget.

ЗЗЫ прочие ссылки:

// Коллекция ресурсов по современному C++

На RSDN промелькнуло, может ещё кому полезно будет:

Кто хочет дополнить - шлите мёрж-реквесты.

Прочие полезные ссылки, спасибо @sikmir:

// Полезные алиасы для программиста

Пока речь пойдёт про алиасы (alias) для man. Потом, может быть, что-то будет дополнено.

MAN

Часто возникает вопрос: «man чаво?». Кроме того, интересные программистам документы, обычно, находятся в секциях 2 (системные вызовы), 3 (библиотечные вызовы) и 7 (стандарты, соглашения, обзоры). По назначению других секций можете спрашивать:

  man # intro

где # - номер секции от 1 до 7.

В общем родилось три алиаса: для обращения и для поиска.

Для использование, код ниже поместить в ~/.bashrc

alias man-prog='man -s 2,3,7'
alias man-prog-search='man -s 2,3,7 -K'
alias man-prog-apropos='man -s 2,3,7 -k'

Первый - просто ограничивает область поиска и по man-prog printf выведет не описание команды, а описание функции.

Второй - обеспечивает полнотекстовый поиск по страницам, третий - по индексу (apropos). В чём разница. Поясню на примере:

$ man-prog-apropos tcp
clnttcp_create (3)   - library routines for remote procedure calls
clock_getcpuclockid (3) - obtain ID of a process CPU-time clock
getcpu (2)           - determine CPU and NUMA node on which the calling thread is running
pthread_getcpuclockid (3) - retrieve ID of a thread's CPU time clock
QwtCPointerData (3)  - (неизвестный объект)
sched_getcpu (3)     - determine CPU on which the calling thread is running
svctcp_create (3)    - library routines for remote procedure calls
tcp (7)              - TCP protocol
zmq_tcp (7)          - 0MQ unicast transport using TCP

Вроде всё хорошо. Дальше:

$ man-prog-apropos TCP_CORK
TCP_CORK: ничего подходящего не найдено.

Оппа… В гуголь лезть? А если так:

$ man-prog-search TCP_CORK
--Man-- след: sendfile(2) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]
--Man-- след: sendfile64(2) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]
--Man-- след: sendmsg(2) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]
--Man-- след: sendto(2) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]
--Man-- след: splice(2) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]
--Man-- след: tcp(7) [ просм (ввод) | пропуск (Ctrl-D) | выход (Ctrl-C) ]

в man 7 tcp мы найдём искомое описание.

// 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() из старого доброго Borland C++). Доступ через эти функции не буфферизирован.

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

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

В C++ для работы с потоками служит библиотека 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 и вообще, а как оно там внутри устроено:

// Source Specific Multicast и Asio

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

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

8) у меня случилось однажды так подружить сетевые абстракции Asio и libev, реализовав, тем самым, реактор на Asio :-)

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

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

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

Маршрут изначально рассматривался как:
Фокино-г.Халаза-г.Горбуша-г.Лысый дед-Молёный мыс
но в результате был скорректирован до:
Душкино-падь Светланка-г.Круглая-г.Пидан-Лукьяновка.

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

// GeoCrop 1.0

Я подумал и решил, что функционала и стабильности достаточно для релиза версии 1.0.

Так что да будет так: https://github.com/h4tr3d/geocrop/releases/tag/v1.0

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

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

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

  • Ozi Explorer
  • World files9)
  • Global Mapper

рассмотрим более подробно.

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 файл10) подтягивается автоматически, если на входе карта в 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 там сразу зашита информация об обрезке (только странно, что они сразу не сделали рамку прозрачной).

// Новый режим в 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, как следствие, образовались такие возможности: Быстро и ненавязчиво готовим карту для открытия в QMapShack) или только обрезать рамку, не делая кроп (опция -n).

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

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

Минусом подобных карт бывает то, что у них есть рамка и отдельные листы карт перекрывают друг друга при открытии. Для того, что бы рамку резать я уже написал ранее11) про свою программку 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, т.е. пятисотметровка.

11) ozi2map от туда более не актуальна

// QMapShack

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

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

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

  • Открытие серии файлов с геоданными, переданных, как аргументы приложения. Это не относится с картам (?) - они берутся только из директорий, которые вы настроили в программе (аналогично произвольная карта не может быть открыта через File → Open Map, такого пункта просто нет).
  • Поддерживаются ВСЕ форматы карт, которые поддерживаются GDAL (!). Но делается это не напрямую, а через формирование .vrt файла. Сей унифицированный способ отменил отдельное открытие GeoTIFF - теперь нужно и для него формировать vrt-файл. К счастью теперь это делается через внутренний инструмент vrtbuilder и позволяет в большинстве случаев обойтись без утомительной конвертации в GeoTIFF, например привязок OziExplorer13)14). Вообще список теперь достаточно вменяемый:
    • Векторые карты:
      • .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. Потребность сомнительная, но пару раз пригождалась.

Ну и ссылки:

12) (!) отмечены фичи уникальные, по сравнению с QLGT, а (-), то, что убрано, (?) - спорные изменения
13) В случае привязок Ozi, нужно открывать .map файл, в случае привязок .pgw+.prj открывать нужно одноимённую картинку
14) К сожалению, на карты и привязки с http://loadmap.net он упорно ругается

// Читинза под снегом 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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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