Skip to content

Commit

Permalink
refactored to fix type issues, added more comments, parameter tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
FayCarsons committed Nov 21, 2023
1 parent 1ca1e2e commit dd3127e
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 38 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
_build
.vscode
.vscode
.DS_Store
76 changes: 40 additions & 36 deletions examples/circle_packing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,60 @@ open Joy.Shape

(* global constants // RNG initialization *)
let resolution = (1200, 900)
let min_radius = 10
let max_radius = 200
let num_circles = 5000
let max_attempts = 50000
let _ = Stdlib.Random.self_init
let min_radius = 20
let max_radius = 150
let num_circles = 5_000
let max_attempts = 100_000
let shrink_factor = 0.85
let _ = Stdlib.Random.self_init ()

let palette =
[
(* purple *)
(107, 108, 163);
(* light blue *)
(135, 188, 189);
(* green *)
(111, 153, 84);
(* light purple *)
(150, 155, 199);
(* light green *)
(137, 171, 124);
(* dark purple *)
(67, 68, 117);
(* darker purple *)
(44, 45, 84);
]

(* utility Functions *)
let distance ({ x = x1; y = y1 } : point) ({ x = x2; y = y2 } : point) =

(* distance between two points *)
let distance (x1, y1) (x2, y2) =
let dx = float_of_int x2 -. float_of_int x1 in
let dy = float_of_int y2 -. float_of_int y1 in
let dist = sqrt ((dx *. dx) +. (dy *. dy)) in
int_of_float dist

(* determines if two circles overlap *)
let overlap ({ c = c1; radius = r1 } : circle)
({ c = c2; radius = r2 } : circle) =
let dist = distance c1 c2 in
(* determines if two circles overlaps *)
let overlaps (p1, r1) (p2, r2) =
let dist = distance p1 p2 in
dist < r1 + r2

(* creates a random point within screen bounds *)
let rand_point () =
{
x = Stdlib.Random.full_int (fst resolution * 2) - fst resolution;
y = Stdlib.Random.full_int (snd resolution * 2) - snd resolution;
}
( Stdlib.Random.full_int (fst resolution * 2) - fst resolution,
Stdlib.Random.full_int (snd resolution * 2) - snd resolution )

(* creates a circle with a random center point and radius *)
let rand_circle () =
let point = rand_point () in
{
c = point;
radius = min_radius + Stdlib.Random.full_int (max_radius - min_radius);
}
(point, min_radius + Stdlib.Random.full_int (max_radius - min_radius))

(* creates a lis of packed circles *)
let pack_circles () =
(* checks whether a circle intersects with a list of circles *)
let check_overlap lst current =
List.fold_right (fun curr acc -> overlap curr current || acc) lst false
let check_overlaps lst current =
List.fold_right (fun curr acc -> overlaps curr current || acc) lst false
in
(* creates a new circle, checks if it intersects previous circles,
if max attempts have been reached,
Expand All @@ -59,14 +64,14 @@ let pack_circles () =
or returns the list of circles *)
let rec pack lst attempts =
let new_circle = rand_circle () in
let does_overlap = check_overlap lst new_circle in
let does_overlap = check_overlaps lst new_circle in
let safe = List.length lst < num_circles - 1 && attempts < max_attempts in
if does_overlap && safe then pack lst (attempts + 1)
else if not safe then new_circle :: lst
else pack (new_circle :: lst) attempts
in
let attempts = 0 in
let lst = [ { c = { x = 0; y = 0 }; radius = 10 } ] in
let lst = [ rand_circle () ] in
pack lst attempts

(* pulls a random color from the 'palette' list
Expand All @@ -76,30 +81,29 @@ let draw_with_color circle =
let idx = Stdlib.Random.full_int (List.length palette - 1) in
let r, g, b = List.nth palette idx in
Graphics.set_color (Graphics.rgb r g b);
Graphics.draw_circle circle.c.x circle.c.y circle.radius
render_shape circle

(* turns a circle into a list of concentric circles *)
let make_concentric circle =
let rec choose lst =
let first = List.hd (List.rev lst) in
if first.radius <= 1 then lst
let rec shrink lst =
let point, radius = List.hd (List.rev lst) in
if radius <= 1 then lst
else
let new_circle =
{
c = first.c;
radius =
int_of_float
(float_of_int first.radius *. 0.9);
}
(point, int_of_float (float_of_int radius *. shrink_factor))
in
choose (lst @ [ new_circle ])
shrink (lst @ [ new_circle ])
in
choose [ circle ]
shrink [ circle ]

(* main fn *)
let () =
set_dimensions (fst resolution) (snd resolution);
init ();
Graphics.set_line_width 4;
Graphics.set_line_width 3;
let circles = pack_circles () in
let circles = List.flatten (List.map make_concentric circles) in
List.iter draw_with_color circles;
List.iter
(fun ((x, y), radius) -> draw_with_color (circle ~x ~y radius))
circles;
close ()
1 change: 0 additions & 1 deletion lib/shape.mli
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
type shape
type shapes = shape list
type point = { x : int; y : int }
type circle = { c : point; radius : int }

val render_shape : shape -> unit
val circle : ?x:int -> ?y:int -> int -> shape
Expand Down

0 comments on commit dd3127e

Please sign in to comment.