package ocamlgraph
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
A generic graph library for OCaml
Install
dune-project
Dependency
Authors
Maintainers
Sources
ocamlgraph-2.0.0.tbz
sha256=20fe267797de5322088a4dfb52389b2ea051787952a8a4f6ed70fcb697482609
sha512=c4973ac03bdff52d1c8a1ed01c81e0fbe2f76486995e57ff4e4a11bcc7b1793556139d52a81ff14ee8c8de52f1b40e4bd359e60a2ae626cc630ebe8bccefb3f1
doc/src/ocamlgraph/xDot.ml.html
Source file xDot.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372(**************************************************************************) (* *) (* This file is part of OcamlGraph. *) (* *) (* Copyright (C) 2009-2010 *) (* CEA (Commissariat � l'�nergie Atomique) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) (* Foundation, version 2.1, with a linking exception. *) (* *) (* It is distributed in the hope that it will be useful, *) (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) (* See the file ../LICENSE for more details. *) (* *) (* Authors: *) (* - Julien Signoles (Julien.Signoles@cea.fr) *) (* - Jean-Denis Koeck (jdkoeck@gmail.com) *) (* - Benoit Bataille (benoit.bataille@gmail.com) *) (* *) (**************************************************************************) (** Reading XDot files *) open Dot_ast open Printf (* Layout types *) (* This file is responsible for converting the coordinates from dot coordinates to GnomeCanvas world coordinates. The matrix transformation to apply is: (1 0) (0 -1) Care must be taken to exchange max and min values on the y axis. Outside this module all coordinates are assumed to be in canvas world coordinates. *) type pos = float * float (* coordinates *) type bounding_box = pos * pos (* bounding box *) type node_layout = { n_name : string; n_pos : pos; n_bbox : bounding_box; n_draw : XDotDraw.operation list; n_ldraw : XDotDraw.operation list; } type cluster_layout = { c_pos : pos; c_bbox : bounding_box; c_draw : XDotDraw.operation list; c_ldraw : XDotDraw.operation list; } type edge_layout = { e_draw : XDotDraw.operation list; e_ldraw : XDotDraw.operation list; e_hdraw : XDotDraw.operation list; e_tdraw : XDotDraw.operation list; e_hldraw : XDotDraw.operation list; e_tldraw : XDotDraw.operation list; } let mk_node_layout ~name ~pos ~bbox ~draw ~ldraw = { n_name = name; n_pos = pos; n_bbox = bbox; n_draw = draw; n_ldraw = ldraw } let mk_cluster_layout ~pos ~bbox ~draw ~ldraw = { c_pos = pos; c_bbox = bbox; c_draw = draw; c_ldraw = ldraw } let mk_edge_layout ~draw ~ldraw ~hdraw ~tdraw ~hldraw ~tldraw = { e_draw = draw; e_ldraw = ldraw; e_hdraw = hdraw; e_tdraw = tdraw; e_hldraw = hldraw; e_tldraw = tldraw; } exception ParseError of string (* MISCELLANEOUS FUNCTIONS *) let read_pos s = Scanf.sscanf s "%f,%f" (fun x y -> x, -.y) let bounding_box (x, y) w h = let lower_left = x -. w , y -. h in let upper_right = x+.w,y+.h in lower_left,upper_right let get_dot_string = function | Dot_ast.String s -> s | Dot_ast.Ident s -> s | Dot_ast.Number s -> s | Dot_ast.Html s -> s (* READING VERTEX LAYOUTS *) (** Finds the attributes [pos], [width] and [height] of a node in the attribute list *) let read_common_layout mk_layout attr_list = (* Iter on the attributes *) (* shape, position, width, height, color, filled *) let fold ((p,w,h, draw,ldraw) as attrs) = function | (Dot_ast.Ident "pos"), Some (Dot_ast.String s) -> (Some s), w, h, draw,ldraw | (Dot_ast.Ident "width"), Some (Dot_ast.String s) -> p, (Some s), h, draw,ldraw | (Dot_ast.Ident "height"), Some (Dot_ast.String s) -> p, w, (Some s), draw,ldraw | (Dot_ast.Ident "_draw_"), Some (Dot_ast.String draw) -> p,w,h, XDotDraw.parse draw, ldraw | (Dot_ast.Ident "_ldraw_"), Some (Dot_ast.String ldraw) -> p,w,h, draw, XDotDraw.parse ldraw | _ -> attrs in let fold_attr acc attr_list = List.fold_left fold acc attr_list in let attrs = List.fold_left fold_attr (None, None, None, [], []) attr_list in (* Check if we have position, width and height *) match attrs with | Some pos, Some w, Some h, draw,ldraw-> let pos = read_pos pos in let coord = bounding_box pos (float_of_string w) (-.(float_of_string h)) in (* Return the node model *) mk_layout ~pos ~bbox:coord ~draw ~ldraw | _,_,_, draw, ldraw -> let pos = (0.,0.) in let bbox = (0.,0.),(0.,0.) in mk_layout ~pos ~bbox ~draw ~ldraw let read_node_layout (id,_) attrs = let f = read_common_layout (fun ~pos ~bbox ~draw ~ldraw -> mk_node_layout ~pos ~bbox ~draw ~ldraw) attrs in f ~name:(get_dot_string id) let read_cluster_layout = read_common_layout mk_cluster_layout (* READING EDGE LAYOUTS *) (** Reads the spline control points of a curve in an xdot file example : "c 5 -black B 4 65 296 65 288 65 279 65 270 " *) (* The edge drawing operations are in the following attributes : _hdraw_ Head arrowhead _tdraw_ Tail arrowhead _hldraw_ Head label _tldraw_ Tail label *) (** Gets the layout of an edge out of the dot ast *) let read_edge_layout attr_list = let draw = ref [] in let ldraw = ref [] in let hdraw = ref [] in let tdraw = ref [] in let hldraw = ref [] in let tldraw = ref [] in let fill_draw_ops = function | (Dot_ast.Ident "_draw_"), Some (Dot_ast.String s) -> draw := XDotDraw.parse s | (Dot_ast.Ident "_ldraw_"), Some (Dot_ast.String s) -> ldraw := XDotDraw.parse s | (Dot_ast.Ident "_hdraw_"), Some (Dot_ast.String s) -> hdraw := XDotDraw.parse s | (Dot_ast.Ident "_tdraw_"), Some (Dot_ast.String s) -> tdraw := XDotDraw.parse s | (Dot_ast.Ident "_hldraw_"), Some (Dot_ast.String s) -> hldraw := XDotDraw.parse s | (Dot_ast.Ident "_tldraw_"), Some (Dot_ast.String s) -> tldraw := XDotDraw.parse s | _ -> () in List.iter (List.iter fill_draw_ops) attr_list; let draw, ldraw = !draw, !ldraw in let hdraw, tdraw, hldraw, tldraw = !hdraw, !tdraw, !hldraw, !tldraw in mk_edge_layout ~draw ~ldraw ~hdraw ~tdraw ~hldraw ~tldraw (* Computes the bounding box *) let read_bounding_box str = let x1,y1,x2,y2 = Scanf.sscanf str "%f,%f,%f,%f" (fun a b c d -> a,b,c,d) in (* Convert coordinates to the world canvas coordinates *) let lower_left = (x1, -.y2) and upper_right = x2, -.y1 in lower_left,upper_right module Make(G : Graphviz.GraphWithDotAttrs) = struct module HV = Hashtbl.Make(G.V) (* cannot use an hashtable because no hash function for edges *) module HE = Map.Make (struct type t = G.E.t let compare = G.E.compare end) module HT = Hashtbl.Make (Util.HTProduct (Util.HTProduct(G.V)(G.V)) (struct type t = string let equal = (=) let hash = Hashtbl.hash end)) type graph_layout = { vertex_layouts : node_layout HV.t; edge_layouts : edge_layout HE.t; cluster_layouts : (string, cluster_layout) Hashtbl.t; bbox : bounding_box } exception Found of string let get_edge_comment e = let al = G.edge_attributes e in try List.iter (function `Comment c -> raise (Found c) | _ -> ()) al; None with Found c -> Some c let get_dot_comment (al : Dot_ast.attr list) = try List.iter (List.iter (function | Ident "comment", Some c -> raise (Found (get_dot_string c)) | _ -> ())) al; "" with Found c -> c let strip_quotes = function | "" -> "" | s -> let len = String.length s in if s.[0] = '"' && s.[len -1] = '"' then String.sub s 1 (len - 2) else s (* Parses the graph attribute named id, and converts it with conv *) let parse_graph_attr id conv stmts = let read_attr = function | Ident ident , Some (String attr) when ident = id -> raise (Found attr) | _ -> () in let read_stmt = function | Attr_graph attrs -> List.iter (List.iter read_attr) attrs | _ -> () in try List.iter read_stmt stmts; failwith ("Could not find the graph attribute named " ^ id) with Found attr -> conv attr let parse_bounding_box = parse_graph_attr "bb" read_bounding_box (*let parse_bgcolor = parse_graph_attr "bgcolor" XDotDraw.normalize_color*) let parse_layouts g stmts = let name_to_vertex = Hashtbl.create 97 in let vertices_comment_to_edge = HT.create 97 in let vertex_layouts = HV.create 97 in let edge_layouts = ref HE.empty in let cluster_layouts = Hashtbl.create 97 in G.iter_vertex (fun v -> let name = strip_quotes (G.vertex_name v) in Hashtbl.add name_to_vertex name v) g; G.iter_edges_e (fun e -> let comment = match get_edge_comment e with | Some c -> strip_quotes c | None -> "" in let vs = G.E.src e, G.E.dst e in HT.add vertices_comment_to_edge (vs, comment) e) g; let find_vertex (id,_) = let name = get_dot_string id in try Hashtbl.find name_to_vertex name with Not_found -> failwith ("Could not find vertex named " ^ name) in let find_edge v v' comment = try HT.find vertices_comment_to_edge ((v, v'), comment) with Not_found -> (* Printf.printf "Did not find edge from %s to %s with comment %s\n" (G.vertex_name v) (G.vertex_name v') (match comment with Some c -> c | None -> "none");*) raise Not_found in let rec collect_layouts cluster stmt = try match stmt with | Node_stmt (node_id, al) -> let v = find_vertex node_id in HV.add vertex_layouts v (read_node_layout node_id al) | Edge_stmt (NodeId id, [NodeId id'], al) -> let v = find_vertex id in let v' = find_vertex id' in let comment = get_dot_comment al in let e = find_edge v v' comment in edge_layouts := HE.add e (read_edge_layout al) !edge_layouts | Subgraph (SubgraphDef (Some id, stmts)) -> let cluster = get_dot_string id in List.iter (collect_layouts (Some cluster)) stmts (* Anonymous subgraph *) | Subgraph (SubgraphDef (_, stmts)) -> List.iter (collect_layouts cluster) stmts | Attr_graph al -> (match cluster with | Some c -> Hashtbl.add cluster_layouts c (read_cluster_layout al) | None -> ()) | _ -> () with Not_found -> () in List.iter (collect_layouts None) stmts; vertex_layouts, edge_layouts, cluster_layouts let parse g dot_ast = let v_layouts, e_layouts, c_layouts = parse_layouts g dot_ast.stmts in let bbox = parse_bounding_box dot_ast.stmts in (* let bgcolor = parse_bgcolor dot_ast.stmts in*) { vertex_layouts = v_layouts; edge_layouts = !e_layouts; cluster_layouts = c_layouts; bbox = bbox } exception DotError of string let layout_of_xdot ~xdot_file g = let dot_ast = Dot.parse_dot_ast xdot_file in parse g dot_ast let layout_of_dot ?(cmd="dot") ~dot_file g = let base_name = try Filename.basename (Filename.chop_extension dot_file) with Invalid_argument _ -> dot_file in let xdot_file = Filename.temp_file base_name ".xdot" in (* Run graphviz to get xdot file *) let dot_cmd = sprintf "%s -Txdot %s > %s" cmd dot_file xdot_file in match Sys.command dot_cmd with | 0 -> let l = layout_of_xdot ~xdot_file g in Sys.remove xdot_file; l | _ -> Sys.remove xdot_file; raise (DotError "Error during dot execution") end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>