wolffd@0
|
1 classdef Gvizlayout < Abstractlayout
|
wolffd@0
|
2 % Use the graphVIZ package to determine the optimal layout for a graph.
|
wolffd@0
|
3 %
|
wolffd@0
|
4 % Matthew Dunham
|
wolffd@0
|
5 % University of British Columbia
|
wolffd@0
|
6 % http://www.cs.ubc.ca/~mdunham/
|
wolffd@0
|
7 properties
|
wolffd@0
|
8 xmin; % The left most point on the graph axis in data units
|
wolffd@0
|
9 xmax; % The right most point on the graph axis in data units
|
wolffd@0
|
10 ymin; % The bottom most point on the graph axis in data units
|
wolffd@0
|
11 ymax; % The top most point on the graph axis in data units
|
wolffd@0
|
12 adjMatrix; % The adjacency matrix
|
wolffd@0
|
13 maxNodeSize; % The maximum diameter of a node in data units
|
wolffd@0
|
14 image; % An image for the button that will lanuch this layout
|
wolffd@0
|
15 name; % A unique name for instances of this class.
|
wolffd@0
|
16 shortDescription; % A short descriptions used in tooltips.
|
wolffd@0
|
17 nodeSize; % The calculated node size, call dolayout() before accessing
|
wolffd@0
|
18 centers; % The calculated node centers in an n-by-2 matrix
|
wolffd@0
|
19 end
|
wolffd@0
|
20
|
wolffd@0
|
21 properties(GetAccess = 'protected', SetAccess = 'protected')
|
wolffd@0
|
22 layoutFile = 'layout.dot';
|
wolffd@0
|
23 adjFile = 'adjmat.dot';
|
wolffd@0
|
24 end
|
wolffd@0
|
25
|
wolffd@0
|
26 methods
|
wolffd@0
|
27
|
wolffd@0
|
28 function obj = Gvizlayout(name)
|
wolffd@0
|
29 % constructor
|
wolffd@0
|
30 if(nargin < 1)
|
wolffd@0
|
31 obj.name = 'Gvizlayout';
|
wolffd@0
|
32 else
|
wolffd@0
|
33 obj.name = name;
|
wolffd@0
|
34 end
|
wolffd@0
|
35 load glicons;
|
wolffd@0
|
36 obj.image = icons.energy;
|
wolffd@0
|
37 obj.shortDescription = 'Minimum Energy Layout (GraphViz)';
|
wolffd@0
|
38 end
|
wolffd@0
|
39
|
wolffd@0
|
40 function available = isavailable(obj)
|
wolffd@0
|
41 % Make sure graphViz is available.
|
wolffd@0
|
42 available = Gvizlayout.queryGviz('neato');
|
wolffd@0
|
43 if(not(available))
|
wolffd@0
|
44 fprintf('Please install or upgrade graphViz\n');
|
wolffd@0
|
45 end
|
wolffd@0
|
46 end
|
wolffd@0
|
47
|
wolffd@0
|
48
|
wolffd@0
|
49 end
|
wolffd@0
|
50
|
wolffd@0
|
51
|
wolffd@0
|
52 methods(Access = 'protected')
|
wolffd@0
|
53
|
wolffd@0
|
54 function calcLayout(obj)
|
wolffd@0
|
55 % Have graphViz calculate the layout
|
wolffd@0
|
56 obj.writeDOTfile();
|
wolffd@0
|
57 obj.callGraphViz();
|
wolffd@0
|
58 obj.readLayout();
|
wolffd@0
|
59 obj.cleanup();
|
wolffd@0
|
60 end
|
wolffd@0
|
61
|
wolffd@0
|
62 function writeDOTfile(obj)
|
wolffd@0
|
63 % Write the adjacency matrix into a dot file that graphViz can
|
wolffd@0
|
64 % understand.
|
wolffd@0
|
65 fid = fopen('adjmat.dot','w');
|
wolffd@0
|
66 fprintf(fid,'digraph G {\ncenter = 1;\nsize="10,10";\n');
|
wolffd@0
|
67 n = size(obj.adjMatrix,1);
|
wolffd@0
|
68 for i=1:n, fprintf(fid,'%d;\n',i); end
|
wolffd@0
|
69 edgetxt = ' -> ';
|
wolffd@0
|
70 for i=1:n
|
wolffd@0
|
71 for j=1:n
|
wolffd@0
|
72 if(obj.adjMatrix(i,j))
|
wolffd@0
|
73 fprintf(fid,'%d%s%d;\n',i,edgetxt,j);
|
wolffd@0
|
74 end
|
wolffd@0
|
75 end
|
wolffd@0
|
76 end
|
wolffd@0
|
77 fprintf(fid,'}');
|
wolffd@0
|
78 fclose(fid);
|
wolffd@0
|
79 end
|
wolffd@0
|
80
|
wolffd@0
|
81 function callGraphViz(obj)
|
wolffd@0
|
82 % Call GraphViz to determine an optimal layout. Write this layout in
|
wolffd@0
|
83 % layout.dot for later parsing.
|
wolffd@0
|
84 err = system(['neato -Tdot -Gmaxiter=5000 -Gstart=7 -o ',obj.layoutFile,' ',obj.adjFile]);
|
wolffd@0
|
85 if(err),error('Sorry, unknown GraphViz failure, try another layout'); end
|
wolffd@0
|
86 end
|
wolffd@0
|
87
|
wolffd@0
|
88 function readLayout(obj)
|
wolffd@0
|
89 % Parse the layout.dot file for the graphViz node locations and
|
wolffd@0
|
90 % dimensions.
|
wolffd@0
|
91 fid = fopen(obj.layoutFile,'r');
|
wolffd@0
|
92 text = textscan(fid,'%s','delimiter','\n');
|
wolffd@0
|
93 fclose(fid);
|
wolffd@0
|
94 text = text{:};
|
wolffd@0
|
95 [start,dims] = strtok(text{cellfun(@(x)~isempty(x),strfind(text,'graph [bb="'))},'"');
|
wolffd@0
|
96 dims = textscan(strtok(dims,'"'),'%n','delimiter',',');
|
wolffd@0
|
97 dims = dims{:}';
|
wolffd@0
|
98 text(cellfun(@(x)~isempty(x),strfind(text,' -> ')))=[]; % delete edge info, we don't need it
|
wolffd@0
|
99 text(cellfun(@(x)isempty(x),strfind(text,'pos')))=[]; % keep only positions
|
wolffd@0
|
100 [start,remaining] = strtok(text,'"');
|
wolffd@0
|
101 [locations,remaining] = strtok(remaining,'"');
|
wolffd@0
|
102 locations = cellfun(@(str)textscan(str,'%n','delimiter',','),locations,'UniformOutput',false);
|
wolffd@0
|
103 locations = [locations{:}];
|
wolffd@0
|
104 locations = [locations{:}]';
|
wolffd@0
|
105 obj.scaleLocations(locations,dims);
|
wolffd@0
|
106 end
|
wolffd@0
|
107
|
wolffd@0
|
108 function scaleLocations(obj,locations,graphVizDims)
|
wolffd@0
|
109 % Scale the graphViz node locations to the smartgraph dimensions and
|
wolffd@0
|
110 % set the node size.
|
wolffd@0
|
111 dims = graphVizDims; loc = locations;
|
wolffd@0
|
112 loc(:,1) = (loc(:,1)-dims(1)) ./ (dims(3)-dims(1))*(obj.xmax - obj.xmin) + obj.xmin;
|
wolffd@0
|
113 loc(:,2) = (loc(:,2)-dims(2)) ./ (dims(4)-dims(2))*(obj.ymax - obj.ymin) + obj.ymin;
|
wolffd@0
|
114 obj.centers = loc;
|
wolffd@0
|
115
|
wolffd@0
|
116 a = min(abs(loc(:,1) - obj.xmin));
|
wolffd@0
|
117 b = min(abs(loc(:,1) - obj.xmax));
|
wolffd@0
|
118 c = min(abs(loc(:,2) - obj.ymin));
|
wolffd@0
|
119 d = min(abs(loc(:,2) - obj.ymax));
|
wolffd@0
|
120 obj.nodeSize = min(2*min([a,b,c,d]),obj.maxNodeSize);
|
wolffd@0
|
121
|
wolffd@0
|
122 end
|
wolffd@0
|
123
|
wolffd@0
|
124 function cleanup(obj)
|
wolffd@0
|
125 % delete the temporary files.
|
wolffd@0
|
126 delete(obj.adjFile);
|
wolffd@0
|
127 delete(obj.layoutFile);
|
wolffd@0
|
128 end
|
wolffd@0
|
129
|
wolffd@0
|
130 end
|
wolffd@0
|
131
|
wolffd@0
|
132 methods(Access = 'protected',Static = true)
|
wolffd@0
|
133
|
wolffd@0
|
134 function available = queryGviz(name)
|
wolffd@0
|
135 err = system([name,' -V']);
|
wolffd@0
|
136 available = ~err;
|
wolffd@0
|
137 end
|
wolffd@0
|
138
|
wolffd@0
|
139 end
|
wolffd@0
|
140
|
wolffd@0
|
141
|
wolffd@0
|
142 end % end of graphVIZlayout class |