User:Kopophex/venn.ml
From Wikipedia, the free encyclopedia
This is a program I wrote to draw venn diagrams of any degree. It is a little rough, but all the parts are there.
(* An experiment in drawing n-degree Venn diagrams. *) (* to compile: ocamlc -o venn -I +cairo bigarray.cma cairo.cma venn.ml *) (* To run: ./venn n where, n is the degree of the diagram to draw. *) open List let rec take n l = match (n,l) with 0,_ -> [] | _,h::t -> h :: take (n-1) t | _,[] -> failwith "take: empty list" let pi = 4. *. atan 1. let alpha = 0.65 let (cx,cy) = (alpha /. (sqrt 2.)), -.(alpha /. (sqrt 2.)) let draw1 ctx = Cairo.arc ctx cx cy 1.0 0.0 (2.*.pi) ; Cairo.stroke ctx let draw2 ctx = let theta = 5. *. pi /. 12. in Cairo.arc ctx (alpha *. (cos theta)) (alpha *. (sin theta)) 1.0 0.0 (2.*.pi) ; Cairo.stroke ctx let draw3 ctx = let theta = 13. *. pi /. 12. in Cairo.arc ctx (alpha *. (cos theta)) (alpha *. (sin theta)) 1.0 0.0 (2.0*.pi) ; Cairo.stroke ctx let rec draw_n_curves ctx r = function i when i <= 0. -> () | i -> Cairo.arc ctx cx cy ((1.0 +. i*.r) -. (r /. 2.0)) 0.0 (-. pi) ; Cairo.stroke ctx; Cairo.arc ctx cx cy ((1.0 -. i*.r) +. (r /. 2.0)) 0.0 (-. pi) ; Cairo.stroke ctx ; draw_n_curves ctx r (i-.1.0) let rec draw_n_right_arcs ctx r = function i when i <= 0. -> () | i -> Cairo.arc ctx (cx+.1.0) cy (((i-.1.0)*.r)+.(r/.2.0)) (-. pi) 0.0 ; Cairo.stroke ctx ; draw_n_right_arcs ctx r (i-.1.0) let rec draw_n_left_arcs ctx r x = function i when i = 0. -> Cairo.arc ctx (x+.r) cy (r/.2.0) (-. pi) 0.0 ; Cairo.stroke ctx | i -> let rec draw_arcs x = function j when j <= 0. -> () | j -> Cairo.arc ctx x cy ((r*.(j-.1.0))+.(r/.2.0)) (-. pi) 0.0 ; Cairo.stroke ctx ; draw_arcs x (j-.1.0) in draw_arcs (x+.(r*.(i/.2.0))) (i/.2.0) ; draw_n_left_arcs ctx r (x-.(r*.(i/.2.0))) (i/.2.0) let base_r = 1.5 let draw_n ctx n = let i = 2.0 ** ((float_of_int n) -. 1.0) in let r = base_r /. 2.0 ** (float_of_int n) in draw_n_curves ctx r i ; draw_n_right_arcs ctx r i ; draw_n_left_arcs ctx r (cx-.1.0) i let rec draw ctx colors = function 0 -> () | i -> let (r,g,b,a) = (hd colors) in Cairo.set_source_rgba ctx r g b a ; (match i with 1 -> draw1 ctx | 2 -> draw2 ctx | 3 -> draw3 ctx | _ -> draw_n ctx (i-3)) ; draw ctx (tl colors) (i-1) let () = let n = int_of_string Sys.argv.(1) in let colors = rev (take n [ (0.0,0.0,0.0,1.0); (0.0,0.0,0.0,1.0); (0.0,0.0,0.0,1.0); (6.0,0.0,0.0,1.0); (0.0,6.0,0.0,1.0); (0.0,0.0,6.0,1.0) ]) in let (width,height) = (600,530) in let (fwidth,fheight) = (float_of_int width, float_of_int height) in let scale = 160. in let file = open_out "out.svg" in let surface = Cairo_svg.surface_create_for_channel file 650.0 520.0 in let ctx = Cairo.create surface in Cairo.translate ctx (fwidth/.2.) (fheight/.2.) ; Cairo.scale ctx scale (-.scale) ; Cairo.set_line_width ctx (2.0/.scale) ; draw ctx colors n ; Cairo.surface_finish surface