Lately, I was reading this snippet by vegaseat. I thought, why not do it in C#? But I would also like to add lattitude and logitude in the celestial calculations and draw a picture of the moon at that moment and location. Now the calculations can get a bit involved but are doable. So first I did a little try out about the drawing of a moon phase picture. Code for the main drawing method is given here. Just call it from a Paint event. A litte project file for a test app is included in a zip file as is a picture of how it looks.
Draw phases of the moon On a form
using System;
using System.Drawing;
namespace MoonPhases
{
public enum Phase
{
new_moon, waxing_crescent, first_quarter, waxing_gibbous,
full_moon, waning_gibbous, third_quarter, waning_crescent
}
class Moon
{
private const float ArcLength = 180; //from north to south pole
private float penthickness = 2f; //2 to get a better overlap of pixels
public int DrawSize { get; set; }
public Point DrawPosition { get; set; }
public Moon()
{
DrawSize = 200; //default values
DrawPosition = new Point(100, 100);
}
public Moon(int drawsize)
{
DrawSize = drawsize;
if (drawsize < 50) penthickness = 1f;
else penthickness = 2f;
DrawPosition = new Point(100, 100);
}
/// <summary>
/// "Main" method of this class
/// </summary>
/// <param name="a Graphics object"></param>
/// <param name="angle should be -90"></param>
/// <param name="phase see the Pase enum"></param>
public void DrawMoonPhase(Graphics G, float angle, Phase phase)
{
bool blackcoloring = true;
Brush BR;
Pen P = new Pen(Color.Black, penthickness);
int moonphase = GetMoonPhasenumber(phase, out blackcoloring);
if (blackcoloring) // reverse color depending on what phase we are in
{
BR = Brushes.Black; P.Color = Color.Wheat;
}
else
{
BR = Brushes.Wheat; P.Color = Color.Black;
}
G.FillEllipse(BR, DrawPosition.X, DrawPosition.Y, DrawSize, DrawSize);
if (moonphase <= DrawSize / 2)
{
DrawRightMoonPart(G, angle, P, moonphase);
}
else
{
DrawRightMoonPart(G, angle, P, DrawSize / 2);
DrawLeftMoonPart(G, angle, P, moonphase - DrawSize / 2);
}
}
private void DrawLeftMoonPart(Graphics G, float angle, Pen P, int moonphase)
{
for (int i = 0; i < moonphase; i++)
{
// Increase rect size to draw arc in
G.DrawArc(P,
new RectangleF(DrawPosition.X + DrawSize / 2 - i, DrawPosition.Y, 0.1f + 2 * i, DrawSize), angle + ArcLength, ArcLength);
}
}
private void DrawRightMoonPart(Graphics G, float angle, Pen P, int moonphase)
{
for (int i = 0; i < moonphase; i++)
{
// Decrease rect size to draw arc in
G.DrawArc(P,
new RectangleF(DrawPosition.X + i, DrawPosition.Y, DrawSize - 2 * i, DrawSize), angle, ArcLength);
}
}
//return the number of pixels, to indicate sunlight on the moon
private int GetMoonPhasenumber(Phase P, out Boolean colorblack)
{
int phasenumber = 0;
Boolean cb = true;
switch (P)
{
case Phase.new_moon:
phasenumber = 0;
cb = true;
break;
case Phase.waxing_crescent:
phasenumber = DrawSize / 4;
cb = true;
break;
case Phase.first_quarter:
phasenumber = DrawSize / 2;
cb = true;
break;
case Phase.waxing_gibbous:
phasenumber = 3 * DrawSize / 4;
cb = true;
break;
case Phase.full_moon:
phasenumber = 0;
cb = false;
break;
case Phase.waning_gibbous:
phasenumber = DrawSize / 4;
cb = false;
break;
case Phase.third_quarter:
phasenumber = DrawSize / 2;
cb = false;
break;
case Phase.waning_crescent:
phasenumber = 3 * DrawSize / 4;
cb = false;
break;
default:
break;
}
colorblack = cb;
return phasenumber;
}
}
}
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.