Исходник программы, показывающей пример рисования фаз луны - хорошее упражнение в использовании функций ARC и FloodFill элемента TCanvas.
Фазы луны существуют в виду того, что мы обычно видим только часть луны, освещенной солнцем. Луна обращается вокруг Земли раз в месяц. Плоскость вращения луны почти такая же, как и плоскость вращения Земли вокруг Солнца (разница всего 5 градусов). В течение двух недель, пока Луна находится внутри солнечной орбиты (между нами и Солнцем), мы видим менее половины обращенной к нам стороны Луны (полумесяц). Когда он находится за пределами нашей орбиты, мы видим большую часть луны. Считается, что луна растет в период, когда видимая часть увеличивается, и убывает, когда видимая часть уменьшается. Они объединяются, чтобы произвести повторяющуюся последовательность «лунных фаз»: новый, растущий полумесяц, первая четверть, растущая луна, полная, убывающая луна, последняя четверть, убывающий полумесяц и, наконец, возврат к новой, описывающий полный цикл фаз луны.
Если смотреть с Полярной звезды, Луна вращается вокруг Земли против часовой стрелки, в том же направлении, в котором мы вращаемся вокруг Солнца. Это вызывает свечение слева во время фазы убывания, когда оно движется впереди нас, и справа, когда оно приближается к положению полной луны.
Теперь у нас достаточно информации для создания анимации луны. Мы будем использовать 2 параметра: фаза луны (число от 0 до 1, представляющее видимую часть лица луны) и растущая луна (логический флаг), указывающий, увеличивается или уменьшается освещение.
ARC и Floodfill
Arc принимает 8 параметров, представляющих 4 точки. Два противоположных угла, определяющих эллипс, и 2 точки, представляющие конечные точки 2 линий от центра эллипса. Дуга проводится против часовой стрелки по периметру эллипса от точки пересечения первой линии до точки пересечения со второй линией. Наши начальная и конечная точки всегда будут сверху и снизу по центру изображения луны. Сложнее всего определить, какую половину эллипса рисовать.
Заливка заполнит темную часть луны. Чтобы использовать заливку, мы должны указать точку внутри области, которую нужно заполнить. Затем режим fsborder будет заполнять наружу во всех направлениях, пока не будет достигнут заданный цвет (черная граница для нас). Рядом с краями может быть немного хлопот. Например, луна может быть на пиксель меньше указанной ширины. Таким образом, точка RightX-1, CenterY может быть на границе, а не внутри. В коде есть несколько тестов, чтобы избежать этих аномалий.
Обратите внимание, что есть два случая, фаза 0.0 и фаза 1.0, где увеличение / уменьшение не имеет значения. Во всех остальных случаях мы затемним левую сторону, если луна растет, и правую, если убывает. Нам также нужно будет нарисовать дугу эллипса снизу вверх для правых полумесяцев, указав сначала нижнюю координату при вызове Arc.
Также обратите внимание, что радиус эллипса, определяющего дугу, изменяется от радиуса Луны, Rad, до 0 и обратно до Rad, когда фаза перемещается от 0 до 1. Я экспериментально определил функцию как Delta = Rad * abs (Moonphase - 0.5), где abs - функция абсолютного значения Delphi.
Изображение Луны
Я добавил изображение настоящей луны, чтобы посмотреть, как это будет работать. Изображение границы изображения очищается во время загрузки, устанавливая черным цветом все пиксели, находящиеся на расстоянии более Rad пикселей от центра. Я также обнаружил, что TBitmap использует палитру Windows для реализации цветов. В результате черный отображается как самый темный цвет, определенный в текущей палитре. Никакого реального вреда, за исключением того, что луна становится полностью черной из-за Floodfill, она становится темнее, чем окружающее небо. Я нашел 2 решения. Установка свойства PixelFormat растрового изображения на pf24bit после загрузки изображения заставит палитру распознавать истинный черный цвет. Во второй версии, реализованной в настоящее время, процедура рисования использует значение пикселя [1,1] как черное для рисования и заливки границ. Переменная myBlack содержит истинный черный цвет, если изображение не отображается, или текущее представление палитры, если оно есть.