LoginSignup
1
1

More than 5 years have passed since last update.

Mokkosuで内トロコイド

Last updated at Posted at 2015-03-17

「(本名)くん、Mokkosu を書こうよ」
というわけで Mokkosu 内トロコイドを書くことになった。

1 作ってみた

trochoid.jpg

実装したのは以下の機能
・ 内側、外側、描画点のサイズの変更
・ 各サイズのリセット
・ カラフルな線

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 で少し躓いたがある程度慣れたかなと。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1