From 0a91567ed6acadaff1d81eb57f083c0f384d9107 Mon Sep 17 00:00:00 2001 From: Ganesh Narayanan <95270674+ganeshn-gh@users.noreply.github.com> Date: Mon, 11 Mar 2024 18:15:12 +0530 Subject: [PATCH 1/3] Add a smiling emoji example using different shapes (#124) --- examples/dune | 6 ++++++ examples/smile.ml | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 examples/smile.ml diff --git a/examples/dune b/examples/dune index 47a75b9..c9927ac 100644 --- a/examples/dune +++ b/examples/dune @@ -122,3 +122,9 @@ (name fill_rect) (modules fill_rect) (libraries joy)) + +(executable + (name smile) + (modules smile) + (libraries joy)) + \ No newline at end of file diff --git a/examples/smile.ml b/examples/smile.ml new file mode 100644 index 0000000..89ca1d3 --- /dev/null +++ b/examples/smile.ml @@ -0,0 +1,27 @@ +open Joy + +let make_nose () = + let l = line (point 0 50)|> translate 0 (-25) in + let l1 = l in + let l2 = l |> rotate 90|> translate 0 (-25) in + let nose = complex [l1; l2] in + nose + +let make_arc rx ry = + let r = rectangle ~c:(point 0 (ry / 2)) (2 * rx) ry in + let col = r |> with_fill white |> with_stroke white in + let e = ellipse ~c:(point 0 0) rx ry in + complex [e; col] + +let () = + init (); + let a = circle 200 in + let d = circle ~c:(point 50 50) 20 in + let b = circle ~c:(point (-50) 50) 20 in + let nose = make_nose () in + let leb = make_arc 26 14 |> rotate 180 |> translate 50 70 in + let reb = make_arc 26 14 |> rotate 180 |> translate (-50) 70 in + let mouth = make_arc 80 40 |>translate 0 (-60) in + show [mouth;leb;reb;a;d;b;nose]; + write () + From 726e7b85b24c7103d5f3c5335c00d26963a50442 Mon Sep 17 00:00:00 2001 From: Puneeth Chaganti Date: Mon, 11 Mar 2024 18:23:09 +0530 Subject: [PATCH 2/3] Add a dependency on the base library --- joy.opam | 1 + 1 file changed, 1 insertion(+) diff --git a/joy.opam b/joy.opam index c5bfbd8..632ce28 100644 --- a/joy.opam +++ b/joy.opam @@ -12,6 +12,7 @@ depends: [ "dune" {>= "3.10"} "graphics" "cairo2" + "base" "odoc" {with-doc} ] build: [ From 48e067e481553aee30b94cab477678c6c18aa649 Mon Sep 17 00:00:00 2001 From: Puneeth Chaganti Date: Tue, 12 Mar 2024 12:02:53 +0530 Subject: [PATCH 3/3] Fix ellipse rotation to work correctly (#126) * Fix ellipse rotation to work correctly Previously, we only rotated the center of the ellipse, similar to the circle. This commit adds a rotation field to the ellipse shape type which stores the rotation of the ellipse in radians. And we use Cairo's rotate function when rendering the ellipse. Fixes #116 along with #121. * Add example with ellipse rotation --- examples/dune | 6 +++++- examples/rotate_ellipse.ml | 15 +++++++++++++++ lib/render.ml | 3 ++- lib/shape.ml | 3 ++- lib/shape.mli | 1 + lib/transform.ml | 7 ++++++- lib/util.ml | 1 + lib/util.mli | 1 + 8 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 examples/rotate_ellipse.ml diff --git a/examples/dune b/examples/dune index c9927ac..535d5cc 100644 --- a/examples/dune +++ b/examples/dune @@ -48,6 +48,11 @@ (modules rotate) (libraries joy)) +(executable + (name rotate_ellipse) + (modules rotate_ellipse) + (libraries joy)) + (executable (name line) (modules line) @@ -127,4 +132,3 @@ (name smile) (modules smile) (libraries joy)) - \ No newline at end of file diff --git a/examples/rotate_ellipse.ml b/examples/rotate_ellipse.ml new file mode 100644 index 0000000..57b7eb4 --- /dev/null +++ b/examples/rotate_ellipse.ml @@ -0,0 +1,15 @@ +open Joy + +let max = 32. +let rec range a b = if a > b then [] else a :: range (a +. 1.) b + +let _ = + init (); + let rect = rectangle 100 50 |> translate 195 220 in + let ell = ellipse 100 50 |> translate 60 60 in + let nums = range 0. max in + let rotated = + List.map (fun i -> rotate (int_of_float (i /. max *. 360.0)) ell) nums + in + show (rect :: rotated); + write ~filename:"rotate_ellipse.png" () diff --git a/lib/render.ml b/lib/render.ml index 42a7cbc..fc2ab0a 100644 --- a/lib/render.ml +++ b/lib/render.ml @@ -16,7 +16,7 @@ let draw_circle ctx ({ c; radius; stroke; fill } : circle) = Option.iter fill_circle fill; Cairo.Path.clear ctx.ctx -let draw_ellipse ctx { c; rx; ry; stroke; fill } = +let draw_ellipse ctx { c; rx; ry; stroke; fill; rotation } = let stroke_ellipse stroke = set_color stroke; Cairo.stroke_preserve ctx.ctx @@ -31,6 +31,7 @@ let draw_ellipse ctx { c; rx; ry; stroke; fill } = (* Translate and scale to create an ellipse from a circle *) Cairo.translate ctx.ctx c.x (Float.neg c.y); + Cairo.rotate ctx.ctx rotation; Cairo.scale ctx.ctx rx ry; Cairo.arc ctx.ctx 0. 0. ~r:1. ~a1:0. ~a2:(2. *. Float.pi); diff --git a/lib/shape.ml b/lib/shape.ml index d46f947..080ac34 100644 --- a/lib/shape.ml +++ b/lib/shape.ml @@ -13,6 +13,7 @@ type ellipse = { c : float point; rx : float; ry : float; + rotation : float; stroke : color option; fill : color option; } @@ -55,7 +56,7 @@ let rectangle ?(c = center) width height = let ellipse ?(c = center) rx ry = let rx, ry = (float_of_int rx, float_of_int ry) in - Ellipse { c; rx; ry; stroke = Some Color.black; fill = None } + Ellipse { c; rx; ry; stroke = Some Color.black; fill = None; rotation = 0. } let line ?(a = center) b = Line { a; b; stroke = Color.black } diff --git a/lib/shape.mli b/lib/shape.mli index 692a488..dcd4e95 100644 --- a/lib/shape.mli +++ b/lib/shape.mli @@ -12,6 +12,7 @@ type ellipse = { c : float point; rx : float; ry : float; + rotation : float; stroke : color option; fill : color option; } diff --git a/lib/transform.ml b/lib/transform.ml index b2850ce..bfc27f4 100644 --- a/lib/transform.ml +++ b/lib/transform.ml @@ -82,7 +82,12 @@ let rotate_point degrees point = let rec rotate degrees = function | Circle circle' -> Circle { circle' with c = rotate_point degrees circle'.c } | Ellipse ellipse' -> - Ellipse { ellipse' with c = rotate_point degrees ellipse'.c } + Ellipse + { + ellipse' with + c = rotate_point degrees ellipse'.c; + rotation = ellipse'.rotation +. to_radians degrees; + } | Line line' -> Line { line' with a = rotate_point degrees line'.a; b = rotate_point degrees line'.b } | Polygon polygon' -> Polygon diff --git a/lib/util.ml b/lib/util.ml index ec23ded..ffd8e19 100644 --- a/lib/util.ml +++ b/lib/util.ml @@ -36,3 +36,4 @@ let rec partition n ?(step = 0) lst = (* Misc *) let range n = List.init n Fun.id +let to_radians degrees = degrees *. Stdlib.Float.pi /. 180. diff --git a/lib/util.mli b/lib/util.mli index 74cadbd..c892687 100644 --- a/lib/util.mli +++ b/lib/util.mli @@ -10,3 +10,4 @@ val ( >> ) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c val take : int -> 'a list -> 'a list * 'a list val partition : int -> ?step:int -> 'a list -> 'a list list val range : int -> int list +val to_radians : float -> float