ocaml_project/src/gfile.ml

119 lines
3 KiB
OCaml

open Graph
open Printf
type path = string
(* Format of text files:
% This is a comment
% A node with its coordinates (which are not used).
n 88.8 209.7
n 408.9 183.0
% The first node has id 0, the next is 1, and so on.
% Edges: e source dest label
e 3 1 11
e 0 2 8
*)
let write_file path graph =
(* Open a write-file. *)
let ff = open_out path in
(* Write in this file. *)
fprintf ff "%% This is a graph.\n\n" ;
(* Write all nodes (with fake coordinates) *)
n_iter_sorted graph (fun id -> fprintf ff "n %.1f 1.0\n" (float_of_int id)) ;
fprintf ff "\n" ;
(* Write all arcs *)
e_iter graph (fun id1 id2 lbl -> fprintf ff "e %d %d %s\n" id1 id2 lbl) ;
fprintf ff "\n%% End of graph\n" ;
close_out ff ;
()
(* Reads a line with a node. *)
let read_node id graph line =
try Scanf.sscanf line "n %f %f" (fun _ _ -> new_node graph id)
with e ->
Printf.printf "Cannot read node in line - %s:\n%s\n%!" (Printexc.to_string e) line ;
failwith "from_file"
(* Ensure that the given node exists in the graph. If not, create it.
* (Necessary because the website we use to create online graphs does not generate correct files when some nodes have been deleted.) *)
let ensure graph id = if node_exists graph id then graph else new_node graph id
(* Reads a line with an arc. *)
let read_arc graph line =
try Scanf.sscanf line "e %d %d %s"
(fun id1 id2 label -> new_arc (ensure (ensure graph id1) id2) id1 id2 label)
with e ->
Printf.printf "Cannot read arc in line - %s:\n%s\n%!" (Printexc.to_string e) line ;
failwith "from_file"
(* Reads a comment or fail. *)
let read_comment graph line =
try Scanf.sscanf line " %%" graph
with _ ->
Printf.printf "Unknown line:\n%s\n%!" line ;
failwith "from_file"
let from_file path =
let infile = open_in path in
(* Read all lines until end of file.
* n is the current node counter. *)
let rec loop n graph =
try
let line = input_line infile in
(* Remove leading and trailing spaces. *)
let line = String.trim line in
let (n2, graph2) =
(* Ignore empty lines *)
if line = "" then (n, graph)
(* The first character of a line determines its content : n or e. *)
else match line.[0] with
| 'n' -> (n+1, read_node n graph line)
| 'e' -> (n, read_arc graph line)
(* It should be a comment, otherwise we complain. *)
| _ -> (n, read_comment graph line)
in
loop n2 graph2
with End_of_file -> graph (* Done *)
in
let final_graph = loop 0 empty_graph in
close_in infile ;
final_graph
(* Write the graph in a .dot file*)
let export path graph =
(* Open a write-file. *)
let ff = open_out (path^".dot") in
(* Write in this file. *)
fprintf ff "digraph graphique1 {\n\tsize=\"20\"\n\tnode [shape = circle];\n";
(* Write all arcs *)
e_iter graph (fun id1 id2 lbl -> fprintf ff "\t%d -> %d [ label = \"%s\" ];\n" id1 id2 lbl) ;
fprintf ff "}\n" ;
close_out ff ;
()