在研究日历的时候,通常会关注公历,但很少有人注意到农历。为了计算任何给定日期的月球年龄,浏览了互联网上的许多网站。发现许多网站提供了不同的计算方法,采纳了其中一些方法,以期得到更接近真实情况的结果。
注意到,大多数网站在计算儒略日时意见一致,但在计算月球年龄时却存在分歧,这些网站之间的差异可能高达一天。当月球年龄为30天时,一些网站的结果为零。
在这个程序中,计算了月球的大致年龄(以天为单位),并没有关注小时和分钟的部分。为了让程序更有用,添加了一个PictureBox控件来显示与月球年龄相对应的月球亮面和暗面。
创建了两个项目,一个用C#(2003)编写,另一个用VB.NET(2003)编写。MoonPhase项目有一个表单(frmMoon),包含以下控件:MonthCalendar控件(MyCalendar)、Button控件(btnToDay)、Button控件(btnClose)、PictureBox控件(PicMoon)和Label控件(lblAge)。
将日期转换为儒略日:
private int JulianDate(int d, int m, int y) {
int mm, yy;
int k1, k2, k3;
int j;
yy = y - (int)((12 - m) / 10);
mm = m + 9;
if (mm >= 12) {
mm = mm - 12;
}
k1 = (int)(365.25 * (yy + 4712));
k2 = (int)(30.6001 * mm + 0.5);
k3 = (int)((yy / 100) + 49) * 0.75 - 38;
// 'j' for dates in Julian calendar:
j = k1 + k2 + d + 59;
if (j > 2299160) {
// For Gregorian calendar:
j = j - k3;
}
// 'j' is the Julian date at 12h UT (Universal Time)
return j;
}
计算月球的大致年龄(以天为单位):
private double MoonAge(int d, int m, int y) {
int j = JulianDate(d, m, y);
// Calculate the approximate phase of the moon
double ip = (j + 4.867) / 29.53059;
ip = ip - Math.Floor(ip);
// After several trials I've seen to add the following lines,
// which gave the result was not bad
if (ip < 0.5) {
double ag = ip * 29.53059 + 29.53059 / 2;
} else {
double ag = ip * 29.53059 - 29.53059 / 2;
}
// Moon's age in days
ag = Math.Floor(ag) + 1;
return ag;
}
绘制月球:
private void DrawMoon() {
int Xpos, Ypos, Rpos;
int Xpos1, Xpos2;
double Phase;
Phase = ip;
// Width of 'ImageToDraw' Object = Width of 'PicMoon' control
int PageWidth = PicMoon.Width;
// Height of 'ImageToDraw' Object = Height of 'PicMoon' control
int PageHeight = PicMoon.Height;
// Initiate 'ImageToDraw' Object with size = size of control 'PicMoon' control
Bitmap ImageToDraw = new Bitmap(PageWidth, PageHeight);
// Create graphics object for alteration.
Graphics newGraphics = Graphics.FromImage(ImageToDraw);
Pen PenB = new Pen(Color.Black);
// For darkness part of the moon
Pen PenW = new Pen(Color.White);
// For the lighted part of the moon
for (Ypos = 0; Ypos <= 45; Ypos++) {
Xpos = (int)Math.Sqrt(45 * 45 - Ypos * Ypos);
// Draw darkness part of the moon
Point pB1 = new Point(90 - Xpos, Ypos + 90);
Point pB2 = new Point(Xpos + 90, Ypos + 90);
Point pB3 = new Point(90 - Xpos, 90 - Ypos);
Point pB4 = new Point(Xpos + 90, 90 - Ypos);
newGraphics.DrawLine(PenB, pB1, pB2);
newGraphics.DrawLine(PenB, pB3, pB4);
// Determine the edges of the lighted part of the moon
Rpos = 2 * Xpos;
if (Phase < 0.5) {
Xpos1 = -Xpos;
Xpos2 = (int)(Rpos - 2 * Phase * Rpos - Xpos);
} else {
Xpos1 = Xpos;
Xpos2 = (int)(Xpos - 2 * Phase * Rpos + Rpos);
}
// Draw the lighted part of the moon
Point pW1 = new Point(Xpos1 + 90, 90 - Ypos);
Point pW2 = new Point(Xpos2 + 90, 90 - Ypos);
Point pW3 = new Point(Xpos1 + 90, Ypos + 90);
Point pW4 = new Point(Xpos2 + 90, Ypos + 90);
newGraphics.DrawLine(PenW, pW1, pW2);
newGraphics.DrawLine(PenW, pW3, pW4);
}
// Display the bitmap in the picture box.
PicMoon.Image = ImageToDraw;
// Release graphics object
PenB.Dispose();
PenW.Dispose();
newGraphics.Dispose();
ImageToDraw = null;
}
如果想查看VB.NET代码,请解压Moon_VB.zip文件后返回源文件。