123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247(**************************************************************************)(* *)(* 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) *)(* *)(**************************************************************************)moduletypeS=sigmoduleTree:Graphviz.GraphWithDotAttrsmoduleTreeManipulation:sigtypetvalget_structure:t->Tree.tvalget_tree_vertices:Tree.V.label->t->Tree.V.tlistvalget_graph_vertex:Tree.V.t->t->Tree.V.labelvalis_ghost_node:Tree.V.t->t->boolvalis_ghost_edge:Tree.E.t->t->boolendtypecluster=stringtypegraph_layoutclasstree_model:graph_layout->TreeManipulation.t->[Tree.V.t,Tree.E.t,cluster]DGraphModel.abstract_modelvaltree:unit->TreeManipulation.tendmoduleBuild(G:Sig.G)(T:Graphviz.GraphWithDotAttrswithtypeV.label=G.V.t)(TM:DGraphSubTree.SwithtypeTree.t=T.tandtypeTree.V.t=T.V.tandtypeTree.E.t=T.E.t)=structmoduleTreeManipulation=TMtypecluster=stringmoduleX=XDot.Make(T)typegraph_layout=X.graph_layoutclasstree_modellayouttree:[T.V.t,T.E.t,cluster]DGraphModel.abstract_model=lettree_structure=TM.get_structuretreeinobject(* Iterators *)methoditer_edgesf=T.iter_edges(funv1v2->ifnot(TM.is_ghost_nodev1tree&&TM.is_ghost_nodev2tree)thenfv1v2)tree_structuremethoditer_edges_ef=T.iter_edges_e(fune->ifnot(TM.is_ghost_edgeetree)thenfe)tree_structuremethoditer_predfv=T.iter_pred(funv->ifnot(TM.is_ghost_nodevtree)thenfv)tree_structurevmethoditer_pred_efv=T.iter_pred_e(fune->ifnot(TM.is_ghost_edgeetree)thenfe)tree_structurevmethoditer_succf=T.iter_succ(funv->ifnot(TM.is_ghost_nodevtree)thenfv)tree_structuremethoditer_succ_ef=T.iter_succ_e(fune->ifnot(TM.is_ghost_edgeetree)thenfe)tree_structuremethoditer_vertexf=T.iter_vertex(funv->ifnot(TM.is_ghost_nodevtree)thenfv)tree_structuremethoditer_associated_vertexfv=letorigin_vertex=TM.get_graph_vertexvtreeinList.iter(funv->ifnot(TM.is_ghost_nodevtree)thenfv)(TM.get_tree_verticesorigin_vertextree)methoditer_clustersf=Hashtbl.iter(funk_->fk)layout.X.cluster_layouts(* Membership functions *)methodfind_edge=tryT.find_edgetree_structurewithNot_found->assertfalsemethodmem_edge=T.mem_edgetree_structuremethodmem_edge_e=T.mem_edge_etree_structuremethodmem_vertex=T.mem_vertextree_structuremethodsrc=T.E.srcmethoddst=T.E.dst(* Layout *)methodbounding_box=layout.X.bboxmethodget_vertex_layoutv=tryX.HV.findlayout.X.vertex_layoutsvwithNot_found->assertfalsemethodget_edge_layoute=tryX.HE.findelayout.X.edge_layoutswithNot_found->assertfalsemethodget_cluster_layoutc=tryHashtbl.findlayout.X.cluster_layoutscwithNot_found->assertfalseendendmoduleSubTreeMake(G:Graphviz.GraphWithDotAttrs)=structmoduleT=Imperative.Digraph.Abstract(G.V)moduleTM=DGraphSubTree.Make(G)(T)lettree_ref:TM.toptionref=refNonelettree()=match!tree_refwithNone->assertfalse|Somet->tletgraph_ref:G.toptionref=refNoneletgraph()=match!graph_refwithNone->assertfalse|Someg->gmoduleTree=structincludeTletgraph_attributes_=G.graph_attributes(graph())letdefault_vertex_attributes_=G.default_vertex_attributes(graph())letdefault_edge_attributes_=G.default_edge_attributes(graph())letcpt=ref0letname_table=Hashtbl.create97letvertex_namev=tryHashtbl.findname_tablevwithNot_found->incrcpt;Hashtbl.addname_tablev(string_of_int!cpt);string_of_int!cptletvertex_attributesv=lett=tree()inifTM.is_ghost_nodevtthen[`Style`Invis]elseG.vertex_attributes(TM.get_graph_vertexvt)letedge_attributese=lett=tree()inifTM.is_ghost_node(T.E.srce)t||TM.is_ghost_node(T.E.dste)tthen[`Style`Dashed;`Dir`None]elseG.edge_attributes(G.find_edge(graph())(TM.get_graph_vertex(T.E.srce)t)(TM.get_graph_vertex(T.E.dste)t))letget_subgraphv=lett=tree()inifTM.is_ghost_nodevtthenNoneelseG.get_subgraph(TM.get_graph_vertexvt)endincludeBuild(G)(Tree)(TM)moduleTreeLayout=DGraphTreeLayout.Make(Tree)(structletis_ghost_nodev=TM.is_ghost_nodev(tree())end)letfrom_graph?(depth_forward=2)?(depth_backward=2)~fontMeasuregv=(* Generate subtree *)lett=TM.makegvdepth_forwarddepth_backwardintree_ref:=Somet;graph_ref:=Someg;letlayout=TreeLayout.from_tree~fontMeasure(TM.get_structuret)(TM.get_roott)innewtree_modellayouttendmoduleSubTreeDotModelMake=structmoduleT=Imperative.Digraph.Abstract(DGraphModel.DotG.V)moduleTM=DGraphSubTree.Make_from_dot_model(T)lettree_ref:TM.toptionref=refNonelettree()=match!tree_refwithNone->assertfalse|Somet->tmoduleTreeLayout=DGraphTreeLayout.MakeFromDotModel(T)(structletis_ghost_nodev=TM.is_ghost_nodev(tree())end)includeTreeLayoutincludeBuild(DGraphModel.DotG)(Tree)(TM)letfrom_model?(depth_forward=2)?(depth_backward=2)modelv=lett=TM.makemodelvdepth_forwarddepth_backwardintree_ref:=Somet;lettree_structure=TM.get_structuretinletlayout=from_modeltree_structure(TM.get_roott)modelinnewtree_modellayouttend