Представьте, что в уголке вашего терминала висит глобус Земли, и ночь на нём наступает там же, где за окном. Я написал такую программу за два дня. Она загружает карту мира, обтягивает ею сферу и отображает её символами: точками шрифта Брайля, значками Юникода либо буквами. Шар вращается мышью и раскрашивается одной из десяти палитр. Помимо Земли утилита показывает Солнце, Луну, все планеты и Цереру. Практической ценности у неё нет.

С чего всё началось
Однажды мне попался в pinterest прикольный пост: Земля, сложенная из букв, в окружении тонкого кольца, с редкими звёздами вокруг. Захотелось сделать такую же картинку в терминале. Я подумал: пусть сфера вращается, а материки сохраняют собственный цвет. В результате программа может воссоздать и исходный постер.

Установка
Для работы достаточно терминала, умеющего выводить цвета. Внутри сборки уже находятся интерпретатор Python, библиотека NumPy и карты всех тел. Установка состоит из одной команды:
curl -fsSL https://raw.githubusercontent.com/pluttan/ascii-earth/main/install.sh | sh
Или:
brew install pluttan/tap/ascii-earth
Сборки для Windows пока нет. Я тестировал поведение на macOS и Linux, сеансы внутри tmux и соединения через mosh.
Если запустить без аргументов, программа один раз отрисовывает Землю по размеру окна и завершается. Настоящая жизнь начинается в интерактивном режиме:
ascii-earth -i
Далее глобусом управляют мышью и клавиатурой: перетаскивание вращает сферу, а колёсико меняет масштаб. Клавиша ? выводит перечень всех клавиш, q завершает работу.
Что можно менять
Ниже перечислены клавиши интерактивного режима.
Клавиша |
Что делает |
|---|---|
|
предыдущее и следующее тело |
стрелки или |
повернуть шар |
|
приблизить и отдалить |
пробел |
шар крутится сам |
|
вид знаков: Брайль, Юникод, ASCII |
|
следующая и предыдущая палитра |
|
меньше и больше насыщенности |
|
темнее и светлее |
|
цвет: 24 бита, 256 цветов, без цвета |
|
день и ночь по настоящему Солнцу |
|
слежение за Солнцем |
|
масштаб: fit, sqrt, real |
|
кольца планет |
|
звёзды, обводка диска, подписи |
|
вернуть всё как было |
Те же параметры можно задать через аргументы командной строки, если требуется сразу получить картинку в определённом виде:
ascii-earth --body saturn --lat 26 # Сатурн, кольца раскрыты ascii-earth --sun # Земля прямо сейчас: день и ночь ascii-earth --palette catppuccin # палитра Catppuccin ascii-earth --scale real --body mars # Марс в честном размере ascii-earth --spin # шар крутится сам, Ctrl+C для выхода
Раскраска и палитры
Всего десять палитр, и та, что имитирует природные цвета, напоминает атлас: синий океан, зелёные леса, жёлтые пустыни. Палитры играют с цветом: синяя, зелёная, янтарная, ледяная, серая, inferno, неоновая и Catppuccin. Клавиша p циклически меняет палитру прямо во время работы, а [, ], , и . регулируют насыщенность и яркость.

Исходный цвет считывается с реальной карты, после чего палитра его перекрашивает. Палитра Catppuccin заимствует цвета из одноимённой темы. Когда терминал не заявляет о поддержке 24-битного цвета, программа автоматически переключается в режим 256 цветов.
Доступны три набора символов, переключаемых клавишей g, причём по умолчанию используется Брайль, дающий самые плавные очертания. Последовательность из 56 символов Юникода создаёт наиболее пёстрое изображение, а буквы ASCII ближе всего к тому плакату.

Также можно задать подписи сверху и снизу. Если выбрать буквы, синюю палитру и две строки подписей, программа воспроизводит тот самый постер:
ascii-earth --glyphs ascii --palette blue \ --top "THAT'S NO EARTH!" --bottom "IT'S A SPACE STATION."

Восемь точек на клетку
Чем символы Брайля превосходят обычные буквы? Обычная буква заполняет клетку одним цветовым пятном, тогда как в Юникоде существует блок из 256 знаков Брайля, каждый из которых содержит восемь точек в сетке 2 на 4. Каждая точка соответствует отдельному биту; символ формируется прибавлением суммы битов активных точек к коду U+2800.

Одна терминальная клетка превращается в восемь пикселей. Цвет у клетки остаётся одним, но граница диска и береговые линии получаются сглаженными. Решение о том, какие точки активировать, принимает упорядоченное размытие по матрице Байера 4×4: в светлых областях зажигается больше точек, в тёмных меньше.
Я строю изображение от экранных координат к карте. Для каждого экранного пикселя вычисляю соответствующую точку на сфере, применяю к ней поворот на угол наклона оси, после чего определяю широту и долготу. По этим координатам из карты извлекаю цвет. Поскольку клетка терминала вдвое выше, чем широка, мне приходится сжимать диск по вертикали вдвое, иначе Земля выглядела бы вытянутой.
День и ночь по реальному Солнцу
Клавиша n активирует реальный терминатор дня и ночи. Программа вычисляет подсолнечную точку, то есть место, где Солнце находится в зените. Широта определяется днём года, а долгота временем по UTC: каждый час Солнце сдвигается на 15 градусов к западу. Ночная сторона отображается в чёрно-белой гамме, причём море делается темнее суши, чтобы очертания берегов оставались различимыми. Погрешность составляет пару градусов, для визуализации этого достаточно.

Клавиша f включает режим отслеживания Солнца. Центр диска совмещается с подсолнечной точкой, так что видимой остаётся лишь дневная сторона. Земля вращается под Солнцем с реальной скоростью, один оборот в сутки. Кадр обновляется ежесекундно, и такой глобус удобно размещать в узкой панели tmux:
ascii-earth --follow
Солнце, Луна и планеты
Клавиши < и > циклически переключают 11 небесных тел: Солнце, восемь планет, Луну и Цереру. Карту Земли я загрузил из NASA Blue Marble, а остальные из Solar System Scope под лицензией CC BY 4.0.
Сатурн и Уран обладают кольцами, причём передняя дуга рисуется поверх сферы, а задняя скрывается за ней. В кольце Сатурна заметна тёмная щель, напоминающая деление Кассини. Однородное кольцо при вращении казалось бы статичным, поэтому в кольцо внесены неравномерные сгустки.

Клавиша m переключает масштаб, и в режиме fit каждое тело полностью занимает экран. Режим real сохраняет реальные пропорции: Солнце в 109 раз больше Земли и заполняет экран сплошной стеной, тогда как Церера видна крохотным кружком. Режим sqrt извлекает квадратный корень из отношения радиусов. При таком масштабе Солнце превосходит Землю примерно в 10 раз, и при переключении тел наглядно видно соотношение размеров. Колёсико мыши в этих режимах масштабирует все тела синхронно.

Что получилось
У меня вышел скрипт на Python, умещающийся в одном файле объёмом примерно в тысячу строк. Он отображает 11 небесных тел, используя три набора символов и десять цветовых схем, определяет, где сейчас день, а где ночь, и работает полностью офлайн. Код открыт под лицензией MIT: https://github.com/pluttan/ascii-earth.
TheHost
Объявлена неделя нейрослопных постов по навайбкоженным поделкам