(* Algorithme de dessin de chryzodes *) open Big_int;; (* Pi *) let pi = 4. *. atan 1. (* Chryzodes: renvoie des couples de points du cercle *) let chryzodes puissance npoints = let rec chryzodes points dejafait n pt = if List.mem pt dejafait then points else let next = int_of_big_int (mod_big_int (power_int_positive_int puissance n) (big_int_of_int npoints)) in chryzodes ((pt, next) :: points) (pt :: dejafait) (n + 1) next in let rec p = function | n when truncate(float puissance ** float n) > npoints -> n | n -> p (n + 1) in let li = chryzodes [] [] (p 0) puissance in List.tl (List.rev li) (* Dessin des chryzodes à partir d'une liste de coordonnées de points *) let rec draw ctx npoints coords = function | [] -> () | (pt1, pt2) :: tl -> let x1, y1 = coords.(pt1) in let x2, y2 = coords.(pt2) in Cairo.move_to ctx x1 y1; Cairo.line_to ctx x2 y2; Cairo.close_path ctx; Cairo.stroke ctx; draw ctx npoints coords tl (* Génère les coordonnées des points *) let gencoords npoints rayon = Array.init npoints (fun n -> cos (float n *. (2. *. pi /. float npoints)) *. rayon +. rayon, sin (float n *. (2. *. pi /. float npoints)) *. rayon +. rayon) (* Point d'entrée *) let _ = (* Prise d'informations *) let size, puissance, npoints = Scanf.scanf "%d %d %d" (fun a b c -> a, b, c) in (* Initialisation de Cairo *) let surface = Cairo.image_surface_create Cairo.FORMAT_ARGB32 ~width:size ~height:size in let ctx = Cairo.create surface in Cairo.set_line_width ctx 2.; (* Cercle *) let beuh = (float size /. 2.) in Cairo.arc ctx ~xc:beuh ~yc:beuh ~radius:beuh ~angle1:0. ~angle2:(2. *. pi); (* Dessin *) Cairo.set_operator ctx Cairo.OPERATOR_XOR; draw ctx npoints (gencoords npoints (float size /. 2.)) (chryzodes puissance npoints); Cairo.close_path ctx; Cairo.stroke ctx; (* Sortie *) Cairo_png.surface_write_to_file surface "chryzodes.png"