Навеяно.
Из того, что мне понравилось:
-
SDL2
* Язык: C
* Реализация: библиотека
* Реально проста для простых применений. Куча примеров и статей в интернете. Поддерживает достаточно большое число платформ и компиляторов.
-
CImg
* Язык: C++
* Реализация: header-only
* Библиотека отличается феноменальной простотой установки: только один заголовочный файл и всё. Минусом будет только тот факт, что нужно будет указать правильные флаги линковщика для целевой платформы. Но при этом весь базовый функционал для рисования и процессинга изображений присутствует. Дружится с OpenCV. Думаю, стоит рассматривать вариант этой библиотеки, когда нужно что-то по-быстрому нарисовать.
-
SMFL
* Язык: C++
* Реализация: библиотека
* С данной библиотекой особо не имел дел. Но примеры представляют её эдаким вариантом SDL, но на C++. Стоит попробовать.
Кроме того, на ресурсе
cppreference.com есть свой
список библиотек под различные задачи (в дополнение к
предыдущему посту), и, в частности,
для графики.
ЗЫ по ссылке выше есть интересная библиотечка для пользовательского интерфейса (GUI):
nana, стоит пощупать. А так же для TUI:
cwidget.
ЗЗЫ прочие ссылки:
На RSDN промелькнуло, может ещё кому полезно будет:
Кто хочет дополнить - шлите мёрж-реквесты.
Прочие полезные ссылки, спасибо @sikmir:
-
C++ links - A categorized list of C++ resources. Assembler, Lock-free и иже с ними.
-
Awesome C/C++ - A curated list of awesome C/C++ frameworks, libraries, resources, and shiny things. Inspired by awesome-… stuff.
Пока речь пойдёт про алиасы (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
мы найдём искомое описание.
Сначала немного информации из мира С.
При запуске приложения (речь идёт о POSIX) вместе с ним открывается 3 файловых дескритоптора:
- 0 - ассоциирован со стандартным вводом (stdin)
- 1 - ассоциирован со стандартным выводом (stdout)
- 2 - ассоциирован со стандартным выводом в поток ошибок (stderr)
В стандартной библиотеки Си используется FILE*
-based буфферизируемый доступ к файлам и терминалу. В stdio.h объявлены следующие глобальные символы, которые отражают стандартные потоки ввода вывода:
Соответственно их свободно можно использовать вместе с семейством функций 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 и вообще, а как оно там внутри устроено:
Недавно на
ru.SO проскочил вопрос:
как можно подключиться к SSM (
Source Specific Multicast) группе?
Нюанс в том, что для этого используется опция MCAST_JOIN_SOURCE_GROUP
для которой нет объекта-обёртки. Но, как оказалось, такой объект пишется самостоятельно на раз-два. Под катом я продублирую
свой ответ, как пример подхода реализации нужного функционала. Пример не самый идеологически правильный, но, как оказалось, рабочий. Автор сам предложил
свой вариант с захватом сырого хендла. Такой подход тоже имеет смысл в некоторых ситуациях((у меня случилось однажды так подружить сетевые абстракции Asio и libev, реализовав, тем самым, реактор на Asio :simple_smile:)).
23 февраля решили отпраздновать очередным снегоступингом.
По предложению Кирилла рассматривали варианты посещения южных отрогов Ливадийского хребта.
Маршрут изначально рассматривался как:
Фокино-г.Халаза-г.Горбуша-г.Лысый дед-Молёный мыс
но в результате был скорректирован до:
Душкино-падь Светланка-г.Круглая-г.Пидан-Лукьяновка.
Собралось три человека: я, Кирилл, Саня. В роли адового тропильщика в этот раз Кирилл.
Я подумал и решил, что функционала и стабильности достаточно для релиза версии 1.0.
Так что да будет так:
https://github.com/h4tr3d/geocrop/releases/tag/v1.0
Если у вас на входе привязанный 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 там сразу зашита информация об обрезке (только странно, что они сразу не сделали рамку прозрачной).
Теперь в
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
).
Внезапно
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:
- Инструмент привязки карты по точкам (в визуальной форме). Не знаю, будет ли сделан, но таск
завёл.
- Экспорт выделенного куска карты в JNX. Потребность сомнительная, но пару раз пригождалась.
Ну и ссылки:
Для примера будет рассмотрен сервис
http://loadmap.net, который предоставляет карты с привязками в формате OziExplorer.
Минусом подобных карт бывает то, что у них есть рамка и отдельные листы карт перекрывают друг друга при открытии. Для того, что бы рамку резать я уже написал
ранее((ozi2map от туда более не актуальна)) про свою программку
geocrop.
Теперь про самый смак: QMS умеет открывать .vrt файлы. VRT файл это XML документ, с описанием привязки и различных преобразований, понятные движку GDAL. Так вот, в ходе беглого исследования оказалось, что мой способ резки рамки применим к VRT файлам: данное преобразование просто сохраняется внутри и применяется при открытии! Если добавить сюда тот факт, что переконвертации самого растра не происходит и просто формируется дополнительный маленький XML файл, то счастье становится полным.
Рассматривать вопрос сборки программы я подробно не буду, скажу только, что нужны dev пакеты для libgdal и libproj4. Устанавливать программу не нужно - просто скопируйте в удобное место, у меня это ~/bin
. Сборка и работа на Windows не проверялась.
Вот, преамбула завершилась… Основная часть будет короче :)
-
Скачиваем растровый файл карты, допустим это 500-метровка K-53-027-A, тогда файл будет K-53-027-A.png
-
Скачиваем файл привязки K-53-027-A.map
-
Обрезаем рамку и формируем 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, т.е. пятисотметровка.
//Их было четверо…
Они шли, шли, шли и, наконец, пришли!//
Наконец-то первый полноценный снегоступный ПВД за сезон. То несросты, то переносы, но всё-таки собрались: Я, Коля, Кирилл и Гена.
А вообще, пробую завести ещё одну традицию: снегоступинг на Читинзу во второй половине января или начале февраля. В прошлом году была первая серия.
Как обычно, выехали на первой электричке в субботу, домой возвращались на крайней в воскресенье.
Маршрут изначально намечали:
Партизан (пл.98 км) - руч.Просечный - С-В хребет - вершина 1156 м - трверс на Читинзу - Читинза - С-З хребет - р.Постышевка - Наречное.
Но в электричке скорректировали его до:
Красноармейский - Ручьи - С-С-В хребет (классика) - Читинза - траверс на Смольную - Смольная - С-В хребет - вершина 734 м - руч.Прав.Лесопильный - Тигровой
Небольшая сводка:
День |
Протопали, км |
Набор высоты, м |
Сброс высоты, м |
Время в движении, ч |
Средняя скорость, км/ч |
Начало движения, ч |
Конец движения, ч |
Cб |
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.
В статье на Snowshoe|википедии
про это есть. Уж не знаю, существуют ли подготовленные снегоступные трассы, но если ответ положительный - я не удивлюсь :)
Хорошая статья на тему (автор - полярник):
Правда не знал, что -20, даже при ветре, это экстремально холодно :)
По способам: всё правильно. К примеру, дыхание ртом, когда язык загибаешь к нёбу. Про этот способ несколько лет назад сказал мой друг Олег. С тех пор и пользуюсь. Балаклава с “намордником” тоже решает. Правда скулы нужно не забывать закрывать, а то легкие не застудишь, а ряху обморозишь.