How to resolve the algorithm Dragon curve step by step in the OCaml programming language
How to resolve the algorithm Dragon curve step by step in the OCaml programming language
Table of Contents
Problem Statement
Create and display a dragon curve fractal. (You may either display the curve directly or write it to an image file.)
Here are some brief notes the algorithms used and how they might suit various languages. This always has F at even positions and S at odd. Eg. after 3 levels F_S_F_S_F_S_F_S. The +/- turns in between bend to the left or right the same as the "successive approximation" method above. Read more at for instance Joel Castellanos' L-system page. Variations are possible if you have only a single symbol for line draw, for example the Icon and Unicon and Xfractint code. The angles can also be broken into 45-degree parts to keep the expansion in a single direction rather than the endpoint rotating around. The string rewrites can be done recursively without building the whole string, just follow its instructions at the target level. See for example C by IFS Drawing code. The effect is the same as "recursive with parameter" above but can draw other curves defined by L-systems.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Dragon curve step by step in the OCaml programming language
Source code in the ocaml programming language
(* This constant does not seem to be defined anywhere in the standard modules *)
let pi = acos (-1.0);
(*
** CLASS dragon_curve_computer:
** ----------------------------
** Computes the coordinates for the line drawing the curve.
** - initial_x initial_y: coordinates for starting point for curve
** - total_length: total length for the curve
** - total_splits: total number of splits to perform
*)
class dragon_curve_computer initial_x initial_y total_length total_splits =
object(self)
val mutable current_x = (float_of_int initial_x) (* current x coordinate in curve *)
val mutable current_y = (float_of_int initial_y) (* current y coordinate in curve *)
val mutable current_angle = 0.0 (* current angle *)
(*
** METHOD compute_coords:
** ----------------------
** Actually computes the coordinates in the line for the curve
** - length: length for current iteration
** - nb_splits: number of splits to perform for current iteration
** - direction: direction for current line (-1.0 or 1.0)
** Returns: the list of coordinates for the line in this iteration
*)
method compute_coords length nb_splits direction =
(* If all splits have been done *)
if nb_splits = 0
then
begin
(* Draw line segment, updating current coordinates *)
current_x <- current_x +. length *. cos current_angle;
current_y <- current_y +. length *. sin current_angle;
[(int_of_float current_x, int_of_float current_y)]
end
(* If there are still splits to perform *)
else
begin
(* Compute length for next iteration *)
let sub_length = length /. sqrt 2.0 in
(* Turn 45 degrees to left or right depending on current direction and draw part
of curve in this direction *)
current_angle <- current_angle +. direction *. pi /. 4.0;
let coords1 = self#compute_coords sub_length (nb_splits - 1) 1.0 in
(* Turn 90 degrees in the other direction and draw part of curve in that direction *)
current_angle <- current_angle -. direction *. pi /. 2.0;
let coords2 = self#compute_coords sub_length (nb_splits - 1) (-1.0) in
(* Turn back 45 degrees to set head in the initial direction again *)
current_angle <- current_angle +. direction *. pi /. 4.0;
(* Concatenate both sub-curves to get the full curve for this iteration *)
coords1 @ coords2
end
(*
** METHOD get_coords:
** ------------------
** Returns the coordinates for the curve with the parameters set in the object initializer
*)
method get_coords = self#compute_coords total_length total_splits 1.0
end;;
(*
** MAIN PROGRAM:
** =============
*)
let () =
(* Curve is displayed in a Tk canvas *)
let top=Tk.openTk() in
let c = Canvas.create ~width:400 ~height:400 top in
Tk.pack [c];
(* Create instance computing the curve coordinates *)
let dcc = new dragon_curve_computer 100 200 200.0 16 in
(* Create line with these coordinates in canvas *)
ignore (Canvas.create_line ~xys: dcc#get_coords c);
Tk.mainLoop ();
;;
let zig (x1,y1) (x2,y2) = (x1+x2+y1-y2)/2, (x2-x1+y1+y2)/2
let zag (x1,y1) (x2,y2) = (x1+x2-y1+y2)/2, (x1-x2+y1+y2)/2
let rec dragon p1 p2 p3 n =
if n = 0 then [p1;p2] else
(dragon p1 (zig p1 p2) p2 (n-1)) @ (dragon p2 (zag p2 p3) p3 (n-1))
let _ =
let top = Tk.openTk() in
let c = Canvas.create ~width:430 ~height:300 top in
Tk.pack [c];
let p1, p2 = (100, 100), (356,100) in
let points = dragon p1 (zig p1 p2) p2 15 in
ignore (Canvas.create_line ~xys: points c);
Tk.mainLoop ()
You may also check:How to resolve the algorithm Chowla numbers step by step in the Haskell programming language
You may also check:How to resolve the algorithm Nested function step by step in the Clojure programming language
You may also check:How to resolve the algorithm Count the coins step by step in the EchoLisp programming language
You may also check:How to resolve the algorithm Strip a set of characters from a string step by step in the Erlang programming language
You may also check:How to resolve the algorithm Wasteful, equidigital and frugal numbers step by step in the F# programming language