Это может быть простым в использовании graphviz сделать фактический рисунок. Он автоматически рисует график из списка узлов и ребер, что и является вашим входом. Функция fmt_transition
генерирует один ребро, функция fmt_transitions
поднимает его через pp_print_list в списки переходов и завертывает его в правильный заголовок.
let fmt_transition fmt (inedge,by,outedge) =
Format.fprintf fmt "@[%d -> %d [label=\"%c\"];@]" inedge outedge by
let fmt_transitions fmt =
Format.fprintf fmt "@[<v 2>digraph output {@,%[email protected],@]}@,@."
(Format.pp_print_list fmt_transition)
Если попробовать на некоторых тестовых данных, мы получаем тестовый файл, который мы хотели:
let test1 = [ (1,'a',2); (2,'b',1); (1,'b',1)] in
fmt_transitions Format.std_formatter test1;;
результаты в:
digraph output
{
1 -> 2 [label="a"];
2 -> 1 [label="b"];
1 -> 1 [label="b"];
}
Вызов GraphViz является:
dot -T pdf -o output.pdf < input.dot
Если вы вызываете это прямо из ocaml, вы можете также перенесите данные непосредственно в точку, не записывая их сначала на диск.
В качестве альтернативы, вы можете также использовать внешнюю программу просмотр, как ГВ:
let call_dot data =
let cmd = "dot -Tps | gv -" in
let (sout, sin, serr) as channels =
Unix.open_process_full cmd (Unix.environment()) in
let fmt = Format.formatter_of_out_channel sin in
Format.fprintf fmt "%[email protected]" fmt_transitions data;
channels
let cleanup channels =
(* missing: flush channels, empty buffers *)
Unix.close_process_full channels
Вызов call_dot test1 |> cleanup
будет посылать данные точки и открытой Ghostview. Чтобы не допустить предела открытых файлов, один крик ждет завершения процесса и закрытия каналов, что делается в cleanup
.
Если вы хотите использовать библиотеку изображений вместо этого, вы можете заменить определение cmd на «dot -Tpng» и прочитать данные изображения из stdin перед вызовом очистки.
Я знаю, что проще использовать graphviz, но есть способ, чтобы я мог использовать только графический модуль ocaml, возможно, с рекурсивной функцией, которая действует на элементы списка или может быть более одной функции –
, а также я бы например, я не нашел способ вывода файла, сгенерированного ocaml из ocaml. –
. Как вы продолжаете, зависит от ваших дальнейших планов - для статических данных может быть достаточно многоточия вывода точек в evince/ghostview. Если вам нужен пользовательский интерфейс, вы можете создать образ вместо него и использовать привязки gtk ocaml. Также есть [ocamlgraph] (https://github.com/backtracking/ocamlgraph), но у меня нет опыта с ним. В худшем случае вы можете использовать вывод аннотации для графического объекта, чтобы найти хорошее размещение для узлов, а остальные - с помощью функций рисования с низким уровнем в холсте gdk. –