月(moon)の姿を描画するJavaのソースコード
来年のカレンダーの中には、月の満ち欠けが載っているものもありますね。
月の満ち欠けにあわせてスケジュールを調整すると効率が上がる
という説もあるようです。(掃除は月齢15〜29の時が良い?)
毎度、管理人イガジーです。
そんなわけで、月(moon)の姿を描画するプログラムを常備しておくと
よいことがあるかもしれません(^^)
countdownプログラムに組み込んだり壁紙にカレンダーを埋め込もうwallcale.jarに組み込むのも良いかもしれません。
という訳でソースコードを一気に公開します。(ただし無保証です)
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.Calendar;
import java.util.GregorianCalendar;
// copyright by MLTLab
public class MoonShape implements ActionListener {
int mr=120;
Frame f0;
BufferedImage bi;
Graphics g;
MyCanvas cv;
TextField tf;
String []lstr={"年","月","日","時"};
int nn=lstr.length;
TextField []ymdh = new TextField[nn];
Color c0=Color.YELLOW;
Color c1=Color.DARK_GRAY;
MoonShape(String []as){
f0=new Frame("Moon Shape");
f0.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev) {
System.exit(0);
}
});
if (as.length>0){
for (int i=0;i<as.length;++i) {
char c1=as[i].charAt(0);
if ((c1>='0')&&(c1<='9')) {
try {
mr=Integer.parseInt(as[i]);
} catch (NumberFormatException e) {
mr=120; // assume
}
if (mr<10) mr=10;
if (mr>200) mr=200;
}
}
}
bi=new BufferedImage(mr*2+40,mr*2+40,BufferedImage.TYPE_INT_RGB);
g=bi.getGraphics();
g.setColor(c0);
cv=new MyCanvas();
f0.add(cv,BorderLayout.CENTER);
Panel p0=new Panel();
Panel p1=new Panel();
tf=new TextField(5);
tf.addActionListener(new DrawAge());
p1.add(new Label("月齢"));
p1.add(tf);
for (int i=0;i<nn;++i) {
if (i==0) ymdh[i]=new TextField(4);
else ymdh[i]=new TextField(2);
ymdh[i].addActionListener(this);
p0.add(ymdh[i]);
p0.add(new Label(lstr[i]));
}
Button bb=new Button("Set");
bb.addActionListener(this);
p0.add(bb);
f0.add(p0,BorderLayout.NORTH);
f0.add(p1,BorderLayout.SOUTH);
f0.setSize(300,400);
f0.setVisible(true);
}
public int moonage10(Calendar c) { // 月齢を10倍した値を返す
long adj=4L;
return (int)((((c.getTimeInMillis()/1000L)-929332980L)%2551442L)/8640L+adj);
}
@Override
public void actionPerformed(ActionEvent arg0) {
int []dt=new int[nn];
Calendar cc;
boolean vok=true;
for (int i=0;i<nn;++i) {
try {
dt[i]=Integer.parseInt(ymdh[i].getText());
} catch (NumberFormatException e) {
dt[i]=0;
vok=false;
}
}
if (vok) {
cc=new GregorianCalendar(dt[0],dt[1]-1,dt[2],dt[3],0);
}else{
cc=new GregorianCalendar();
}
int yy=cc.get(Calendar.YEAR);//System.out.print("year="+yy);
ymdh[0].setText(Integer.toString(yy));
int mm=cc.get(Calendar.MONTH)+1;//System.out.print(" month="+mm);
ymdh[1].setText(Integer.toString(mm));
int dd=cc.get(Calendar.DAY_OF_MONTH);//System.out.print(" day="+dd);
ymdh[2].setText(Integer.toString(dd));
int hh=cc.get(Calendar.HOUR_OF_DAY);//System.out.println(" hour="+hh);
ymdh[3].setText(Integer.toString(hh));
int ag=moonage10(cc);
tf.setText(Double.toString((double)ag/10.0));
moonshape10(ag,mr);
}
void moonshape10(int age10,int r) {
moonshape((double)age10/10.0,r);
}
public static void main(String[] args) {
new MoonShape(args);
}
void moonshape(double age,int r) {
int x0=r+20;
int y0=r+20;
double theta=Math.PI*age/14.765;
for (int y=-r;y<=0;++y) {
int x2,x1;
// x2=(int)Math.sqrt(r*r-y*y);
double ac=Math.acos((double)y/(double)r);
x2=(int)((double)r*Math.sin(ac)); // 円周
x1=(int)((double)r*Math.cos(theta)*Math.sin(ac)); // 月の形
if ((age>1.0)&&(age<29.0)) {
if (age<15.0) {
g.setColor(c0);
g.drawLine(x0+x1, y0+y, x0+x2, y0+y);
g.drawLine(x0+x1, y0-y, x0+x2, y0-y);
g.setColor(c1);
g.drawLine(x0-x2, y0+y, x0+x1-1, y0+y);
g.drawLine(x0-x2, y0-y, x0+x1-1, y0-y);
}else{
g.setColor(c0);
g.drawLine(x0-x2, y0+y, x0-x1, y0+y);
g.drawLine(x0-x2, y0-y, x0-x1, y0-y);
g.setColor(c1);
g.drawLine(x0-x1-1, y0+y, x0+x2, y0+y);
g.drawLine(x0-x1-1, y0-y, x0+x2, y0-y);
}
}else{
g.setColor(c1);
g.drawLine(x0-x2, y0+y, x0+x2, y0+y);
g.drawLine(x0-x2, y0-y, x0+x2, y0-y);
}
}
cv.repaint();
}
class DrawAge implements ActionListener {
private double v;
@Override
public void actionPerformed(ActionEvent arg0) {
try {
v = Double.parseDouble(tf.getText());
} catch (NumberFormatException e) {
//e.printStackTrace();
v=0.0;
}
moonshape(v,mr);
for (int i=0;i<lstr.length;++i) ymdh[i].setText(null);
}
}
class MyCanvas extends Canvas {
private static final long serialVersionUID = 1L;
@Override
public void update(Graphics g0) {
paint(g0);
}
@Override
public void paint(Graphics g0) {
g0.drawImage(bi,0,0,null);
}
}
}
年月日のところに何も入力せずに[Set]を押すと
その時点での日付時刻がセットされます。
月齢の部分に数値を入れて、[Enter]を押すと、その月齢に対応した
月の姿を描画します。その時、日付時刻はクリアされます。
月齢計算は簡略計算なので、±0.5 くらいの誤差があります。
(このプログラムに限らず、月齢表示プログラムには誤差がある
ものだと思って頂いた方がよいと思います。)
プログラムに関するご質問などは、お気軽に
メールフォームから送ってください。
この記事へのコメントはこちら