File Coverage

blib/lib/Graph/Layouter.pm
Criterion Covered Total %
statement 15 39 38.4
branch 0 8 0.0
condition n/a
subroutine 5 8 62.5
pod 1 1 100.0
total 21 56 37.5


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Graph::Layouter - lay out graph onto an abstract plane
4              
5             =cut
6              
7              
8             package Graph::Layouter;
9              
10 1     1   784 use strict;
  1         1  
  1         40  
11 1     1   5 use Carp qw (croak);
  1         2  
  1         61  
12              
13 1     1   15 use vars qw ($VERSION @ISA @EXPORT_OK);
  1         2  
  1         76  
14              
15             # $Id: Layouter.pm,v 1.3 2006/02/11 17:11:39 pasky Exp $
16             $VERSION = 0.03;
17              
18              
19             =head1 SYNOPSIS
20              
21             my $graph = new Graph;
22             ...
23              
24             use Graph::Layouter qw(layout);
25             my $layouted = layout($graph);
26              
27             use Graph::Layouter;
28             my $layouted = Graph::Layouter->layout($graph);
29             ...
30             $layouted->layout();
31              
32             =cut
33              
34              
35 1     1   6 use base qw (Graph);
  1         1  
  1         1190  
36              
37             require Exporter;
38             push @ISA, 'Exporter';
39              
40             @EXPORT_OK = qw (layout);
41              
42              
43             =head1 DESCRIPTION
44              
45             This module provides an abstract class for various algorithms of graph nodes
46             positioning at a virtual surface. That is, if you have a graph stuffed into a
47             C object, C will take it and assign each node in the
48             graph virtual coordinates in a plane.
49              
50             C does not do anything besides assigning the coordinates ---
51             you will need to have the nodes and edges laid out to some real plane on your
52             own, or use a bundled C modules family.
53              
54             This module contains only the abstract class, you will probably want to get an
55             instance of some particular layouting algorithm instead;
56             C is bundled with this distribution. The general
57             interface for all the subclasses is described below, but be sure consult also
58             the particular class' documentation for remarks, special notes and specific
59             extensions.
60              
61              
62             =head2 Interface
63              
64             =over 4
65              
66             =cut
67              
68              
69 1     1   183509 use Graph;
  1         2  
  1         429  
70              
71              
72             =item B
73              
74             This subroutine is the only entry point of this module, taking a given graph
75             and laying it out appropriately. The subroutine can be called in several ways:
76              
77             =over 4
78              
79             =item I
80              
81             The subroutine can be called as a function (it is not automatically exported,
82             but you can import it on your own if you really want; see the synopsis above).
83             It takes one parameter, the C class (or any descendant) instance. It
84             will set the layout back into the graph and return its parameter back for
85             convenience.
86              
87             =item I
88              
89             The subroutine can be called as a class constructor, like C<$g =
90             Graph::Layouter->layout($graph)>. It will take the C<$graph>, do stuff on it
91             and returns reference to C<$graph> back, however reblessed to a
92             C instance.
93              
94             In human language this means that after the call C<$graph> will still be the
95             original object, only with some more attributes attached, whereas C<$g> will be
96             a C instance; however any changes to C<$g> will be propagated
97             to C<$graph> and vice versa.
98              
99             =item I
100              
101             When you already got a C instance, you can call this
102             subroutine as C<$g->layout()>. It will relayout an already layouted graph.
103              
104             =back
105              
106             =cut
107              
108             sub layout {
109 0     0 1   my $graph = shift;
110              
111 0           croak "You want to use some subclass instead!";
112 0           $graph;
113             }
114              
115              
116             # Make sure the appropriate attributes are set up on all the nodes.
117             #
118             # This is a private device for subclasses, which are expected to call this in
119             # layout, when they are just about to start doing the work. Note that some
120             # subclasses might want to set the attributes to a different initial value or
121             # so.
122             sub _layout_prepare($) {
123 0     0     my $graph = shift;
124              
125 0           foreach my $vertex ($graph->vertices) {
126 0           $graph->set_vertex_attribute($vertex, 'layout_pos1', 0);
127 0           $graph->set_vertex_attribute($vertex, 'layout_pos2', 0);
128 0           $graph->set_vertex_attribute($vertex, 'layout_force1', 0);
129 0           $graph->set_vertex_attribute($vertex, 'layout_force2', 0);
130             }
131              
132 0           $graph;
133             }
134              
135             # Calculate the bounding coordinate values (min/max extremes in a given
136             # dimension) and store them into global graph attributes.
137             #
138             # This is a private device for subclasses, which are expected to call this in
139             # layout, when they are already done with the work.
140             sub _layout_calc_bounds($) {
141 0     0     my $graph = shift;
142              
143             # Make sure Perl does not emit a metric ton of warnings blab when
144             # counting with infinity numbers. Blah.
145              
146 0           local $^W = 0;
147              
148 0           my ($minx, $maxx, $miny, $maxy) = ('Infinity', -'Infinity', 'Infinity', -'Infinity');
149              
150 0           foreach my $vertex ($graph->vertices) {
151 0           my @pos = ($graph->get_vertex_attribute($vertex, 'layout_pos1'),
152             $graph->get_vertex_attribute($vertex, 'layout_pos2'));
153 0 0         $maxx = $pos[0] if $pos[0] > $maxx;
154 0 0         $minx = $pos[0] if $pos[0] < $minx;
155 0 0         $maxy = $pos[1] if $pos[1] > $maxy;
156 0 0         $miny = $pos[1] if $pos[1] < $miny;
157             }
158              
159 0           $graph->set_graph_attribute('layout_min1', $minx);
160 0           $graph->set_graph_attribute('layout_max1', $maxx);
161 0           $graph->set_graph_attribute('layout_min2', $miny);
162 0           $graph->set_graph_attribute('layout_max2', $maxy);
163 0           $graph;
164             }
165              
166              
167             =back
168              
169             =head2 Data encoding
170              
171             The layouting function saves the layout data (coordinates of nodes) back to the
172             C object, in a form of vertex attributes - C and
173             C (C is the x dimension, C the y dimension; it is
174             planned to make it possible to layout in three or unlimited number of
175             dimensions space).
176              
177             We also provide C, C as well as C,
178             C global graph attributes, containing the extreme values in the
179             respective dimensions. This is usually needed to properly map the virtual
180             coordinates to some physical points.
181              
182             If you intend to use C attributes in conjunction with the
183             C, you are advised not to infrige the C namespace. If
184             you are writing a C subclass, you are advised to put your
185             attributes to a C namespace.
186              
187              
188             =head1 SEE ALSO
189              
190             C, C
191              
192              
193             =head1 BUGS
194              
195             Some more universal layout calling interface (hash parameters) is missing.
196              
197              
198             =head1 COPYRIGHT
199              
200             Copyright 2004 by Petr Baudis Epasky@ucw.czE.
201              
202             This code is distributed under the same copyright terms as
203             Perl itself.
204              
205              
206             =head1 VERSION
207              
208             Version 0.03
209              
210             $Id: Layouter.pm,v 1.3 2006/02/11 17:11:39 pasky Exp $
211              
212             =cut
213              
214             1;