65.9K
CodeProject 正在变化。 阅读更多。
Home

计算和绘制月相

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (29投票s)

2010 年 8 月 8 日

CPOL

1分钟阅读

viewsIcon

217845

downloadIcon

4298

计算月球的年龄并在任意给定日期绘制月相。

引言

许多社区除了阳历之外还非常关注农历,所以我查阅了许多网站来了解如何在任何给定日期计算月龄。我发现许多网站提供了不同的方法,我结合了这些方法以获得更接近真实的结果。

我注意到大多数网站都同意使用儒略日期,但在计算月龄上存在分歧,这些网站之间的差异高达一天,当月龄为 30 天时,某些网站的结果为零。

在这个程序中,我计算了月龄的近似天数,没有考虑小时和分钟的小数部分。

为了使程序更有用,我添加了一个PictureBox 控件来显示月亮被照亮的部分和黑暗的部分,与月龄相对应。

img039.JPG

背景

我创建了两个项目,一个用 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)((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
    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)
        ag = ip * 29.53059 + 29.53059 / 2;
    else
        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;
} 

您可以在解压缩Moon_VB.zip文件后返回源代码文件以阅读 VB.NET 代码。

结束语

如果您有任何想法或找到另一种计算月龄的代码,请告诉我。感谢 Code Project 以及所有人的帮助。

Mostafa Kaisoun
m_kaisoun@hotmail.com

© . All rights reserved.