「(本名)くん、Mokkosu を書こうよ」
というわけで Mokkosu 内トロコイドを書くことになった。
#1 作ってみた
実装したのは以下の機能
・ 内側、外側、描画点のサイズの変更
・ 各サイズのリセット
・ カラフルな線
#2 ソースコード
trochoid.mok
# ここにコードを入力して、上の緑色の三角を押すと実行できます。
include "Graphics.mok";
include "List.mok";
include "Print.mok";
let map_tup3 f (x,y,z) = (f x, f y, f z);
let rc = ref 100;
let rm = ref 50;
let rd = ref 10;
let cwheel i =
{
_ ? i < 30 -> call Color::get_Red();
_ ? i < 60 -> call Color::get_OrangeRed();
_ ? i < 90 -> call Color::get_Orange();
_ ? i < 120 -> call Color::get_Gold();
_ ? i < 159 -> call Color::get_Yellow();
_ ? i < 180 -> call Color::get_GreenYellow();
_ ? i < 210 -> call Color::get_Green();
_ ? i < 240 -> call Color::get_DarkBlue();
_ ? i < 270 -> call Color::get_Blue();
_ ? i < 300 -> call Color::get_BlueViolet();
_ ? i < 330 -> call Color::get_Violet();
_ ? i < 360 -> call Color::get_Magenta();
_ -> error "alien."
}
();
let get_pen n =
let color =
cwheel n
in
new Pen(color,3);
let get_pos rc rm rd =
let dr = rc -. rm in
for theta <- 0 .. 360;
in
let dth = int_to_double theta /. pi2 in
let x = dr *. cos dth +. rd *. cos (dr /. rm *. dth) +. 150.0 in
let y = dr *. sin dth -. rd *. sin (dr /. rm *. dth) +. 150.0 in
(double_to_int x, double_to_int y);
do set_size 600 300;
## Create Labels
let inner_circle_label = new Label ();
let outer_circle_label = new Label ();
let draw_circle_label = new Label ();
let inner_circle_label_dis = new Label ();
let outer_circle_label_dis = new Label ();
let draw_circle_label_dis = new Label ();
do inner_circle_label.set_Location(new Point(300,100));
do inner_circle_label.set_Text("Inner circle");
do outer_circle_label.set_Location(new Point(400,100));
do outer_circle_label.set_Text("Outer circle");
do draw_circle_label.set_Location(new Point(500,100));
do draw_circle_label.set_Text("Drawing point");
do inner_circle_label_dis.set_Location(
new Point(inner_circle_label.get_Left(),
inner_circle_label.get_Height() + inner_circle_label.get_Top() + 10)
);
do inner_circle_label_dis.set_Text(!rm |> to_string);
do outer_circle_label_dis.set_Location(
new Point(outer_circle_label.get_Left(),
outer_circle_label.get_Height() + outer_circle_label.get_Top() + 10)
);
do outer_circle_label_dis.set_Text(!rc |> to_string);
do draw_circle_label_dis.set_Location(
new Point(draw_circle_label.get_Left(),
draw_circle_label.get_Height() + draw_circle_label.get_Top() + 10)
);
do draw_circle_label_dis.set_Text(!rd |> to_string);
## Create buttons
let up_inner_circle = new Button ();
let down_inner_circle = new Button ();
let up_draw_point = new Button ();
let down_draw_point = new Button ();
let up_outer_circle = new Button ();
let down_outer_circle = new Button ();
let reset_button = new Button ();
do up_inner_circle.set_Text("Up");
do up_inner_circle.set_Location(
new Point(inner_circle_label_dis.get_Left(),
inner_circle_label_dis.get_Height() + inner_circle_label_dis.get_Top() + 10)
);
do down_inner_circle.set_Text("Down");
do down_inner_circle.set_Location(
new Point(up_inner_circle.get_Left(),
up_inner_circle.get_Height() + up_inner_circle.get_Top() + 10)
);
do up_outer_circle.set_Text("Up");
do up_outer_circle.set_Location(
new Point(outer_circle_label_dis.get_Left(),
outer_circle_label_dis.get_Height() + outer_circle_label_dis.get_Top() + 10)
);
do down_outer_circle.set_Text("Down");
do down_outer_circle.set_Location(
new Point(up_outer_circle.get_Left(),
up_outer_circle.get_Height() + up_outer_circle.get_Top() + 10)
);
do up_draw_point.set_Text("Up");
do up_draw_point.set_Location(
new Point(draw_circle_label_dis.get_Left(),
draw_circle_label_dis.get_Height() + draw_circle_label_dis.get_Top() + 10)
);
do down_draw_point.set_Text("Down");
do down_draw_point.set_Location(
new Point(up_draw_point.get_Left(),
up_draw_point.get_Height() + up_draw_point.get_Top() + 10)
);
do reset_button.set_Text("Reset");
do reset_button.set_Location(
new Point(up_inner_circle.get_Left(),
down_inner_circle.get_Height () + down_inner_circle.get_Top() + 10
));
# EventHandlers
let err () =
"Outer circle must be greater than or equal to Inner circle. Please change other parameters."
|> msgbox;
let up_inner_circle_event ((sender : {Object}), (e : {EventArgs})) =
do
if !rm + 10 >= !rc ->
do
rm := !rc;
err ();
end
else rm := !rm + 10;
inner_circle_label_dis.set_Text(!rm |> to_string);
redraw ();
end;
let down_inner_circle_event ((sender : {Object}), (e : {EventArgs})) =
do
if !rm > 10 -> rm := !rm - 10
else rm := 0;
inner_circle_label_dis.set_Text(!rm |> to_string);
redraw ();
end;
let up_outer_circle_event ((sender : {Object}), (e : {EventArgs})) =
do
rc := !rc + 10;
outer_circle_label_dis.set_Text(!rc |> to_string);
redraw ();
end;
let down_outer_circle_event ((sender : {Object}), (e : {EventArgs})) =
do
if !rc <= 10 -> rc := 10
else if !rm >= !rc - 10 ->
do
rc := !rm;
err ();
end
else rc := !rc - 10;
outer_circle_label_dis.set_Text(!rc |> to_string);
redraw ();
end;
let up_draw_point_event ((sender : {Object}), (e : {EventArgs})) =
do
rd := !rd + 10;
draw_circle_label_dis.set_Text(!rd |> to_string);
redraw();
end;
let down_draw_point_event ((sender : {Object}), (e : {EventArgs})) =
do
rd := !rd - 10;
draw_circle_label_dis.set_Text(!rd |> to_string);
redraw ();
end;
let reset_ev ((sender : {Object}), (e : {EventArgs})) =
do
rc := 100;
rm := 100;
rd := 100;
inner_circle_label_dis.set_Text(!rm |> to_string);
outer_circle_label_dis.set_Text(!rc |> to_string);
draw_circle_label_dis.set_Text(!rd |> to_string);
redraw ();
end;
## Set EventHandler
do up_inner_circle.add_Click (delegate EventHandler up_inner_circle_event);
do down_inner_circle.add_Click (delegate EventHandler down_inner_circle_event);
do up_outer_circle.add_Click (delegate EventHandler up_outer_circle_event);
do down_outer_circle.add_Click (delegate EventHandler down_outer_circle_event);
do up_draw_point.add_Click (delegate EventHandler up_draw_point_event);
do down_draw_point.add_Click (delegate EventHandler down_draw_point_event);
do reset_button.add_Click (delegate EventHandler reset_ev);
## Add labels and buttons to Form
do _form.get_Controls().Add(inner_circle_label);
do _form.get_Controls().Add(outer_circle_label);
do _form.get_Controls().Add(draw_circle_label);
do _form.get_Controls().Add(inner_circle_label_dis);
do _form.get_Controls().Add(outer_circle_label_dis);
do _form.get_Controls().Add(draw_circle_label_dis);
do _form.get_Controls().Add(up_inner_circle);
do _form.get_Controls().Add(down_inner_circle);
do _form.get_Controls().Add(up_outer_circle);
do _form.get_Controls().Add(down_outer_circle);
do _form.get_Controls().Add(up_draw_point);
do _form.get_Controls().Add(down_draw_point);
do _form.get_Controls().Add(reset_button);
do scene "main" {
~Draw(gr) ->
let pos = get_pos (int_to_double !rc) (int_to_double !rm) (int_to_double !rd) in
iteri (\n (x,y) ->
if n <> 360 ->
(uncurry (draw_line gr (get_pen n) x y))
(nth pos (n+1))) pos; _ -> ();
};
do show_window "main" |> ignore;
#3 おわりに
100行くらいで書けるかなと思っていたがそう甘くはなかった。
あと .NET で少し躓いたがある程度慣れたかなと。