/* Zweck: Stelle Baumterme mit dem Programm /bin/dot graphisch dar.
   Autor: H.Leiss,                   28.7.2002, angepaßt an CL-2: 21.11.2005

   Siehe das Handbuch dazu unter Unix: man dot  ...

   Man bekommt dot von AT&T als Teil des Graphikpakets graphviz unter
      http://www.research.att.com/sw/tools/graphviz/download.html

   Ein Baumterm ist eine Liste [Cat|SubTrees], worin
   - Cat eine Kategorie der Grammatik ist
     (atomar: Kategoriename als Funktionszeichen, Merkmale als Argumente,
   - SubTrees die Liste Baumterm der direkten Teilbäume.

   Der Baum ordnet die Blätter auf einer Grundlinie entsprechend den Wörtern
   des Eingabeausdrucks an.

*/

:- module(display_tree,[displayTrees/1,displayTree/1]).
			
/* Schreibe eine Liste <Terme> von Prolog-Termen als Bäume im .dot-Format auf die
   Datei <Datei>.tmp.dot : */

showTrees(Terme,Datei) :-
	concat(Datei,'.tmp.dot',File),
	tell(File),
	dot(Terme),
	told.

dot([Term|Terme]) :-
	nl,
	(ground(Term) ->
	    write('digraph syntaxbaum {'),
	    write('\ncenter=true; size=\"7.5,14\";\
                   \nratio=compress; ordering=out;\
                   \nedge[dir=none]; node[shape=plaintext];\n'),
	    drawTree(Term),
	    write('}')
	; write(user,'Fehler: der darzustellende Term \"'),
	    writeq(user,Term),
	    write(user, '\" enthält freie Variable!\n')
	),
	dot(Terme).
dot([]).

drawTree(Term) :-
    drawTree(Term,0,_,[],[],BlattfolgeR,[]),
    reverse(BlattfolgeR,Blattfolge),
    order(Blattfolge).

order(Blattfolge) :-
    write('{ rank=same ; '),
    write_list(Blattfolge,' ; '),
    write('};\n'),
% subgraph {edge[style = invis]; 3 -> 5 -> 10 -> 15 -> 17 -> 12 }  // Blattordnung
    write('subgraph {edge[style=invis]; '),
    write_list(Blattfolge,' -> '),
    write(' }\n').

write_list([A,B|Bs],Atom) :-
    write(A),write(Atom),write_list([B|Bs],Atom).
write_list([A],_) :-
    write(A).
write_list([],_).

/* drawTree(+Term,+Wurzelnummer,-naechste nicht verbrauchte Knotennummer)  */

drawTree([Kategorie,(Arg1,Arg2)],N,K,AkkL,_,NAkkL,NAkkR) :-
 	!,
 	write(N),
 	write(' [label = "'),write(Kategorie),write('"];\n'),
 	M is N+1,
        drawTrees([Arg1],N,M,L,AkkL,[],NAkkL,[]),
 	drawTrees([Arg2],N,L,K,[],[],NAkkR,[]).

drawTree([Kategorie|Args],N,K,AkkL,AkkR,AkkLN,AkkRN) :-
	!,
	write(N),write(' [label = \"'),write(Kategorie),write('\"];\n'),
	M is N+1,
	drawTrees(Args,N,M,K,AkkL,AkkR,AkkLN,AkkRN).

drawTree(Term,N,K,AkkL,AkkR,[N|AkkL],AkkR) :-
	atom(Term),
	!,
	write(N),
	write(' [fontcolor = blue, label = "'),write(Term),write('"];'),
	write('\n'),
	K is N+1.

list([]).
list([_|L]) :- list(L).

/* Nachfolger von Baum N, ab Nummer M bis Nummer K fuer deren Knoten */

drawTrees([Arg|Args],N,M,K,AkkL,AkkR,NAkkL,NAkkR) :-
	write(N), write(' -> '), write(M), write(' ;\n'),        
	drawTree(Arg,M,K1,AkkL,AkkR,NAkkL1,NAkkR1),
	drawTrees(Args,N,K1,K,NAkkL1,NAkkR1,NAkkL,NAkkR).

drawTrees([],_,M,M,AkkL,AkkR,AkkL,AkkR).

/* Dot: um bestimmte Knoten auf eine Linie stellen, benutze (im Graphen, s.u.):

{ rank=same; 3; 5; 10; 15; 17; 12};                              // Blattmenge 
subgraph {edge[style = invis]; 3 -> 5 -> 10 -> 15 -> 17 -> 12 }  // Blattordnung

*/

/* Anzeigen der Bäume am Bildschirm: */

displayTree(Term) :-
	displayTrees([Term]).

displayTrees(Terme) :-
	showTrees(Terme,testbaum),
	viewgraph(testbaum).

viewgraph(Datei) :-
       concat_atom(['dot -Tps ',Datei,'.tmp.dot ',' -o',Datei,'.tmp.ps '],Command1),
       % Kleiner: concat_atom(['gv -magstep -2 ',Datei,'.tmp.ps &\n'],Command2),
       concat_atom(['gv ',Datei,'.tmp.ps &\n'],Command2),
       shell(Command1),
       shell(Command2).


/* Beispiel: Baumkodierung wie in Satzgrammatik, nicht wie in CL-2

displayTree([np([def, 3, mask], [sg, nom]),
               [det([def], [mask, sg, nom]), der],
               [rn([mask], [sg, nom]), 'Planet'],
               [np([def, 3, fem], [sg, gen]),
                  [det([def], [fem, sg, gen]), der],
                  [en([fem], [sg, nom]), 'Venus']]]).

digraph syntaxbaum {
 center=true;
 size="7.5,14";
 ratio=compress;
 node[shape=plaintext];
0 [label = "s"];
0 -> 1 [dir = none];
1 [label = "np"];
1 -> 2 [dir = none];
2 [label = "det"];
2 -> 3 [dir = none];
3 [fontcolor = blue, label = "der"];
1 -> 4 [dir = none];
4 [label = "n"];
4 -> 5 [dir = none];
5 [fontcolor = blue, label = "forscher"];
0 -> 6 [dir = none];
6 [fontcolor = blue, label = ":"];
6 -> 7 [dir = none];
7 [label = "v"];
7 -> 8 [dir = none];
8 [fontcolor = blue, label = "x"];
8 -> 9 [dir = none];
9 [label = "aux([haben])"];
6 -> 13 [dir = none];
9 -> 10 [dir = none];
10 [fontcolor = blue, label = "hat"];
8 -> 11 [dir = none];
11 [label = "vpart([nom, akk])"];
11 -> 12 [dir = none];
12 [fontcolor = blue, label = "entdeckt"]
13 [label = "np"];
13 -> 14 [dir = none];
14 [label = "det"];
14 -> 15 [dir = none];
15 [fontcolor = blue, label = "ein"];
13 -> 16 [dir = none];
16 [label = "n"];
16 -> 17 [dir = none];
17 [fontcolor = blue, label = "gen"];
{ rank=same; 3; 5; 10; 15; 17; 12};
subgraph {edge[style = invis]; 3 -> 5 -> 10 -> 15 -> 17 -> 12 }
}

*/
