~ubuntu-branches/ubuntu/lucid/igraph/lucid

« back to all changes in this revision

Viewing changes to src/layout.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Malaterre
  • Date: 2009-11-16 18:12:42 UTC
  • Revision ID: james.westby@ubuntu.com-20091116181242-mzv9p5fz9uj57xd1
Tags: upstream-0.5.3
ImportĀ upstreamĀ versionĀ 0.5.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C -*-  */
 
2
/* 
 
3
   IGraph R package.
 
4
   Copyright (C) 2003, 2004, 2005, 2006  Gabor Csardi <csardi@rmki.kfki.hu>
 
5
   MTA RMKI, Konkoly-Thege Miklos st. 29-33, Budapest 1121, Hungary
 
6
   
 
7
   This program is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 2 of the License, or
 
10
   (at your option) any later version.
 
11
   
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
   
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program; if not, write to the Free Software
 
19
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
 
20
   02110-1301 USA
 
21
 
 
22
*/
 
23
 
 
24
#include "igraph.h"
 
25
#include "random.h"
 
26
#include "memory.h"
 
27
#include "config.h"
 
28
#include <math.h>
 
29
#include "igraph_math.h"
 
30
 
 
31
int igraph_i_layout_sphere_2d(igraph_matrix_t *coords, igraph_real_t *x, igraph_real_t *y,
 
32
                              igraph_real_t *r);
 
33
int igraph_i_layout_sphere_3d(igraph_matrix_t *coords, igraph_real_t *x, igraph_real_t *y,
 
34
                              igraph_real_t *z, igraph_real_t *r);
 
35
 
 
36
/**
 
37
 * \section about_layouts
 
38
 * 
 
39
 * <para>Layout generator functions (or at least most of them) try to place the
 
40
 * vertices and edges of a graph on a 2D plane or in 3D space in a way
 
41
 * which visually pleases the human eye.</para>
 
42
 *
 
43
 * <para>They take a graph object and a number of parameters as arguments
 
44
 * and return an \type igraph_matrix_t, in which each row gives the
 
45
 * coordinates of a vertex.</para>
 
46
 */
 
47
 
 
48
/**
 
49
 * \ingroup layout
 
50
 * \function igraph_layout_random
 
51
 * \brief Places the vertices uniform randomly on a plane.
 
52
 * 
 
53
 * \param graph Pointer to an initialized graph object.
 
54
 * \param res Pointer to an initialized graph object. This will
 
55
 *        contain the result and will be resized in needed.
 
56
 * \return Error code. The current implementation always returns with
 
57
 * success. 
 
58
 * 
 
59
 * Time complexity: O(|V|), the
 
60
 * number of vertices. 
 
61
 */
 
62
 
 
63
int igraph_layout_random(const igraph_t *graph, igraph_matrix_t *res) {
 
64
 
 
65
  long int no_of_nodes=igraph_vcount(graph);
 
66
  long int i;
 
67
 
 
68
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 2));
 
69
 
 
70
  RNG_BEGIN();
 
71
 
 
72
  for (i=0; i<no_of_nodes; i++) {
 
73
    MATRIX(*res, i, 0)=RNG_UNIF(-1, 1);
 
74
    MATRIX(*res, i, 1)=RNG_UNIF(-1, 1);
 
75
  }
 
76
 
 
77
  RNG_END();
 
78
  
 
79
  return 0;
 
80
}
 
81
 
 
82
/**
 
83
 * \function igraph_layout_random_3d
 
84
 * \brief Random layout in 3D
 
85
 * 
 
86
 * \param graph The graph to place.
 
87
 * \param res Pointer to an initialized matrix object. It will be
 
88
 * resized to hold the result.
 
89
 * \return Error code. The current implementation always returns with
 
90
 * success. 
 
91
 *
 
92
 * Added in version 0.2.</para><para>
 
93
 * 
 
94
 * Time complexity: O(|V|), the number of vertices.
 
95
 */
 
96
 
 
97
int igraph_layout_random_3d(const igraph_t *graph, igraph_matrix_t *res) {
 
98
  
 
99
  long int no_of_nodes=igraph_vcount(graph);
 
100
  long int i;
 
101
  
 
102
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 3));
 
103
  
 
104
  RNG_BEGIN();
 
105
  
 
106
  for (i=0; i<no_of_nodes; i++) {
 
107
    MATRIX(*res, i, 0)=RNG_UNIF(-1, 1);
 
108
    MATRIX(*res, i, 1)=RNG_UNIF(-1, 1);
 
109
    MATRIX(*res, i, 2)=RNG_UNIF(-1, 1);
 
110
  }
 
111
  
 
112
  RNG_END();
 
113
  
 
114
  return 0;
 
115
}
 
116
 
 
117
/**
 
118
 * \ingroup layout
 
119
 * \function igraph_layout_circle
 
120
 * \brief Places the vertices uniformly on a circle, in the order of vertex ids.
 
121
 * 
 
122
 * \param graph Pointer to an initialized graph object.
 
123
 * \param res Pointer to an initialized graph object. This will
 
124
 *        contain the result and will be resized in needed.
 
125
 * \return Error code.
 
126
 * 
 
127
 * Time complexity: O(|V|), the
 
128
 * number of vertices. 
 
129
 */
 
130
 
 
131
int igraph_layout_circle(const igraph_t *graph, igraph_matrix_t *res) {
 
132
 
 
133
  long int no_of_nodes=igraph_vcount(graph);
 
134
  long int i;
 
135
 
 
136
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 2));  
 
137
 
 
138
  for (i=0; i<no_of_nodes; i++) {
 
139
    igraph_real_t phi=2*M_PI/no_of_nodes*i;
 
140
    MATRIX(*res, i, 0)=cos(phi);
 
141
    MATRIX(*res, i, 1)=sin(phi);
 
142
  }
 
143
  
 
144
  return 0;
 
145
}
 
146
 
 
147
/**
 
148
 * \function igraph_layout_sphere
 
149
 * \brief Places vertices (more or less) uniformly on a sphere.
 
150
 *
 
151
 * </para><para> 
 
152
 * The algorithm was described in the following paper:
 
153
 * Distributing many points on a sphere by E.B. Saff and
 
154
 * A.B.J. Kuijlaars, \emb Mathematical Intelligencer \eme 19.1 (1997)
 
155
 * 5--11.  
 
156
 * 
 
157
 * \param graph Pointer to an initialized graph object.
 
158
 * \param res Pointer to an initialized matrix object, the will be
 
159
 * stored here. It will be resized.
 
160
 * \return Error code. The current implementation always returns with
 
161
 * success. 
 
162
 * 
 
163
 * Added in version 0.2.</para><para>
 
164
 *
 
165
 * Time complexity: O(|V|), the number of vertices in the graph.
 
166
 */
 
167
 
 
168
int igraph_layout_sphere(const igraph_t *graph, igraph_matrix_t *res) {
 
169
  
 
170
  long int no_of_nodes=igraph_vcount(graph);
 
171
  long int i;
 
172
  igraph_real_t h;
 
173
  
 
174
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 3));
 
175
 
 
176
  if (no_of_nodes != 0) {
 
177
    MATRIX(*res, 0, 0)=M_PI;
 
178
    MATRIX(*res, 0, 1)=0;
 
179
  }
 
180
  for (i=1; i<no_of_nodes-1; i++) {
 
181
    h = -1 + 2*i/(double)(no_of_nodes-1);
 
182
    MATRIX(*res, i, 0) = acos(h);
 
183
    MATRIX(*res, i, 1) = fmod((MATRIX(*res, i-1, 1) +
 
184
                               3.6/sqrt(no_of_nodes*(1-h*h))), 2*M_PI);
 
185
    IGRAPH_ALLOW_INTERRUPTION();
 
186
  }
 
187
  if (no_of_nodes >=2) {
 
188
    MATRIX(*res, no_of_nodes-1, 0)=0;
 
189
    MATRIX(*res, no_of_nodes-1, 1)=0;
 
190
  }
 
191
 
 
192
  for (i=0; i<no_of_nodes; i++) {
 
193
    igraph_real_t x=cos(MATRIX(*res, i, 1))*sin(MATRIX(*res, i, 0));
 
194
    igraph_real_t y=sin(MATRIX(*res, i, 1))*sin(MATRIX(*res, i, 0));
 
195
    igraph_real_t z=cos(MATRIX(*res, i, 0));
 
196
    MATRIX(*res, i, 0)=x;
 
197
    MATRIX(*res, i, 1)=y;
 
198
    MATRIX(*res, i, 2)=z;
 
199
    IGRAPH_ALLOW_INTERRUPTION();
 
200
  }
 
201
  
 
202
  return 0;
 
203
}
 
204
 
 
205
/**
 
206
 * \ingroup layout
 
207
 * \function igraph_layout_fruchterman_reingold
 
208
 * \brief Places the vertices on a plane according to the Fruchterman-Reingold algorithm.
 
209
 *
 
210
 * </para><para>
 
211
 * This is a force-directed layout, see Fruchterman, T.M.J. and
 
212
 * Reingold, E.M.: Graph Drawing by Force-directed Placement.
 
213
 * Software -- Practice and Experience, 21/11, 1129--1164,
 
214
 * 1991. 
 
215
 * This function was ported from the SNA R package.
 
216
 * \param graph Pointer to an initialized graph object.
 
217
 * \param res Pointer to an initialized matrix object. This will
 
218
 *        contain the result and will be resized in needed.
 
219
 * \param niter The number of iterations to do.
 
220
 * \param maxdelta The maximum distance to move a vertex in an
 
221
 *        iteration.
 
222
 * \param area The area parameter of the algorithm.
 
223
 * \param coolexp The cooling exponent of the simulated annealing.
 
224
 * \param repulserad Determines the radius at which
 
225
 *        vertex-vertex repulsion cancels out attraction of
 
226
 *        adjacent vertices.
 
227
 * \param use_seed Logical, if true the supplied values in the
 
228
 *        \p res argument are used as an initial layout, if
 
229
 *        false a random initial layout is used.
 
230
 * \param weight Pointer to a vector containing edge weights, 
 
231
 *        the attraction along the edges will be multiplied by these. 
 
232
 *        It will be ignored if it is a null-pointer.
 
233
 * \return Error code.
 
234
 * 
 
235
 * Time complexity: O(|V|^2) in each
 
236
 * iteration, |V| is the number of
 
237
 * vertices in the graph. 
 
238
 */
 
239
 
 
240
int igraph_layout_fruchterman_reingold(const igraph_t *graph, igraph_matrix_t *res,
 
241
                                       igraph_integer_t niter, igraph_real_t maxdelta,
 
242
                                       igraph_real_t area, igraph_real_t coolexp, 
 
243
                                       igraph_real_t repulserad, igraph_bool_t use_seed,
 
244
                                       const igraph_vector_t *weight) {
 
245
  igraph_real_t frk,t,ded,xd,yd;
 
246
  igraph_real_t rf,af;
 
247
  long int i,j,k;
 
248
 
 
249
  long int no_of_nodes=igraph_vcount(graph);
 
250
  igraph_matrix_t dxdy=IGRAPH_MATRIX_NULL;
 
251
  igraph_eit_t edgeit;
 
252
  igraph_integer_t from, to;
 
253
  
 
254
  if (weight && igraph_vector_size(weight) != igraph_ecount(graph)) {
 
255
    IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
 
256
  }
 
257
  
 
258
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 2));
 
259
  if (!use_seed) {
 
260
    IGRAPH_CHECK(igraph_layout_random(graph, res));
 
261
  }
 
262
  IGRAPH_MATRIX_INIT_FINALLY(&dxdy, no_of_nodes, 2);
 
263
 
 
264
  IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(0), &edgeit));
 
265
  IGRAPH_FINALLY(igraph_eit_destroy, &edgeit);
 
266
  
 
267
  frk=sqrt(area/no_of_nodes);
 
268
 
 
269
  for(i=niter;i>0;i--) {
 
270
    /* Report progress in approx. every 100th step */
 
271
    if (i%10 == 0)
 
272
      IGRAPH_PROGRESS("Fruchterman-Reingold layout: ",
 
273
                      100.0-100.0*i/niter, NULL);
 
274
    
 
275
    /* Set the temperature (maximum move/iteration) */
 
276
    t=maxdelta*pow(i/(double)niter,coolexp);
 
277
    /* Clear the deltas */
 
278
    igraph_matrix_null(&dxdy);
 
279
    /* Increment deltas for each undirected pair */
 
280
    for(j=0;j<no_of_nodes;j++) {
 
281
      IGRAPH_ALLOW_INTERRUPTION();
 
282
      for(k=j+1;k<no_of_nodes;k++){
 
283
        /* Obtain difference vector */
 
284
        xd=MATRIX(*res, j, 0)-MATRIX(*res, k, 0);
 
285
        yd=MATRIX(*res, j, 1)-MATRIX(*res, k, 1);
 
286
        ded=sqrt(xd*xd+yd*yd);  /* Get dyadic euclidean distance */
 
287
        xd/=ded;                /* Rescale differences to length 1 */
 
288
        yd/=ded;
 
289
        /* Calculate repulsive "force" */
 
290
        rf=frk*frk*(1.0/ded-ded*ded/repulserad);
 
291
        MATRIX(dxdy, j, 0)+=xd*rf; /* Add to the position change vector */
 
292
        MATRIX(dxdy, k, 0)-=xd*rf;
 
293
        MATRIX(dxdy, j, 1)+=yd*rf;
 
294
        MATRIX(dxdy, k, 1)-=yd*rf;
 
295
      }
 
296
    }
 
297
    /* Calculate the attractive "force" */
 
298
    IGRAPH_EIT_RESET(edgeit);
 
299
    while (!IGRAPH_EIT_END(edgeit)) {
 
300
      long int edge=IGRAPH_EIT_GET(edgeit);
 
301
      igraph_real_t w= weight ? VECTOR(*weight)[ edge ] : 1.0;
 
302
      igraph_edge(graph, edge, &from, &to);
 
303
      j=from; 
 
304
      k=to;
 
305
      xd=MATRIX(*res, j, 0)-MATRIX(*res, k, 0);
 
306
      yd=MATRIX(*res, j, 1)-MATRIX(*res, k, 1);
 
307
      ded=sqrt(xd*xd+yd*yd);  /* Get dyadic euclidean distance */
 
308
      if (ded != 0) {
 
309
        xd/=ded;                /* Rescale differences to length 1 */
 
310
        yd/=ded;
 
311
      }
 
312
      af=ded*ded/frk*w;
 
313
      MATRIX(dxdy, j, 0)-=xd*af; /* Add to the position change vector */
 
314
      MATRIX(dxdy, k, 0)+=xd*af;
 
315
      MATRIX(dxdy, j, 1)-=yd*af;
 
316
      MATRIX(dxdy, k, 1)+=yd*af;
 
317
      IGRAPH_EIT_NEXT(edgeit);
 
318
    }
 
319
    
 
320
    /* Dampen motion, if needed, and move the points */   
 
321
    for(j=0;j<no_of_nodes;j++){
 
322
      ded=sqrt(MATRIX(dxdy, j, 0)*MATRIX(dxdy, j, 0)+
 
323
               MATRIX(dxdy, j, 1)*MATRIX(dxdy, j, 1));    
 
324
      if(ded>t){                /* Dampen to t */
 
325
        ded=t/ded;
 
326
        MATRIX(dxdy, j, 0)*=ded;
 
327
        MATRIX(dxdy, j, 1)*=ded;
 
328
      }
 
329
      MATRIX(*res, j, 0)+=MATRIX(dxdy, j, 0); /* Update positions */
 
330
      MATRIX(*res, j, 1)+=MATRIX(dxdy, j, 1);
 
331
    }
 
332
  }
 
333
 
 
334
  IGRAPH_PROGRESS("Fruchterman-Reingold layout: ", 100.0, NULL);
 
335
  
 
336
  igraph_eit_destroy(&edgeit);
 
337
  igraph_matrix_destroy(&dxdy);
 
338
  IGRAPH_FINALLY_CLEAN(2);
 
339
  
 
340
  return 0;
 
341
}
 
342
 
 
343
/**
 
344
 * \function igraph_layout_fruchterman_reingold_3d
 
345
 * \brief 3D Fruchterman-Reingold algorithm.
 
346
 * 
 
347
 * This is the 3D version of the force based
 
348
 * Fruchterman-Reingold layout (see \ref
 
349
 * igraph_layout_fruchterman_reingold for the 2D version
 
350
 *
 
351
 * </para><para>
 
352
 * This function was ported from the SNA R package.
 
353
 * \param graph Pointer to an initialized graph object.
 
354
 * \param res Pointer to an initialized matrix object. This will
 
355
 *        contain the result and will be resized in needed.
 
356
 * \param niter The number of iterations to do.
 
357
 * \param maxdelta The maximum distance to move a vertex in an
 
358
 *        iteration.
 
359
 * \param volume The volume parameter of the algorithm.
 
360
 * \param coolexp The cooling exponent of the simulated annealing.
 
361
 * \param repulserad Determines the radius at which
 
362
 *        vertex-vertex repulsion cancels out attraction of
 
363
 *        adjacent vertices.
 
364
 * \param use_seed Logical, if true the supplied values in the
 
365
 *        \p res argument are used as an initial layout, if
 
366
 *        false a random initial layout is used.
 
367
 * \param weight Pointer to a vector containing edge weights, 
 
368
 *        the attraction along the edges will be multiplied by these. 
 
369
 *        It will be ignored if it is a null-pointer.
 
370
 * \return Error code.
 
371
 *
 
372
 * Added in version 0.2.</para><para>
 
373
 *
 
374
 * Time complexity: O(|V|^2) in each
 
375
 * iteration, |V| is the number of
 
376
 * vertices in the graph. 
 
377
 * 
 
378
 */
 
379
 
 
380
int igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, 
 
381
                                          igraph_matrix_t *res,
 
382
                                          igraph_integer_t niter, igraph_real_t maxdelta,
 
383
                                          igraph_real_t volume, igraph_real_t coolexp,
 
384
                                          igraph_real_t repulserad,
 
385
                                          igraph_bool_t use_seed,
 
386
                                          const igraph_vector_t *weight) {
 
387
  
 
388
  igraph_real_t frk, t, ded, xd, yd, zd;
 
389
  igraph_matrix_t dxdydz;
 
390
  igraph_real_t rf, af;
 
391
  long int i, j, k;
 
392
  
 
393
  long int no_of_nodes=igraph_vcount(graph);
 
394
  igraph_eit_t edgeit;
 
395
  igraph_integer_t from, to;
 
396
 
 
397
  if (weight && igraph_vector_size(weight) != igraph_ecount(graph)) {
 
398
    IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
 
399
  }
 
400
  
 
401
  IGRAPH_CHECK(igraph_matrix_init(&dxdydz, no_of_nodes, 3));
 
402
  IGRAPH_FINALLY(igraph_matrix_destroy, &dxdydz);
 
403
  
 
404
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 3));
 
405
  if (!use_seed) {
 
406
    IGRAPH_CHECK(igraph_layout_random_3d(graph, res));
 
407
  }
 
408
 
 
409
  IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(0), &edgeit));
 
410
  IGRAPH_FINALLY(igraph_eit_destroy, &edgeit);
 
411
 
 
412
  frk=pow(volume/(double)no_of_nodes,1.0/3.0); /*Define the F-R constant*/
 
413
 
 
414
  /*Run the annealing loop*/
 
415
  for(i=niter;i>=0;i--){
 
416
    if (i%10 == 0)
 
417
      IGRAPH_PROGRESS("3D Fruchterman-Reingold layout: ",
 
418
                      100.0-100.0*i/niter, NULL);
 
419
 
 
420
    /*Set the temperature (maximum move/iteration)*/
 
421
    t=maxdelta*pow(i/(double)niter,coolexp);
 
422
    /*Clear the deltas*/
 
423
    igraph_matrix_null(&dxdydz);
 
424
    /*Increment deltas for each undirected pair*/
 
425
    for(j=0;j<no_of_nodes;j++) {
 
426
      IGRAPH_ALLOW_INTERRUPTION();
 
427
      for(k=j+1;k<no_of_nodes;k++){
 
428
        /*Obtain difference vector*/
 
429
        xd=MATRIX(*res, j, 0)-MATRIX(*res, k, 0);
 
430
        yd=MATRIX(*res, j, 1)-MATRIX(*res, k, 1);
 
431
        zd=MATRIX(*res, j, 2)-MATRIX(*res, k, 2);
 
432
        ded=sqrt(xd*xd+yd*yd+zd*zd);  /*Get dyadic euclidean distance*/
 
433
        if (ded != 0) {
 
434
          xd/=ded;                      /*Rescale differences to length 1*/
 
435
          yd/=ded;
 
436
          zd/=ded;
 
437
        }
 
438
        /*Calculate repulsive "force"*/
 
439
        rf=frk*frk*(1.0/ded-ded*ded/repulserad);
 
440
        MATRIX(dxdydz, j, 0)+=xd*rf;     /*Add to the position change vector*/
 
441
        MATRIX(dxdydz, k, 0)-=xd*rf;
 
442
        MATRIX(dxdydz, j, 1)+=yd*rf;
 
443
        MATRIX(dxdydz, k, 1)-=yd*rf;
 
444
        MATRIX(dxdydz, j, 2)+=zd*rf;
 
445
        MATRIX(dxdydz, k, 2)-=zd*rf;
 
446
      }
 
447
    }
 
448
 
 
449
    /*Calculate the attractive "force"*/
 
450
    IGRAPH_EIT_RESET(edgeit);
 
451
    while (!IGRAPH_EIT_END(edgeit)) {
 
452
      long int edge=IGRAPH_EIT_GET(edgeit);
 
453
      igraph_real_t w= weight ? VECTOR(*weight)[edge] : 1.0;
 
454
      igraph_edge(graph, edge, &from, &to);
 
455
      j=from;
 
456
      k=to;
 
457
      xd=MATRIX(*res, j, 0)-MATRIX(*res, k, 0);
 
458
      yd=MATRIX(*res, j, 1)-MATRIX(*res, k, 1);
 
459
      zd=MATRIX(*res, j, 2)-MATRIX(*res, k, 2);
 
460
      ded=sqrt(xd*xd+yd*yd+zd*zd);  /*Get dyadic euclidean distance*/
 
461
      if (ded != 0) {
 
462
        xd/=ded;                      /*Rescale differences to length 1*/
 
463
        yd/=ded;
 
464
        zd/=ded;
 
465
      }
 
466
      af=ded*ded/frk*w;
 
467
      MATRIX(dxdydz, j, 0)-=xd*af;   /*Add to the position change vector*/
 
468
      MATRIX(dxdydz, k, 0)+=xd*af;
 
469
      MATRIX(dxdydz, j, 1)-=yd*af;
 
470
      MATRIX(dxdydz, k, 1)+=yd*af;
 
471
      MATRIX(dxdydz, j, 2)-=zd*af;
 
472
      MATRIX(dxdydz, k, 2)+=zd*af;
 
473
      IGRAPH_EIT_NEXT(edgeit);
 
474
    }
 
475
 
 
476
    /*Dampen motion, if needed, and move the points*/
 
477
    for(j=0;j<no_of_nodes;j++){
 
478
      ded=sqrt(MATRIX(dxdydz, j, 0)*MATRIX(dxdydz, j, 0)+
 
479
               MATRIX(dxdydz, j, 1)*MATRIX(dxdydz, j, 1)+
 
480
               MATRIX(dxdydz, j, 2)*MATRIX(dxdydz, j, 2));
 
481
      if(ded>t){                 /*Dampen to t*/
 
482
        ded=t/ded;
 
483
        MATRIX(dxdydz, j, 0)*=ded;
 
484
        MATRIX(dxdydz, j, 1)*=ded;
 
485
        MATRIX(dxdydz, j, 2)*=ded;
 
486
      }
 
487
      MATRIX(*res, j, 0)+=MATRIX(dxdydz, j, 0);          /*Update positions*/
 
488
      MATRIX(*res, j, 1)+=MATRIX(dxdydz, j, 1);
 
489
      MATRIX(*res, j, 2)+=MATRIX(dxdydz, j, 2);
 
490
    }
 
491
  }
 
492
 
 
493
  IGRAPH_PROGRESS("3D Fruchterman-Reingold layout: ", 100.0, NULL);
 
494
  
 
495
  igraph_matrix_destroy(&dxdydz);
 
496
  igraph_eit_destroy(&edgeit);
 
497
  IGRAPH_FINALLY_CLEAN(2);
 
498
  return 0;
 
499
}
 
500
 
 
501
/**
 
502
 * \ingroup layout
 
503
 * \function igraph_layout_kamada_kawai
 
504
 * \brief Places the vertices on a plane according the Kamada-Kawai algorithm. 
 
505
 *
 
506
 * </para><para>
 
507
 * This is a force directed layout, see  Kamada, T. and Kawai, S.: An
 
508
 * Algorithm for Drawing General Undirected Graphs. Information
 
509
 * Processing Letters, 31/1, 7--15, 1989.
 
510
 * This function was ported from the SNA R package.
 
511
 * \param graph A graph object.
 
512
 * \param res Pointer to an initialized matrix object. This will
 
513
 *        contain the result and will be resized if needed.
 
514
 * \param niter The number of iterations to perform.
 
515
 * \param sigma Sets the base standard deviation of position
 
516
 *        change proposals. 
 
517
 * \param initemp Sets the initial temperature for the annealing.
 
518
 * \param coolexp The cooling exponent of the annealing.
 
519
 * \param kkconst The Kamada-Kawai vertex attraction constant.
 
520
 * \param use_seed Boolean, whether to use the values cupplied in the \p res 
 
521
 *     argument as the initial configuration. If zero then a random initial 
 
522
 *     configuration is used.
 
523
 * \return Error code.
 
524
 * 
 
525
 * Time complexity: O(|V|^2) for each
 
526
 * iteration, |V| is the number of
 
527
 * vertices in the graph. 
 
528
 */
 
529
 
 
530
int igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t *res,
 
531
                               igraph_integer_t niter, igraph_real_t sigma, 
 
532
                               igraph_real_t initemp, igraph_real_t coolexp,
 
533
                               igraph_real_t kkconst, igraph_bool_t use_seed) {
 
534
 
 
535
  igraph_real_t temp, candx, candy;
 
536
  igraph_real_t dpot, odis, ndis, osqd, nsqd;
 
537
  long int n,i,j,k;
 
538
  igraph_matrix_t elen;
 
539
 
 
540
  /* Define various things */
 
541
  n=igraph_vcount(graph);
 
542
 
 
543
  /* Calculate elen, initial x & y */
 
544
 
 
545
  RNG_BEGIN();
 
546
 
 
547
  IGRAPH_CHECK(igraph_matrix_resize(res, n, 2));
 
548
  IGRAPH_MATRIX_INIT_FINALLY(&elen, n, n);
 
549
  IGRAPH_CHECK(igraph_shortest_paths(graph, &elen, igraph_vss_all(), 
 
550
                                     IGRAPH_ALL));
 
551
  if (!use_seed) {
 
552
    for (i=0; i<n; i++) {
 
553
      MATRIX(elen, i, i) = sqrt(n);
 
554
      MATRIX(*res, i, 0) = RNG_NORMAL(0, n/4.0);
 
555
      MATRIX(*res, i, 1) = RNG_NORMAL(0, n/4.0);
 
556
    }
 
557
  }
 
558
  
 
559
  /*Perform the annealing loop*/
 
560
  temp=initemp;
 
561
  for(i=0;i<niter;i++){
 
562
    /* Report progress in approx. every 100th step */
 
563
    if (i%10 == 0)
 
564
      IGRAPH_PROGRESS("Kamada-Kawai layout: ",
 
565
                      100.0*i/niter, NULL);
 
566
    /*Update each vertex*/
 
567
    for(j=0;j<n;j++){
 
568
      IGRAPH_ALLOW_INTERRUPTION();
 
569
      /*Draw the candidate via a gaussian perturbation*/
 
570
      candx=RNG_NORMAL(MATRIX(*res, j, 0),sigma*temp/initemp);
 
571
      candy=RNG_NORMAL(MATRIX(*res, j, 1),sigma*temp/initemp);
 
572
      /*Calculate the potential difference for the new position*/
 
573
      dpot=0.0;
 
574
      for(k=0;k<n;k++)  /*Potential differences for pairwise effects*/
 
575
        if(j!=k){
 
576
          odis=sqrt((MATRIX(*res, j, 0)-MATRIX(*res, k, 0))*
 
577
                    (MATRIX(*res, j, 0)-MATRIX(*res, k, 0))+
 
578
                    (MATRIX(*res, j, 1)-MATRIX(*res, k, 1))*
 
579
                    (MATRIX(*res, j, 1)-MATRIX(*res, k, 1)));
 
580
          ndis=sqrt((candx-MATRIX(*res, k, 0))*(candx-MATRIX(*res, k, 0))+
 
581
                    (candy-MATRIX(*res, k, 1))*(candy-MATRIX(*res, k, 1)));
 
582
          osqd=(odis-MATRIX(elen, j, k))*(odis-MATRIX(elen, j, k));
 
583
          nsqd=(ndis-MATRIX(elen, j, k))*(ndis-MATRIX(elen, j, k));
 
584
          dpot+=kkconst*(osqd-nsqd)/(MATRIX(elen, j, k)*MATRIX(elen, j, k));
 
585
        }
 
586
      /*Make a keep/reject decision*/
 
587
      if(log(RNG_UNIF(0.0,1.0))<dpot/temp){
 
588
        MATRIX(*res, j, 0)=candx;
 
589
        MATRIX(*res, j, 1)=candy;
 
590
      }
 
591
    }
 
592
    /*Cool the system*/
 
593
    temp*=coolexp;
 
594
  }
 
595
 
 
596
  IGRAPH_PROGRESS("Kamada-Kawai layout: ", 100.0, NULL);
 
597
 
 
598
  RNG_END();
 
599
  igraph_matrix_destroy(&elen);
 
600
  IGRAPH_FINALLY_CLEAN(1);
 
601
 
 
602
  return 0;
 
603
}
 
604
 
 
605
/**
 
606
 * \function igraph_layout_kamada_kawai_3d
 
607
 * \brief 3D version of the force based Kamada-Kawai layout.
 
608
 *
 
609
 * The pair of the \ref igraph_layout_kamada_kawai 2D layout generator
 
610
 * 
 
611
 * </para><para>
 
612
 * This function was ported from the SNA R package.
 
613
 * \param graph A graph object.
 
614
 * \param res Pointer to an initialized matrix object. This will
 
615
 *        contain the result and will be resized if needed.
 
616
 * \param niter The number of iterations to perform.
 
617
 * \param sigma Sets the base standard deviation of position
 
618
 *        change proposals. 
 
619
 * \param initemp Sets the initial temperature for the annealing.
 
620
 * \param coolexp The cooling exponent of the annealing.
 
621
 * \param kkconst The Kamada-Kawai vertex attraction constant.
 
622
 * \param use_seed Boolean, whether to use the values cupplied in the \p res 
 
623
 *     argument as the initial configuration. If zero then a random initial 
 
624
 *     configuration is used.
 
625
 * \return Error code.
 
626
 * 
 
627
 * Added in version 0.2.</para><para>
 
628
 * 
 
629
 * Time complexity: O(|V|^2) for each
 
630
 * iteration, |V| is the number of
 
631
 * vertices in the graph. 
 
632
 */
 
633
 
 
634
int igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matrix_t *res,
 
635
                                  igraph_integer_t niter, igraph_real_t sigma, 
 
636
                                  igraph_real_t initemp, igraph_real_t coolexp, 
 
637
                                  igraph_real_t kkconst, igraph_bool_t use_seed) {
 
638
  igraph_real_t temp, candx, candy, candz;
 
639
  igraph_real_t dpot, odis, ndis, osqd, nsqd;
 
640
  long int i,j,k;
 
641
  long int no_of_nodes=igraph_vcount(graph);
 
642
  igraph_matrix_t elen;
 
643
  
 
644
  RNG_BEGIN();
 
645
  
 
646
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 3));
 
647
  IGRAPH_MATRIX_INIT_FINALLY(&elen,  no_of_nodes, no_of_nodes);
 
648
  IGRAPH_CHECK(igraph_shortest_paths(graph, &elen, igraph_vss_all(), 
 
649
                                     IGRAPH_ALL));
 
650
  
 
651
  if (!use_seed) {
 
652
    for (i=0; i<no_of_nodes; i++) {
 
653
      MATRIX(elen, i, i) = sqrt(no_of_nodes);
 
654
      MATRIX(*res, i, 0) = RNG_NORMAL(0, no_of_nodes/4.0);
 
655
      MATRIX(*res, i, 1) = RNG_NORMAL(0, no_of_nodes/4.0);
 
656
      MATRIX(*res, i, 2) = RNG_NORMAL(0, no_of_nodes/4.0);
 
657
    }
 
658
  }
 
659
 
 
660
  temp=initemp;
 
661
  for(i=0;i<niter;i++){
 
662
    if (i%10 == 0)
 
663
      IGRAPH_PROGRESS("3D Kamada-Kawai layout: ",
 
664
                      100.0*i/niter, NULL);
 
665
 
 
666
    /*Update each vertex*/
 
667
    for(j=0;j<no_of_nodes;j++){
 
668
      IGRAPH_ALLOW_INTERRUPTION();
 
669
      /*Draw the candidate via a gaussian perturbation*/
 
670
      candx=RNG_NORMAL(MATRIX(*res, j, 0) ,sigma*temp/initemp);
 
671
      candy=RNG_NORMAL(MATRIX(*res, j, 1) ,sigma*temp/initemp);
 
672
      candz=RNG_NORMAL(MATRIX(*res, j, 2) ,sigma*temp/initemp);
 
673
      /*Calculate the potential difference for the new position*/
 
674
      dpot=0.0;
 
675
      for(k=0;k<no_of_nodes;k++) /*Potential differences for pairwise effects*/
 
676
        if(j!=k){
 
677
          odis=sqrt((MATRIX(*res, j, 0)-MATRIX(*res, k, 0))*
 
678
                    (MATRIX(*res, j, 0)-MATRIX(*res, k, 0))+
 
679
                    (MATRIX(*res, j, 1)-MATRIX(*res, k, 1))*
 
680
                    (MATRIX(*res, j, 1)-MATRIX(*res, k, 1))+
 
681
                    (MATRIX(*res, j, 2)-MATRIX(*res, k, 2))*
 
682
                    (MATRIX(*res, j, 2)-MATRIX(*res, k, 2)));
 
683
          ndis=sqrt((candx-MATRIX(*res, k, 0))*(candx-MATRIX(*res, k, 0))+
 
684
                    (candy-MATRIX(*res, k, 1))*(candy-MATRIX(*res, k, 1))+
 
685
                    (candz-MATRIX(*res, k, 2))*(candz-MATRIX(*res, k, 2)));
 
686
          osqd=(odis-MATRIX(elen, j, k))*(odis-MATRIX(elen, j, k));
 
687
          nsqd=(ndis-MATRIX(elen, j, k))*(ndis-MATRIX(elen, j, k));
 
688
          dpot+=kkconst*(osqd-nsqd)/(MATRIX(elen, j, k)*MATRIX(elen, j, k));
 
689
        }
 
690
      /*Make a keep/reject decision*/
 
691
      if(log(RNG_UNIF(0.0,1.0))<dpot/temp){
 
692
        MATRIX(*res, j, 0)=candx;
 
693
        MATRIX(*res, j, 1)=candy;
 
694
        MATRIX(*res, j, 2)=candz;
 
695
      }
 
696
    }
 
697
    /*Cool the system*/
 
698
    temp*=coolexp;
 
699
  }
 
700
 
 
701
  IGRAPH_PROGRESS("3D Kamada-Kawai layout: ", 100.0, NULL);
 
702
 
 
703
  RNG_END();
 
704
  igraph_matrix_destroy(&elen);
 
705
  IGRAPH_FINALLY_CLEAN(1);
 
706
 
 
707
  return 0;
 
708
}
 
709
 
 
710
int igraph_layout_springs(const igraph_t *graph, igraph_matrix_t *res,
 
711
                          igraph_real_t mass, igraph_real_t equil, igraph_real_t k,
 
712
                          igraph_real_t repeqdis, igraph_real_t kfr, igraph_bool_t repulse) {
 
713
  /* TODO */
 
714
  return 0;
 
715
}
 
716
 
 
717
void igraph_i_norm2d(igraph_real_t *x, igraph_real_t *y) {
 
718
  igraph_real_t len=sqrt((*x)*(*x) + (*y)*(*y));
 
719
  if (len != 0) {
 
720
    *x /= len;
 
721
    *y /= len;
 
722
  }
 
723
}
 
724
 
 
725
/**
 
726
 * \function igraph_layout_lgl
 
727
 * \brief Force based layout algorithm for large graphs.
 
728
 * 
 
729
 * </para><para>
 
730
 * This is a layout generator similar to the Large Graph Layout
 
731
 * algorithm and program
 
732
 * (http://bioinformatics.icmb.utexas.edu/lgl/). But unlike LGL, this
 
733
 * version uses a Fruchterman-Reingold style simulated annealing
 
734
 * algorithm for placing the vertices. The speedup is achived by
 
735
 * placing the vertices on a grid and calculating the repulsion only
 
736
 * for vertices which are closer to each other than a limit. 
 
737
 * 
 
738
 * \param graph The (initialized) graph object to place.
 
739
 * \param res Pointer to an initialized matrix object to hold the
 
740
 *   result. It will be resized if needed.
 
741
 * \param maxit The maximum number of cooling iterations to perform
 
742
 *   for each layout step.
 
743
 * \param maxdelta The maximum length of the move allowed for a vertex
 
744
 *   in a single iteration. 
 
745
 * \param area This parameter gives the area of the square on which
 
746
 *   the vertices will be placed.
 
747
 * \param coolexp The cooling exponent. 
 
748
 * \param repulserad Determines the radius at which vertex-vertex 
 
749
 *   repulsion cancels out attraction of adjacenct vertices.
 
750
 * \param cellsize The size of the grid cells, one side of the
 
751
 *   square. 
 
752
 * \param proot The root vertex, this is placed first, its neighbors
 
753
 *   in the first iteration, second neighbors in the second, etc. If
 
754
 *   negative then a random vertex is chosen.
 
755
 * \return Error code.
 
756
 * 
 
757
 * Added in version 0.2.</para><para>
 
758
 * 
 
759
 * Time complexity: ideally O(dia*maxit*(|V|+|E|)), |V| is the number
 
760
 * of vertices, 
 
761
 * dia is the diameter of the graph, worst case complexity is still 
 
762
 * O(dia*maxit*(|V|^2+|E|)), this is the case when all vertices happen to be
 
763
 * in the same grid cell. 
 
764
 */
 
765
 
 
766
int igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res,
 
767
                      igraph_integer_t maxit, igraph_real_t maxdelta, 
 
768
                      igraph_real_t area, igraph_real_t coolexp,
 
769
                      igraph_real_t repulserad, igraph_real_t cellsize, 
 
770
                      igraph_integer_t proot) {
 
771
  
 
772
  
 
773
  long int no_of_nodes=igraph_vcount(graph);
 
774
  long int no_of_edges=igraph_ecount(graph);
 
775
  igraph_t mst;
 
776
  long int root;
 
777
  long int no_of_layers, actlayer=0;
 
778
  igraph_vector_t vids;
 
779
  igraph_vector_t layers;
 
780
  igraph_vector_t parents;
 
781
  igraph_vector_t edges;
 
782
  igraph_2dgrid_t grid;  
 
783
  igraph_vector_t eids;
 
784
  igraph_vector_t forcex;
 
785
  igraph_vector_t forcey;
 
786
 
 
787
  igraph_real_t frk=sqrt(area/no_of_nodes);
 
788
  igraph_real_t H_n=0;
 
789
 
 
790
  IGRAPH_CHECK(igraph_minimum_spanning_tree_unweighted(graph, &mst));
 
791
  IGRAPH_FINALLY(igraph_destroy, &mst);
 
792
  
 
793
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 2));
 
794
  
 
795
  /* Determine the root vertex, random pick right now */
 
796
  if (proot < 0) {
 
797
    root=RNG_INTEGER(0, no_of_nodes-1);
 
798
  } else {
 
799
    root=proot;
 
800
  }
 
801
 
 
802
  /* Assign the layers */
 
803
  IGRAPH_VECTOR_INIT_FINALLY(&vids, 0);
 
804
  IGRAPH_VECTOR_INIT_FINALLY(&layers, 0);
 
805
  IGRAPH_VECTOR_INIT_FINALLY(&parents, 0);
 
806
  IGRAPH_CHECK(igraph_bfs(&mst, root, IGRAPH_ALL, &vids, &layers, &parents));
 
807
  no_of_layers=igraph_vector_size(&layers)-1;
 
808
  
 
809
  /* We don't need the mst any more */
 
810
  igraph_destroy(&mst);
 
811
  igraph_empty(&mst, 0, IGRAPH_UNDIRECTED); /* to make finalization work */
 
812
  
 
813
  IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
 
814
  IGRAPH_CHECK(igraph_vector_reserve(&edges, no_of_edges));
 
815
  IGRAPH_VECTOR_INIT_FINALLY(&eids, 0);
 
816
  IGRAPH_VECTOR_INIT_FINALLY(&forcex, no_of_nodes);
 
817
  IGRAPH_VECTOR_INIT_FINALLY(&forcey, no_of_nodes);
 
818
 
 
819
  /* Place the vertices randomly */
 
820
  IGRAPH_CHECK(igraph_layout_random(graph, res));
 
821
  igraph_matrix_scale(res, 1e6);
 
822
  
 
823
  /* This is the grid for calculating the vertices near to a given vertex */  
 
824
  IGRAPH_CHECK(igraph_2dgrid_init(&grid, res, 
 
825
                                  -sqrt(area/M_PI),sqrt(area/M_PI), cellsize,
 
826
                                  -sqrt(area/M_PI),sqrt(area/M_PI), cellsize));
 
827
  IGRAPH_FINALLY(igraph_2dgrid_destroy, &grid);
 
828
 
 
829
  /* Place the root vertex */
 
830
  igraph_2dgrid_add(&grid, root, 0, 0);
 
831
 
 
832
  for (actlayer=1; actlayer<no_of_layers; actlayer++) {
 
833
    H_n += 1.0/actlayer;
 
834
  }
 
835
 
 
836
  for (actlayer=1; actlayer<no_of_layers; actlayer++) {
 
837
 
 
838
    igraph_real_t c=1;
 
839
    long int i, j;
 
840
    igraph_real_t massx, massy;
 
841
    igraph_real_t px, py;
 
842
    igraph_real_t sx, sy;
 
843
 
 
844
    long int it=0;
 
845
    igraph_real_t epsilon=10e-6;
 
846
    igraph_real_t maxchange=epsilon+1;
 
847
    long int pairs;
 
848
    igraph_real_t sconst=sqrt(area/M_PI) / H_n; 
 
849
    igraph_2dgrid_iterator_t vidit;
 
850
 
 
851
/*     printf("Layer %li:\n", actlayer); */
 
852
    
 
853
    /*-----------------------------------------*/
 
854
    /* Step 1: place the next layer on spheres */
 
855
    /*-----------------------------------------*/
 
856
 
 
857
    RNG_BEGIN();
 
858
 
 
859
    j=VECTOR(layers)[actlayer];
 
860
    for (i=VECTOR(layers)[actlayer-1]; i<VECTOR(layers)[actlayer]; i++) {
 
861
 
 
862
      long int vid=VECTOR(vids)[i];
 
863
      long int par=VECTOR(parents)[vid];
 
864
      IGRAPH_ALLOW_INTERRUPTION();
 
865
      igraph_2dgrid_getcenter(&grid, &massx, &massy);
 
866
      igraph_i_norm2d(&massx, &massy);
 
867
      px=MATRIX(*res, vid, 0)-MATRIX(*res, par, 0);
 
868
      py=MATRIX(*res, vid, 1)-MATRIX(*res, par, 1);
 
869
      igraph_i_norm2d(&px, &py);
 
870
      sx=c*(massx+px)+MATRIX(*res, vid, 0);
 
871
      sy=c*(massy+py)+MATRIX(*res, vid, 1);
 
872
 
 
873
      /* The neighbors of 'vid' */
 
874
      while (j < VECTOR(layers)[actlayer+1] && 
 
875
             VECTOR(parents)[(long int)VECTOR(vids)[j]]==vid) {
 
876
        igraph_real_t rx, ry;
 
877
        if (actlayer==1) {
 
878
          igraph_real_t phi=2*M_PI/(VECTOR(layers)[2]-1)*(j-1);
 
879
          rx=cos(phi);
 
880
          ry=sin(phi);
 
881
        } else {
 
882
          rx=RNG_UNIF(-1,1);
 
883
          ry=RNG_UNIF(-1,1);
 
884
        }
 
885
        igraph_i_norm2d(&rx, &ry);
 
886
        rx = rx / actlayer * sconst;
 
887
        ry = ry / actlayer * sconst;
 
888
        igraph_2dgrid_add(&grid, VECTOR(vids)[j], sx+rx, sy+ry);
 
889
        j++; 
 
890
      }
 
891
    }
 
892
 
 
893
    RNG_END();
 
894
    
 
895
    /*-----------------------------------------*/
 
896
    /* Step 2: add the edges of the next layer */
 
897
    /*-----------------------------------------*/
 
898
 
 
899
    for (j=VECTOR(layers)[actlayer]; j<VECTOR(layers)[actlayer+1]; j++) {
 
900
      long int vid=VECTOR(vids)[j];
 
901
      long int k;
 
902
      IGRAPH_ALLOW_INTERRUPTION();
 
903
      IGRAPH_CHECK(igraph_adjacent(graph, &eids, vid, IGRAPH_ALL));
 
904
      for (k=0;k<igraph_vector_size(&eids);k++) {
 
905
        long int eid=VECTOR(eids)[k];
 
906
        igraph_integer_t from, to;
 
907
        igraph_edge(graph, eid, &from, &to);
 
908
        if ((from != vid && igraph_2dgrid_in(&grid, from)) ||
 
909
            (to   != vid && igraph_2dgrid_in(&grid, to))) {
 
910
          igraph_vector_push_back(&edges, eid);
 
911
        }
 
912
      }
 
913
    }
 
914
 
 
915
    /*-----------------------------------------*/
 
916
    /* Step 3: let the springs spring          */
 
917
    /*-----------------------------------------*/
 
918
    
 
919
    maxchange=epsilon+1;
 
920
    while (it < maxit && maxchange > epsilon) {
 
921
      long int j;
 
922
      igraph_real_t t=maxdelta*pow((maxit-it)/(double)maxit, coolexp);
 
923
      long int vid, nei;
 
924
 
 
925
          IGRAPH_PROGRESS("Large graph layout",
 
926
            100.0*((actlayer-1.0)/(no_of_layers-1.0)+((float)it)/(maxit*(no_of_layers-1.0))),
 
927
                0);
 
928
 
 
929
      /* init */
 
930
      igraph_vector_null(&forcex);
 
931
      igraph_vector_null(&forcey);
 
932
      maxchange=0;
 
933
      
 
934
      /* attractive "forces" along the edges */
 
935
      for (j=0; j<igraph_vector_size(&edges); j++) {
 
936
        igraph_integer_t from, to;
 
937
        igraph_real_t xd, yd, dist, force;
 
938
        IGRAPH_ALLOW_INTERRUPTION();
 
939
        igraph_edge(graph, VECTOR(edges)[j], &from, &to);
 
940
        xd=MATRIX(*res, (long int)from, 0)-MATRIX(*res, (long int)to, 0);
 
941
        yd=MATRIX(*res, (long int)from, 1)-MATRIX(*res, (long int)to, 1);
 
942
        dist=sqrt(xd*xd+yd*yd);
 
943
        if (dist != 0) { xd/=dist; yd/=dist; }
 
944
        force=dist*dist/frk;
 
945
        VECTOR(forcex)[(long int)from] -= xd*force;
 
946
        VECTOR(forcex)[(long int)to]   += xd*force;
 
947
        VECTOR(forcey)[(long int)from] -= yd*force;
 
948
        VECTOR(forcey)[(long int)to]   += yd*force;
 
949
      }
 
950
      
 
951
      /* repulsive "forces" of the vertices nearby */
 
952
      pairs=0;
 
953
      igraph_2dgrid_reset(&grid, &vidit);
 
954
      while ( (vid=igraph_2dgrid_next(&grid, &vidit)-1) != -1) {
 
955
        while ( (nei=igraph_2dgrid_next_nei(&grid, &vidit)-1) != -1) {
 
956
          igraph_real_t xd=MATRIX(*res, (long int)vid, 0)-
 
957
            MATRIX(*res, (long int)nei, 0);
 
958
          igraph_real_t yd=MATRIX(*res, (long int)vid, 1)-
 
959
            MATRIX(*res, (long int)nei, 1);
 
960
          igraph_real_t dist=sqrt(xd*xd+yd*yd);
 
961
          igraph_real_t force;
 
962
          if (dist < cellsize) {
 
963
            pairs++;
 
964
            if (dist==0) { dist=epsilon; };
 
965
            xd/=dist; yd/=dist;
 
966
            force=frk*frk*(1.0/dist-dist*dist/repulserad);
 
967
            VECTOR(forcex)[(long int)vid] += xd*force;
 
968
            VECTOR(forcex)[(long int)nei] -= xd*force;
 
969
            VECTOR(forcey)[(long int)vid] += yd*force;
 
970
            VECTOR(forcey)[(long int)nei] -= yd*force;      
 
971
          }
 
972
        }
 
973
      }
 
974
      
 
975
/*       printf("verties: %li iterations: %li\n",  */
 
976
/*           (long int) VECTOR(layers)[actlayer+1], pairs); */
 
977
      
 
978
      /* apply the changes */
 
979
      for (j=0; j<VECTOR(layers)[actlayer+1]; j++) {
 
980
        long int vid=VECTOR(vids)[j];
 
981
        igraph_real_t fx=VECTOR(forcex)[vid];
 
982
        igraph_real_t fy=VECTOR(forcey)[vid];
 
983
        igraph_real_t ded=sqrt(fx*fx+fy*fy);
 
984
        if (ded > t) {
 
985
          ded=t/ded;
 
986
          fx*=ded; fy *=ded;
 
987
        }
 
988
        igraph_2dgrid_move(&grid, vid, fx, fy);
 
989
        if (fx > maxchange) { maxchange=fx; }
 
990
        if (fy > maxchange) { maxchange=fy; }
 
991
      }
 
992
      it++;
 
993
/*       printf("%li iterations, maxchange: %f\n", it, (double)maxchange); */
 
994
    }
 
995
  }
 
996
 
 
997
  IGRAPH_PROGRESS("Large graph layout", 100.0, 0);
 
998
  igraph_destroy(&mst);
 
999
  igraph_vector_destroy(&vids);
 
1000
  igraph_vector_destroy(&layers);
 
1001
  igraph_vector_destroy(&parents);
 
1002
  igraph_vector_destroy(&edges);
 
1003
  igraph_2dgrid_destroy(&grid);
 
1004
  igraph_vector_destroy(&eids);
 
1005
  igraph_vector_destroy(&forcex);
 
1006
  igraph_vector_destroy(&forcey);
 
1007
  IGRAPH_FINALLY_CLEAN(9);
 
1008
  return 0;
 
1009
 
 
1010
}
 
1011
 
 
1012
/**
 
1013
 * \function igraph_layout_grid_fruchterman_reingold
 
1014
 * \brief Force based layout generator for large graphs.
 
1015
 * 
 
1016
 * </para><para>
 
1017
 * This algorithm is the same as the Fruchterman-Reingold layout
 
1018
 * generator, but it partitions the 2d space to a grid and and vertex
 
1019
 * repulsion is calculated only for vertices nearby.
 
1020
 *
 
1021
 * \param graph The graph object. 
 
1022
 * \param res The result, the coordinates in a matrix. The parameter
 
1023
 *   should point to an initialized matrix object and will be resized.
 
1024
 * \param niter Number of iterations to perform.
 
1025
 * \param maxdelta Maximum distance to move a vertex in an iteration.
 
1026
 * \param area The area of the square on which the vertices will be
 
1027
 *   placed.
 
1028
 * \param coolexp The cooling exponent.
 
1029
 * \param repulserad Determines the radius at which vertex-vertex 
 
1030
 *   repulsion cancels out attraction of adjacenct vertices.
 
1031
 * \param cellsize The size of the grid cells.
 
1032
 * \param use_seed Logical, if true, the coordinates passed in \p res
 
1033
 *   (should have the appropriate size) will be used for the first
 
1034
 *   iteration.
 
1035
 * \return Error code.
 
1036
 *
 
1037
 * Added in version 0.2.</para><para>
 
1038
 * 
 
1039
 * Time complexity: ideally (constant number of vertices in each cell) 
 
1040
 * O(niter*(|V|+|E|)), in the worst case O(niter*(|V|^2+|E|)).
 
1041
 */
 
1042
 
 
1043
int igraph_layout_grid_fruchterman_reingold(const igraph_t *graph, 
 
1044
                                            igraph_matrix_t *res,
 
1045
                                            igraph_integer_t niter, igraph_real_t maxdelta, 
 
1046
                                            igraph_real_t area, igraph_real_t coolexp,
 
1047
                                            igraph_real_t repulserad, 
 
1048
                                            igraph_real_t cellsize,
 
1049
                                            igraph_bool_t use_seed) {
 
1050
 
 
1051
  long int no_of_nodes=igraph_vcount(graph);
 
1052
  long int no_of_edges=igraph_ecount(graph);
 
1053
  igraph_2dgrid_t grid;  
 
1054
  igraph_vector_t forcex;
 
1055
  igraph_vector_t forcey;
 
1056
  long int i, it=0;
 
1057
  igraph_2dgrid_iterator_t vidit;  
 
1058
 
 
1059
  igraph_real_t frk=sqrt(area/no_of_nodes);
 
1060
 
 
1061
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 2));
 
1062
  IGRAPH_VECTOR_INIT_FINALLY(&forcex, no_of_nodes);
 
1063
  IGRAPH_VECTOR_INIT_FINALLY(&forcey, no_of_nodes);
 
1064
  
 
1065
  /* initial layout */
 
1066
  if (!use_seed) {
 
1067
    IGRAPH_CHECK(igraph_layout_random(graph, res));
 
1068
    igraph_matrix_scale(res, sqrt(area/M_PI));
 
1069
  }
 
1070
  
 
1071
  /* make grid */
 
1072
  IGRAPH_CHECK(igraph_2dgrid_init(&grid, res, 
 
1073
                                  -sqrt(area/M_PI),sqrt(area/M_PI), cellsize,
 
1074
                                  -sqrt(area/M_PI),sqrt(area/M_PI), cellsize));
 
1075
  IGRAPH_FINALLY(igraph_2dgrid_destroy, &grid);
 
1076
  
 
1077
  /* place vertices on grid */
 
1078
  for (i=0; i<no_of_nodes; i++) {
 
1079
    igraph_2dgrid_add2(&grid, i);
 
1080
  }
 
1081
 
 
1082
  while (it<niter) {
 
1083
    long int j;
 
1084
    igraph_real_t t=maxdelta*pow((niter-it)/(double)niter, coolexp);
 
1085
    long int vid, nei;
 
1086
 
 
1087
    /* Report progress */
 
1088
    if (it%10 == 0) {
 
1089
      IGRAPH_PROGRESS("Grid based Fruchterman-Reingold layout: ", 
 
1090
                      (100.0*it)/niter, NULL);
 
1091
    }
 
1092
 
 
1093
    igraph_vector_null(&forcex);
 
1094
    igraph_vector_null(&forcey);
 
1095
    
 
1096
    /* attraction */
 
1097
    for (j=0; j<no_of_edges; j++) {
 
1098
      igraph_integer_t from, to;
 
1099
      igraph_real_t xd, yd, dist, force;
 
1100
      igraph_edge(graph, j, &from, &to);
 
1101
      xd=MATRIX(*res, (long int)from, 0)-MATRIX(*res, (long int)to, 0);
 
1102
      yd=MATRIX(*res, (long int)from, 1)-MATRIX(*res, (long int)to, 1);
 
1103
      dist=sqrt(xd*xd+yd*yd);
 
1104
      if (dist != 0) { xd/=dist; yd/=dist; }
 
1105
      force=dist*dist/frk;
 
1106
      VECTOR(forcex)[(long int)from] -= xd*force;
 
1107
      VECTOR(forcex)[(long int)to]   += xd*force;
 
1108
      VECTOR(forcey)[(long int)from] -= yd*force;
 
1109
      VECTOR(forcey)[(long int)to]   += yd*force;
 
1110
    }
 
1111
 
 
1112
    /* repulsion */
 
1113
    igraph_2dgrid_reset(&grid, &vidit);
 
1114
    while ( (vid=igraph_2dgrid_next(&grid, &vidit)-1) != -1) {
 
1115
      IGRAPH_ALLOW_INTERRUPTION();
 
1116
      while ( (nei=igraph_2dgrid_next_nei(&grid, &vidit)-1) != -1) {
 
1117
        igraph_real_t xd=MATRIX(*res, (long int)vid, 0)-
 
1118
          MATRIX(*res, (long int)nei, 0);
 
1119
        igraph_real_t yd=MATRIX(*res, (long int)vid, 1)-
 
1120
          MATRIX(*res, (long int)nei, 1);
 
1121
        igraph_real_t dist=sqrt(xd*xd+yd*yd);
 
1122
        igraph_real_t force;
 
1123
        if (dist < cellsize) {
 
1124
          if (dist==0) { dist=1e-6; };
 
1125
          xd/=dist; yd/=dist;
 
1126
          force=frk*frk*(1.0/dist-dist*dist/repulserad);
 
1127
          VECTOR(forcex)[(long int)vid] += xd*force;
 
1128
          VECTOR(forcex)[(long int)nei] -= xd*force;
 
1129
          VECTOR(forcey)[(long int)vid] += yd*force;
 
1130
          VECTOR(forcey)[(long int)nei] -= yd*force;        
 
1131
        }
 
1132
      }
 
1133
    }
 
1134
 
 
1135
    /* update */
 
1136
    for (j=0; j<no_of_nodes; j++) {
 
1137
      long int vid=j;
 
1138
      igraph_real_t fx=VECTOR(forcex)[vid];
 
1139
      igraph_real_t fy=VECTOR(forcey)[vid];
 
1140
      igraph_real_t ded=sqrt(fx*fx+fy*fy);
 
1141
      if (ded > t) {
 
1142
        ded=t/ded;
 
1143
        fx*=ded; fy *=ded;
 
1144
      }
 
1145
      igraph_2dgrid_move(&grid, vid, fx, fy);
 
1146
    }
 
1147
    it++;
 
1148
    
 
1149
  } /* it<niter */
 
1150
  
 
1151
  IGRAPH_PROGRESS("Grid based Fruchterman-Reingold layout: ", 
 
1152
                  100.0, NULL);
 
1153
 
 
1154
  igraph_vector_destroy(&forcex);
 
1155
  igraph_vector_destroy(&forcey);
 
1156
  igraph_2dgrid_destroy(&grid);
 
1157
  IGRAPH_FINALLY_CLEAN(3);
 
1158
  return 0;
 
1159
}
 
1160
 
 
1161
/* Internal structure for Reingold-Tilford layout */
 
1162
struct igraph_i_reingold_tilford_vertex {
 
1163
  long int parent;        /* Parent node index */
 
1164
  long int level;         /* Level of the node */
 
1165
  igraph_real_t offset;     /* X offset from parent node */
 
1166
  long int left_contour;  /* Next left node of the contour
 
1167
                      of the subtree rooted at this node */
 
1168
  long int right_contour; /* Next right node of the contour
 
1169
                      of the subtree rooted at this node */
 
1170
  igraph_real_t offset_follow_lc;  /* X offset when following the left contour */
 
1171
  igraph_real_t offset_follow_rc;  /* X offset when following the right contour */
 
1172
};
 
1173
 
 
1174
int igraph_i_layout_reingold_tilford_postorder(struct igraph_i_reingold_tilford_vertex *vdata,
 
1175
                                               long int node, long int vcount);
 
1176
int igraph_i_layout_reingold_tilford_calc_coords(struct igraph_i_reingold_tilford_vertex *vdata,
 
1177
                                                 igraph_matrix_t *res, long int node,
 
1178
                                                                                                 long int vcount, igraph_real_t xpos);
 
1179
 
 
1180
/**
 
1181
 * \function igraph_layout_reingold_tilford
 
1182
 * \brief Reingold-Tilford layout for tree graphs
 
1183
 * 
 
1184
 * </para><para>
 
1185
 * Arranges the nodes in a tree where the given node is used as the root.
 
1186
 * The tree is directed downwards and the parents are centered above its
 
1187
 * children. For the exact algorithm, see:
 
1188
 * 
 
1189
 * </para><para>
 
1190
 * Reingold, E and Tilford, J: Tidier drawing of trees.
 
1191
 * IEEE Trans. Softw. Eng., SE-7(2):223--228, 1981
 
1192
 *
 
1193
 * </para><para>
 
1194
 * If the given graph is not a tree, a breadth-first search is executed
 
1195
 * first to obtain a possible spanning tree.
 
1196
 * 
 
1197
 * \param graph The graph object. 
 
1198
 * \param res The result, the coordinates in a matrix. The parameter
 
1199
 *   should point to an initialized matrix object and will be resized.
 
1200
 * \param root The index of the root vertex.
 
1201
 * \return Error code.
 
1202
 *
 
1203
 * Added in version 0.2.
 
1204
 * 
 
1205
 * </para><para>
 
1206
 * TODO: decompose and merge for not fully connected graphs
 
1207
 * TODO: possible speedup could be achieved if we use a table for storing
 
1208
 * the children of each node in the tree. (Now the implementation uses a
 
1209
 * single array containing the parent of each node and a node's children
 
1210
 * are determined by looking for other nodes that have this node as parent)
 
1211
 * 
 
1212
 * \sa \ref igraph_layout_reingold_tilford_circular().
 
1213
 */
 
1214
int igraph_layout_reingold_tilford(const igraph_t *graph, 
 
1215
                                   igraph_matrix_t *res, long int root) {
 
1216
  long int no_of_nodes=igraph_vcount(graph);
 
1217
  long int i, n, j;
 
1218
  igraph_dqueue_t q=IGRAPH_DQUEUE_NULL;
 
1219
  igraph_adjlist_t allneis;
 
1220
  igraph_vector_t *neis;
 
1221
  struct igraph_i_reingold_tilford_vertex *vdata;
 
1222
  
 
1223
  if (root<0 || root>=no_of_nodes) {
 
1224
    IGRAPH_ERROR("invalid vertex id", IGRAPH_EINVVID);
 
1225
  }
 
1226
  
 
1227
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, 2));
 
1228
  IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
 
1229
  
 
1230
  IGRAPH_CHECK(igraph_adjlist_init(graph, &allneis, IGRAPH_ALL));
 
1231
  IGRAPH_FINALLY(igraph_adjlist_destroy, &allneis);
 
1232
  
 
1233
  vdata=igraph_Calloc(no_of_nodes, struct igraph_i_reingold_tilford_vertex);
 
1234
  if (vdata==0) {
 
1235
    IGRAPH_ERROR("igraph_layout_reingold_tilford failed", IGRAPH_ENOMEM);
 
1236
  }
 
1237
  IGRAPH_FINALLY(igraph_free, vdata);
 
1238
 
 
1239
  for (i=0; i<no_of_nodes; i++) {
 
1240
    vdata[i].parent=-1;
 
1241
    vdata[i].level=-1;
 
1242
    vdata[i].offset=0.0;
 
1243
    vdata[i].left_contour=-1;
 
1244
    vdata[i].right_contour=-1;
 
1245
    vdata[i].offset_follow_lc=0.0;
 
1246
    vdata[i].offset_follow_rc=0.0;
 
1247
  }
 
1248
  vdata[root].parent=root;
 
1249
  vdata[root].level=0;
 
1250
  MATRIX(*res, root, 1) = 0;
 
1251
  
 
1252
  /* Step 1: assign Y coordinates based on BFS and setup parents vector */
 
1253
  IGRAPH_CHECK(igraph_dqueue_push(&q, root));
 
1254
  IGRAPH_CHECK(igraph_dqueue_push(&q, 0));
 
1255
  while (!igraph_dqueue_empty(&q)) {
 
1256
    long int actnode=igraph_dqueue_pop(&q);
 
1257
    long int actdist=igraph_dqueue_pop(&q);
 
1258
    neis=igraph_adjlist_get(&allneis, actnode);
 
1259
    n=igraph_vector_size(neis);
 
1260
    for (j=0; j<n; j++) {
 
1261
      long int neighbor=VECTOR(*neis)[j];
 
1262
      if (vdata[neighbor].parent >= 0) { continue; }
 
1263
      MATRIX(*res, neighbor, 1)=actdist+1;
 
1264
      IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
 
1265
      IGRAPH_CHECK(igraph_dqueue_push(&q, actdist+1));
 
1266
      vdata[neighbor].parent = actnode;
 
1267
      vdata[neighbor].level = actdist+1;
 
1268
    }
 
1269
  }
 
1270
  
 
1271
  /* Step 2: postorder tree traversal, determines the appropriate X
 
1272
   * offsets for every node */
 
1273
  igraph_i_layout_reingold_tilford_postorder(vdata, root, no_of_nodes);
 
1274
  
 
1275
  /* Step 3: calculate real coordinates based on X offsets */
 
1276
  igraph_i_layout_reingold_tilford_calc_coords(vdata, res, root, no_of_nodes, vdata[root].offset);
 
1277
  
 
1278
  igraph_dqueue_destroy(&q);
 
1279
  igraph_adjlist_destroy(&allneis);
 
1280
  igraph_free(vdata);
 
1281
  IGRAPH_FINALLY_CLEAN(3);
 
1282
  
 
1283
  IGRAPH_PROGRESS("Reingold-Tilford tree layout", 100.0, NULL);
 
1284
  
 
1285
  return 0;
 
1286
}
 
1287
 
 
1288
int igraph_i_layout_reingold_tilford_calc_coords(struct igraph_i_reingold_tilford_vertex *vdata,
 
1289
                                                 igraph_matrix_t *res, long int node,
 
1290
                                                                                                 long int vcount, igraph_real_t xpos) {
 
1291
  long int i, n;
 
1292
  MATRIX(*res, node, 0) = xpos;
 
1293
  for (i=0, n=0; i<vcount; i++) {
 
1294
    if (i == node) continue;
 
1295
    if (vdata[i].parent == node) {
 
1296
      igraph_i_layout_reingold_tilford_calc_coords(vdata, res, i, vcount,
 
1297
                                                   xpos+vdata[i].offset);
 
1298
    }
 
1299
  }
 
1300
  return 0;
 
1301
}
 
1302
 
 
1303
int igraph_i_layout_reingold_tilford_postorder(struct igraph_i_reingold_tilford_vertex *vdata,
 
1304
                                               long int node, long int vcount) {
 
1305
  long int i, j, childcount, leftroot, leftrootidx, leftleftroot;
 
1306
  igraph_real_t avg;
 
1307
  
 
1308
  /* printf("Starting visiting node %d\n", node); */
 
1309
  
 
1310
  /* Check whether this node is a leaf node */
 
1311
  childcount=0;
 
1312
  for (i=0; i<vcount; i++) {
 
1313
    if (i == node) continue;
 
1314
    if (vdata[i].parent == node) {
 
1315
      /* Node i is a child, so visit it recursively */
 
1316
      childcount++;
 
1317
      igraph_i_layout_reingold_tilford_postorder(vdata, i, vcount);
 
1318
    }
 
1319
  }
 
1320
  
 
1321
  if (childcount == 0) return 0;
 
1322
  
 
1323
  /* Here we can assume that all of the subtrees have been placed and their
 
1324
   * left and right contours are calculated. Let's place them next to each
 
1325
   * other as close as we can.
 
1326
   * We will take each subtree in an arbitrary order. The root of the
 
1327
   * first one will be placed at offset 0, the next ones will be placed
 
1328
   * as close to each other as possible. leftroot stores the root of the
 
1329
   * rightmost subtree of the already placed subtrees - its right contour
 
1330
   * will be checked against the left contour of the next subtree */
 
1331
  leftleftroot=leftroot=leftrootidx=-1;
 
1332
  avg=0.0;
 
1333
  /*printf("Visited node %d and arranged its subtrees\n", node);*/
 
1334
  for (i=0, j=0; i<vcount; i++) {
 
1335
    if (i == node) continue;
 
1336
    if (vdata[i].parent == node) {
 
1337
      /*printf("  Placing child %d on level %d\n", i, vdata[i].level);*/
 
1338
      if (leftroot >= 0) {
 
1339
        /* Now we will follow the right contour of leftroot and the
 
1340
         * left contour of the subtree rooted at i */
 
1341
        long lnode, rnode;
 
1342
        igraph_real_t loffset, roffset, minsep, rootsep;
 
1343
        lnode = leftroot; rnode = i;
 
1344
        minsep = 1;
 
1345
        rootsep = vdata[leftroot].offset + minsep;
 
1346
        loffset = 0; roffset = minsep;
 
1347
        /*printf("    Contour: [%d, %d], offsets: [%lf, %lf], rootsep: %lf\n",
 
1348
               lnode, rnode, loffset, roffset, rootsep);*/
 
1349
        while ((lnode >= 0) && (rnode >= 0)) {
 
1350
          /* Step to the next level on the right contour of the left subtree */
 
1351
          if (vdata[lnode].right_contour >= 0) {
 
1352
            loffset += vdata[lnode].offset_follow_rc;
 
1353
            lnode = vdata[lnode].right_contour;
 
1354
          } else {
 
1355
            /* Left subtree ended there. The right contour of the left subtree
 
1356
             * will continue to the next step on the right subtree. */
 
1357
            if (vdata[rnode].left_contour >= 0) {
 
1358
              /*printf("      Left subtree ended, continuing left subtree's left and right contour on right subtree (node %ld)\n", vdata[rnode].left_contour);*/
 
1359
              vdata[lnode].left_contour = vdata[rnode].left_contour;
 
1360
              vdata[lnode].right_contour = vdata[rnode].left_contour;
 
1361
              vdata[lnode].offset_follow_lc = vdata[lnode].offset_follow_rc =
 
1362
                (roffset-loffset)+vdata[rnode].offset_follow_lc;
 
1363
              /*printf("      vdata[lnode].offset_follow_* = %.4f\n", vdata[lnode].offset_follow_lc);*/
 
1364
            }
 
1365
            lnode = -1;
 
1366
          }
 
1367
          /* Step to the next level on the left contour of the right subtree */
 
1368
          if (vdata[rnode].left_contour >= 0) {
 
1369
            roffset += vdata[rnode].offset_follow_lc;
 
1370
            rnode = vdata[rnode].left_contour;
 
1371
          } else {
 
1372
            /* Right subtree ended here. The left contour of the right
 
1373
             * subtree will continue to the next step on the left subtree.
 
1374
             * Note that lnode has already been advanced here */
 
1375
            if (lnode >= 0) {
 
1376
              /*printf("      Right subtree ended, continuing right subtree's left and right contour on left subtree (node %ld)\n", lnode);*/
 
1377
              vdata[rnode].left_contour = lnode;
 
1378
              vdata[rnode].right_contour = lnode;
 
1379
              vdata[rnode].offset_follow_lc = vdata[rnode].offset_follow_rc =
 
1380
                (loffset-roffset);  /* loffset has also been increased earlier */
 
1381
              /*printf("      vdata[rnode].offset_follow_* = %.4f\n", vdata[rnode].offset_follow_lc);*/
 
1382
            }
 
1383
            rnode = -1;
 
1384
          }
 
1385
          /*printf("    Contour: [%d, %d], offsets: [%lf, %lf], rootsep: %lf\n", 
 
1386
                 lnode, rnode, loffset, roffset, rootsep);*/
 
1387
      
 
1388
          /* Push subtrees away if necessary */
 
1389
          if ((lnode >= 0) && (rnode >= 0) && (roffset - loffset < minsep)) {
 
1390
            /*printf("    Pushing right subtree away by %lf\n", minsep-roffset+loffset);*/
 
1391
            rootsep += minsep-roffset+loffset;
 
1392
            roffset = loffset+minsep;
 
1393
          }
 
1394
        }
 
1395
 
 
1396
        /*printf("  Offset of subtree with root node %d will be %lf\n", i, rootsep);*/
 
1397
        vdata[i].offset = rootsep;
 
1398
        vdata[node].right_contour = i;
 
1399
        vdata[node].offset_follow_rc = rootsep;
 
1400
        avg = (avg*j)/(j+1) + rootsep/(j+1);
 
1401
        leftrootidx=j;
 
1402
        leftroot=i;
 
1403
      } else {
 
1404
        leftrootidx=j;
 
1405
        leftroot=i;
 
1406
        vdata[node].left_contour=i;
 
1407
        vdata[node].right_contour=i;
 
1408
        vdata[node].offset_follow_lc = 0.0;
 
1409
        vdata[node].offset_follow_rc = 0.0;
 
1410
        avg = vdata[i].offset; 
 
1411
      }
 
1412
      j++;
 
1413
    }
 
1414
  }
 
1415
  /*printf("Shifting node to be centered above children. Shift amount: %lf\n", avg);*/
 
1416
  vdata[node].offset_follow_lc -= avg;
 
1417
  vdata[node].offset_follow_rc -= avg;
 
1418
  for (i=0, j=0; i<vcount; i++) {
 
1419
    if (i == node) continue;
 
1420
    if (vdata[i].parent == node) vdata[i].offset -= avg;
 
1421
  }
 
1422
  
 
1423
  return 0;
 
1424
}
 
1425
 
 
1426
/** 
 
1427
 * \function igraph_layout_reingold_tilford_circular
 
1428
 * \brief Circular Reingold-Tilford layout for trees
 
1429
 * 
 
1430
 * </para><para>
 
1431
 * This layout is almost the same as \ref igraph_layout_reingold_tilford(), but 
 
1432
 * the tree is drawn in a circular way, with the root vertex in the center.
 
1433
 * 
 
1434
 * \param graph The graph object.
 
1435
 * \param res The result, the coordinates in a matrix. The parameter
 
1436
 *   should point to an initialized matrix object and will be resized.
 
1437
 * \param root The index of the root vertex.
 
1438
 * \return Error code.
 
1439
 *
 
1440
 * \sa \ref igraph_layout_reingold_tilford().
 
1441
 */
 
1442
 
 
1443
int igraph_layout_reingold_tilford_circular(const igraph_t *graph,
 
1444
                                            igraph_matrix_t *res, long int root) {
 
1445
  
 
1446
  long int no_of_nodes=igraph_vcount(graph);
 
1447
  long int i;
 
1448
  igraph_real_t ratio=2*M_PI*(no_of_nodes-1.0)/no_of_nodes;
 
1449
  igraph_real_t minx, maxx;
 
1450
 
 
1451
  IGRAPH_CHECK(igraph_layout_reingold_tilford(graph, res, root));
 
1452
 
 
1453
  if (no_of_nodes == 0) return 0;
 
1454
 
 
1455
  minx = maxx = MATRIX(*res, 0, 0);
 
1456
  for (i=1; i<no_of_nodes; i++) {
 
1457
    if (MATRIX(*res, i, 0) > maxx) maxx=MATRIX(*res, i, 0);
 
1458
        if (MATRIX(*res, i, 0) < minx) minx=MATRIX(*res, i, 0);
 
1459
  }
 
1460
  ratio /= (maxx-minx);
 
1461
  for (i=0; i<no_of_nodes; i++) {
 
1462
    igraph_real_t phi=(MATRIX(*res, i, 0)-minx)*ratio;
 
1463
    igraph_real_t r=MATRIX(*res, i, 1);
 
1464
    MATRIX(*res, i, 0) = r*cos(phi);
 
1465
    MATRIX(*res, i, 1) = r*sin(phi);
 
1466
  }
 
1467
  
 
1468
  return 0;
 
1469
}
 
1470
 
 
1471
#define COULOMBS_CONSTANT 8987500000.0
 
1472
 
 
1473
igraph_real_t igraph_i_distance_between(const igraph_matrix_t *c, long int a, 
 
1474
                                        long int b) {
 
1475
  igraph_real_t diffx=MATRIX(*c, a, 0)-MATRIX(*c, b, 0);
 
1476
  igraph_real_t diffy=MATRIX(*c, a, 1)-MATRIX(*c, b, 1);
 
1477
  return sqrt( diffx*diffx + diffy*diffy );
 
1478
 
1479
 
 
1480
int igraph_i_determine_electric_axal_forces(const igraph_matrix_t *pos,
 
1481
                                            igraph_real_t *x,
 
1482
                                            igraph_real_t *y,
 
1483
                                            igraph_real_t directed_force,
 
1484
                                            igraph_real_t distance,
 
1485
                                            long int other_node,
 
1486
                                            long int this_node) {
 
1487
  
 
1488
  // We know what the directed force is.  We now need to translate it
 
1489
  // into the appropriate x and y componenets.
 
1490
  // First, assume: 
 
1491
  //                 other_node
 
1492
  //                    /|
 
1493
  //  directed_force  /  |
 
1494
  //                /    | y
 
1495
  //              /______|
 
1496
  //    this_node     x         
 
1497
  //
 
1498
  // other_node.x > this_node.x
 
1499
  // other_node.y > this_node.y
 
1500
  // the force will be on this_node away from other_node
 
1501
  
 
1502
  // the proportion (distance/y_distance) is equal to the proportion
 
1503
  // (directed_force/y_force), as the two triangles are similar.
 
1504
  // therefore, the magnitude of y_force = (directed_force*y_distance)/distance
 
1505
  // the sign of y_force is negative, away from other_node
 
1506
  
 
1507
  igraph_real_t x_distance, y_distance;
 
1508
  y_distance = MATRIX(*pos, other_node, 1)-MATRIX(*pos, this_node, 1);
 
1509
  if (y_distance < 0) { y_distance = -y_distance; }
 
1510
  *y = -1 * ((directed_force * y_distance) / distance);
 
1511
 
 
1512
  // the x component works in exactly the same way.
 
1513
  x_distance = MATRIX(*pos, other_node, 0)-MATRIX(*pos, this_node, 0);
 
1514
  if (x_distance < 0) { x_distance = -x_distance; }
 
1515
  *x = -1 * ((directed_force * x_distance) / distance);
 
1516
  
 
1517
   // Now we need to reverse the polarity of our answers based on the falsness
 
1518
   // of our assumptions.
 
1519
  if (MATRIX(*pos, other_node, 0) < MATRIX(*pos, this_node, 0)) {
 
1520
    *x = *x * -1;
 
1521
  }
 
1522
  if (MATRIX(*pos, other_node, 1) < MATRIX(*pos, this_node, 1)) {
 
1523
    *y = *y * -1;
 
1524
  }
 
1525
  
 
1526
  return 0;
 
1527
}
 
1528
  
 
1529
int igraph_i_apply_electrical_force(const igraph_matrix_t *pos,
 
1530
                                    igraph_vector_t *pending_forces_x,
 
1531
                                    igraph_vector_t *pending_forces_y,
 
1532
                                    long int other_node, long int this_node,
 
1533
                                    igraph_real_t node_charge, 
 
1534
                                    igraph_real_t distance) {
 
1535
 
 
1536
  igraph_real_t directed_force = COULOMBS_CONSTANT * 
 
1537
    ((node_charge * node_charge)/(distance * distance));
 
1538
  
 
1539
  igraph_real_t x_force, y_force;
 
1540
  igraph_i_determine_electric_axal_forces(pos, &x_force, &y_force, 
 
1541
                                          directed_force, distance, 
 
1542
                                          other_node, this_node);
 
1543
 
 
1544
  VECTOR(*pending_forces_x)[this_node] += x_force;
 
1545
  VECTOR(*pending_forces_y)[this_node] += y_force;
 
1546
  VECTOR(*pending_forces_x)[other_node] -= x_force;
 
1547
  VECTOR(*pending_forces_y)[other_node] -= y_force;
 
1548
 
 
1549
  return 0;
 
1550
}
 
1551
 
 
1552
int igraph_i_determine_spring_axal_forces(const igraph_matrix_t *pos,
 
1553
                                          igraph_real_t *x, igraph_real_t *y,
 
1554
                                          igraph_real_t directed_force,
 
1555
                                          igraph_real_t distance,
 
1556
                                          int spring_length,
 
1557
                                          long int other_node, long int this_node) {
 
1558
 
 
1559
  // if the spring is just the right size, the forces will be 0, so we can
 
1560
  // skip the computation.
 
1561
  //
 
1562
  // if the spring is too long, our forces will be identical to those computed
 
1563
  // by determine_electrical_axal_forces() (this_node will be pulled toward
 
1564
  // other_node).
 
1565
  //
 
1566
  // if the spring is too short, our forces will be the opposite of those
 
1567
  // computed by determine_electrical_axal_forces() (this_node will be pushed
 
1568
  // away from other_node)
 
1569
  //
 
1570
  // finally, since both nodes are movable, only one-half of the total force
 
1571
  // should be applied to each node, so half the forces for our answer.
 
1572
  
 
1573
  if (distance == spring_length) {
 
1574
    *x = 0.0;
 
1575
    *y = 0.0;
 
1576
  } else {
 
1577
    igraph_i_determine_electric_axal_forces(pos, x, y, directed_force, distance, 
 
1578
                                            other_node, this_node);
 
1579
    if (distance < spring_length) {
 
1580
      *x = -1 * *x;
 
1581
      *y = -1 * *y;
 
1582
    }
 
1583
    *x = 0.5 * *x;
 
1584
    *y = 0.5 * *y;
 
1585
  }
 
1586
  
 
1587
  return 0;
 
1588
}
 
1589
 
 
1590
int igraph_i_apply_spring_force(const igraph_matrix_t *pos, 
 
1591
                                igraph_vector_t *pending_forces_x,
 
1592
                                igraph_vector_t *pending_forces_y,
 
1593
                                long int other_node,
 
1594
                                long int this_node, int spring_length,
 
1595
                                igraph_real_t spring_constant) {
 
1596
 
 
1597
  // determined using Hooke's Law:
 
1598
  //   force = -kx
 
1599
  // where:
 
1600
  //   k = spring constant
 
1601
  //   x = displacement from ideal length in meters
 
1602
  
 
1603
  igraph_real_t distance, displacement, directed_force, x_force, y_force;
 
1604
  distance = igraph_i_distance_between(pos, other_node, this_node);
 
1605
  // let's protect ourselves from division by zero by ignoring two nodes that
 
1606
  // happen to be in the same place.  Since we separate all nodes before we
 
1607
  // work on any of them, this will only happen in extremely rare circumstances,
 
1608
  // and when it does, electrical force will probably push one or both of them
 
1609
   // one way or another anyway.
 
1610
  if (distance == 0.0) {
 
1611
    return 0;
 
1612
  }
 
1613
  
 
1614
  displacement = distance - spring_length;
 
1615
  if (displacement < 0) {
 
1616
    displacement = -displacement;
 
1617
  }
 
1618
  directed_force = -1 * spring_constant * displacement;
 
1619
  // remember, this is force directed away from the spring;
 
1620
  // a negative number is back towards the spring (or, in our case, back towards
 
1621
   // the other node)
 
1622
  
 
1623
  // get the force that should be applied to >this< node
 
1624
  igraph_i_determine_spring_axal_forces(pos, &x_force, &y_force, 
 
1625
                                        directed_force, distance, spring_length,
 
1626
                                        other_node, this_node);
 
1627
  
 
1628
  VECTOR(*pending_forces_x)[this_node] += x_force;
 
1629
  VECTOR(*pending_forces_y)[this_node] += y_force;
 
1630
  VECTOR(*pending_forces_x)[other_node] -= x_force;
 
1631
  VECTOR(*pending_forces_y)[other_node] -= y_force;
 
1632
 
 
1633
  return 0;
 
1634
}
 
1635
 
 
1636
int igraph_i_move_nodes(igraph_matrix_t *pos, 
 
1637
                        const igraph_vector_t *pending_forces_x, 
 
1638
                        const igraph_vector_t *pending_forces_y,
 
1639
                        igraph_real_t node_mass,
 
1640
                        igraph_real_t max_sa_movement) {
 
1641
  
 
1642
  // Since each iteration is isolated, time is constant at 1.
 
1643
  // Therefore:
 
1644
  //   Force effects acceleration.
 
1645
  //   acceleration (d(velocity)/time) = velocity
 
1646
  //   velocity (d(displacement)/time) = displacement
 
1647
  //   displacement = acceleration
 
1648
  
 
1649
  // determined using Newton's second law:
 
1650
  //   sum(F) = ma
 
1651
  // therefore:
 
1652
  //   acceleration = force / mass
 
1653
  //   velocity     = force / mass
 
1654
  //   displacement = force / mass
 
1655
 
 
1656
  long int this_node, no_of_nodes=igraph_vector_size(pending_forces_x);
 
1657
 
 
1658
  for (this_node=0; this_node < no_of_nodes; this_node++) {
 
1659
 
 
1660
    igraph_real_t x_movement, y_movement;
 
1661
 
 
1662
    x_movement = VECTOR(*pending_forces_x)[this_node] / node_mass;
 
1663
    if (x_movement > max_sa_movement) {
 
1664
      x_movement = max_sa_movement;
 
1665
    } else if (x_movement < -max_sa_movement) {
 
1666
      x_movement = -max_sa_movement;
 
1667
    }
 
1668
 
 
1669
    y_movement = VECTOR(*pending_forces_y)[this_node] / node_mass;
 
1670
    if (y_movement > max_sa_movement) {
 
1671
      y_movement = max_sa_movement;
 
1672
    } else if (y_movement < -max_sa_movement) {
 
1673
      y_movement = -max_sa_movement;
 
1674
    }
 
1675
 
 
1676
    MATRIX(*pos, this_node, 0) += x_movement;
 
1677
    MATRIX(*pos, this_node, 1) += y_movement;
 
1678
 
 
1679
  }
 
1680
  return 0;
 
1681
}
 
1682
 
 
1683
/**
 
1684
 * \function igraph_layout_graphopt
 
1685
 * \brief Optimizes vertex layout via the graphopt algorithm.
 
1686
 * 
 
1687
 * </para><para>
 
1688
 * This is a port of the graphopt layout algorithm by Michael Schmuhl.
 
1689
 * graphopt version 0.4.1 was rewritten in C and the support for 
 
1690
 * layers was removed (might be added later) and a code was a bit 
 
1691
 * reorganized to avoid some unneccessary steps is the node charge (see below) 
 
1692
 * is zero.
 
1693
 * 
 
1694
 * </para><para>
 
1695
 * graphopt uses physical analogies for defining attracting and repelling 
 
1696
 * forces among the vertices and then the physical system is simulated 
 
1697
 * until it reaches an equilibrium. (There is no simulated annealing or 
 
1698
 * anything like that, so a stable fixed point is not guaranteed.)
 
1699
 * 
 
1700
 * </para><para>
 
1701
 * See also http://www.schmuhl.org/graphopt/ for the original graphopt.
 
1702
 * \param graph The input graph.
 
1703
 * \param res Pointer to an initialized matrix, the result will be stored here
 
1704
 *    and its initial contents is used the starting point of the simulation
 
1705
 *    if the \p use_seed argument is true. Note that in this case the 
 
1706
 *    matrix should have the proper size, otherwise a warning is issued and 
 
1707
 *    the supplied values are ignored. If no starting positions are given 
 
1708
 *    (or they are invalid) then a random staring position is used. 
 
1709
 *    The matrix will be resized if needed.
 
1710
 * \param niter Integer constant, the number of iterations to perform.
 
1711
 *    Should be a couple of hundred in general. If you have a large graph 
 
1712
 *    then you might want to only do a few iterations and then check the 
 
1713
 *    result. If it is not good enough you can feed it in again in 
 
1714
 *    the \p res argument. The original graphopt default if 500.
 
1715
 * \param node_charge The charge of the vertices, used to calculate electric
 
1716
 *    repulsion. The original graphopt default is 0.001.
 
1717
 * \param node_mass The mass of the vertices, used for the spring forces.
 
1718
 *    The original graphopt defaults to 30.
 
1719
 * \param spring_length The length of the springs, an integer number.
 
1720
 *    The original graphopt defaults to zero.
 
1721
 * \param spring_constant The spring constant, the original graphopt defaults 
 
1722
 *    to one.
 
1723
 * \param max_sa_movement Real constant, it gives the maximum amount of movement 
 
1724
 *    allowed in a single step along a single axis. The original graphopt 
 
1725
 *    default is 5.
 
1726
 * \param use_seed Logical scalar, whether to use the positions in \p res as
 
1727
 *    a starting configuration. See also \p res above.
 
1728
 * \return Error code.
 
1729
 * 
 
1730
 * Time complexity: O(n (|V|^2+|E|) ), n is the number of iterations, 
 
1731
 * |V| is the number of vertices, |E| the number
 
1732
 * of edges. If \p node_charge is zero then it is only O(n|E|).
 
1733
 */
 
1734
 
 
1735
int igraph_layout_graphopt(const igraph_t *graph, igraph_matrix_t *res, 
 
1736
                           igraph_integer_t niter,
 
1737
                           igraph_real_t node_charge, igraph_real_t node_mass,
 
1738
                           igraph_integer_t spring_length,
 
1739
                           igraph_real_t spring_constant, 
 
1740
                           igraph_real_t max_sa_movement,
 
1741
                           igraph_bool_t use_seed) {
 
1742
 
 
1743
  long int no_of_nodes=igraph_vcount(graph);
 
1744
  long int no_of_edges=igraph_ecount(graph);
 
1745
  int my_spring_length=spring_length;
 
1746
  igraph_vector_t pending_forces_x, pending_forces_y;
 
1747
  /* Set a flag to calculate (or not) the electrical forces that the nodes */
 
1748
  /* apply on each other based on if both node types' charges are zero. */
 
1749
  igraph_bool_t apply_electric_charges= (node_charge!=0);
 
1750
  
 
1751
  long int this_node, other_node, edge;
 
1752
  igraph_real_t distance;
 
1753
  long int i;
 
1754
 
 
1755
  IGRAPH_VECTOR_INIT_FINALLY(&pending_forces_x, no_of_nodes);
 
1756
  IGRAPH_VECTOR_INIT_FINALLY(&pending_forces_y, no_of_nodes);
 
1757
  
 
1758
  if (use_seed) {
 
1759
    if (igraph_matrix_nrow(res) != no_of_nodes ||
 
1760
        igraph_matrix_ncol(res) != 2) {
 
1761
      IGRAPH_WARNING("Invalid size for initial matrix, starting from random layout");
 
1762
      IGRAPH_CHECK(igraph_layout_random(graph, res));
 
1763
    }
 
1764
  } else {
 
1765
    IGRAPH_CHECK(igraph_layout_random(graph, res));
 
1766
  }
 
1767
 
 
1768
  IGRAPH_PROGRESS("Graphopt layout", 0, NULL);
 
1769
  for(i=niter;i>0;i--) {
 
1770
    /* Report progress in approx. every 100th step */
 
1771
    if (i%10 == 0) {
 
1772
      IGRAPH_PROGRESS("Graphopt layout", 100.0-100.0*i/niter, NULL);
 
1773
    }
 
1774
    
 
1775
    /* Clear pending forces on all nodes */
 
1776
    igraph_vector_null(&pending_forces_x);
 
1777
    igraph_vector_null(&pending_forces_y);
 
1778
    
 
1779
    // Apply electrical force applied by all other nodes
 
1780
    if (apply_electric_charges) {
 
1781
      // Iterate through all nodes
 
1782
      for (this_node = 0; this_node < no_of_nodes; this_node++) {
 
1783
        IGRAPH_ALLOW_INTERRUPTION();
 
1784
        for (other_node = this_node + 1; 
 
1785
             other_node < no_of_nodes; 
 
1786
             other_node++) {
 
1787
          distance = igraph_i_distance_between(res, this_node, other_node);
 
1788
          // let's protect ourselves from division by zero by ignoring
 
1789
          // two nodes that happen to be in the same place.  Since we 
 
1790
          // separate all nodes before we work on any of them, this 
 
1791
          // will only happen in extremely rare circumstances, and when
 
1792
          // it does, springs will probably pull them apart anyway.
 
1793
          // also, if we are more than 50 away, the electric force 
 
1794
          // will be negligable.  
 
1795
          // ***** may not always be desirable ****
 
1796
          if ((distance != 0.0) && (distance < 500.0)) {
 
1797
            //    if (distance != 0.0) {
 
1798
            // Apply electrical force from node(counter2) on 
 
1799
            // node(counter)
 
1800
            igraph_i_apply_electrical_force(res, &pending_forces_x, 
 
1801
                                            &pending_forces_y, 
 
1802
                                            other_node, this_node, 
 
1803
                                            node_charge,
 
1804
                                            distance);
 
1805
          }
 
1806
        }
 
1807
      }
 
1808
    }
 
1809
      
 
1810
    // Apply force from springs
 
1811
    for (edge = 0; edge < no_of_edges; edge++) {
 
1812
      long int this_node=IGRAPH_FROM(graph, edge);
 
1813
      long int other_node=IGRAPH_TO(graph, edge);
 
1814
      // Apply spring force on both nodes
 
1815
      igraph_i_apply_spring_force(res, &pending_forces_x, &pending_forces_y,
 
1816
                                  other_node, this_node, my_spring_length, 
 
1817
                                  spring_constant);
 
1818
    }
 
1819
  
 
1820
    // Effect the movement of the nodes based on all pending forces
 
1821
    igraph_i_move_nodes(res, &pending_forces_x, &pending_forces_y, node_mass,
 
1822
                        max_sa_movement);
 
1823
  }
 
1824
  IGRAPH_PROGRESS("Graphopt layout", 100, NULL);
 
1825
 
 
1826
  igraph_vector_destroy(&pending_forces_y);
 
1827
  igraph_vector_destroy(&pending_forces_x);
 
1828
  IGRAPH_FINALLY_CLEAN(2);
 
1829
  
 
1830
  return 0;
 
1831
}
 
1832
 
 
1833
int igraph_i_layout_merge_dla(igraph_i_layout_mergegrid_t *grid, 
 
1834
                              long int actg, igraph_real_t *x, igraph_real_t *y, igraph_real_t r,
 
1835
                              igraph_real_t cx, igraph_real_t cy, igraph_real_t startr, 
 
1836
                              igraph_real_t killr);
 
1837
 
 
1838
/**
 
1839
 * \function igraph_layout_merge_dla
 
1840
 * \brief Merge multiple layouts by using a DLA algorithm
 
1841
 * 
 
1842
 * </para><para>
 
1843
 * First each layout is covered by a circle. Then the layout of the
 
1844
 * largest graph is placed at the origin. Then the other layouts are
 
1845
 * placed by the DLA algorithm, larger ones first and smaller ones
 
1846
 * last.
 
1847
 * \param thegraphs Pointer vector containing the graph object of
 
1848
 *        which the layouts will be merged.
 
1849
 * \param coords Pointer vector containing matrix objects with the 2d
 
1850
 *        layouts of the graphs in \p thegraphs.
 
1851
 * \param res Pointer to an initialized matrix object, the result will
 
1852
 *        be stored here. It will be resized if needed.
 
1853
 * \return Error code.
 
1854
 * 
 
1855
 * Added in version 0.2. This function is experimental.
 
1856
 * 
 
1857
 * </para><para>
 
1858
 * Time complexity: TODO.
 
1859
 */
 
1860
 
 
1861
int igraph_layout_merge_dla(igraph_vector_ptr_t *thegraphs,
 
1862
                            igraph_vector_ptr_t *coords, 
 
1863
                            igraph_matrix_t *res) {
 
1864
  long int graphs=igraph_vector_ptr_size(coords);
 
1865
  igraph_vector_t sizes;
 
1866
  igraph_vector_t x, y, r;
 
1867
  igraph_vector_t nx, ny, nr;
 
1868
  long int allnodes=0;
 
1869
  long int i, j;
 
1870
  long int actg;
 
1871
  igraph_i_layout_mergegrid_t grid;
 
1872
  long int jpos=0;
 
1873
  igraph_real_t minx, maxx, miny, maxy;
 
1874
  igraph_real_t area=0;
 
1875
  igraph_real_t maxr=0;
 
1876
  long int respos;
 
1877
  
 
1878
  IGRAPH_VECTOR_INIT_FINALLY(&sizes, graphs);
 
1879
  IGRAPH_VECTOR_INIT_FINALLY(&x, graphs);
 
1880
  IGRAPH_VECTOR_INIT_FINALLY(&y, graphs);
 
1881
  IGRAPH_VECTOR_INIT_FINALLY(&r, graphs);
 
1882
  IGRAPH_VECTOR_INIT_FINALLY(&nx, graphs);
 
1883
  IGRAPH_VECTOR_INIT_FINALLY(&ny, graphs);
 
1884
  IGRAPH_VECTOR_INIT_FINALLY(&nr, graphs);
 
1885
  
 
1886
  for (i=0; i<igraph_vector_ptr_size(coords); i++) {
 
1887
    igraph_matrix_t *mat=VECTOR(*coords)[i];
 
1888
    long int size=igraph_matrix_nrow(mat);
 
1889
    IGRAPH_ALLOW_INTERRUPTION();
 
1890
    allnodes += size;
 
1891
    VECTOR(sizes)[i]=size;
 
1892
    VECTOR(r)[i]=pow(size, .75);
 
1893
    area+=VECTOR(r)[i] * VECTOR(r)[i];
 
1894
    if (VECTOR(r)[i] > maxr) {
 
1895
      maxr=VECTOR(r)[i];
 
1896
    }
 
1897
 
 
1898
    igraph_i_layout_sphere_2d(mat,
 
1899
                              igraph_vector_e_ptr(&nx, i),
 
1900
                              igraph_vector_e_ptr(&ny, i),
 
1901
                              igraph_vector_e_ptr(&nr, i));
 
1902
    
 
1903
  }
 
1904
  igraph_vector_order2(&sizes); /* largest first */
 
1905
 
 
1906
  /* 0. create grid */
 
1907
  minx=miny=-sqrt(5*area);
 
1908
  maxx=maxy=sqrt(5*area);
 
1909
  igraph_i_layout_mergegrid_init(&grid, minx, maxx, 200,
 
1910
                                 miny, maxy, 200);
 
1911
  IGRAPH_FINALLY(igraph_i_layout_mergegrid_destroy, &grid);
 
1912
 
 
1913
/*   fprintf(stderr, "Ok, starting DLA\n"); */
 
1914
  
 
1915
  /* 1. place the largest  */
 
1916
  actg=VECTOR(sizes)[jpos++];
 
1917
  igraph_i_layout_merge_place_sphere(&grid, 0, 0, VECTOR(r)[actg], actg);
 
1918
  
 
1919
  IGRAPH_PROGRESS("Merging layouts via DLA", 0.0, NULL);
 
1920
  while (jpos<graphs) {
 
1921
    IGRAPH_ALLOW_INTERRUPTION();
 
1922
/*     fprintf(stderr, "comp: %li", jpos); */
 
1923
    IGRAPH_PROGRESS("Merging layouts via DLA", (100.0*jpos)/graphs, NULL);
 
1924
    
 
1925
    actg=VECTOR(sizes)[jpos++];
 
1926
    /* 2. random walk, TODO: tune parameters */
 
1927
    igraph_i_layout_merge_dla(&grid, actg, 
 
1928
                              igraph_vector_e_ptr(&x, actg),
 
1929
                              igraph_vector_e_ptr(&y, actg), 
 
1930
                              VECTOR(r)[actg], 0, 0,
 
1931
                              maxx-maxr, maxx-maxr+5);
 
1932
    
 
1933
    /* 3. place sphere */
 
1934
    igraph_i_layout_merge_place_sphere(&grid, VECTOR(x)[actg], VECTOR(y)[actg],
 
1935
                                       VECTOR(r)[actg], actg);
 
1936
  }
 
1937
  IGRAPH_PROGRESS("Merging layouts via DLA", 100.0, NULL);
 
1938
 
 
1939
  /* Create the result */
 
1940
  IGRAPH_CHECK(igraph_matrix_resize(res, allnodes, 2));
 
1941
  respos=0;
 
1942
  for (i=0; i<graphs; i++) {
 
1943
    long int size=igraph_matrix_nrow(VECTOR(*coords)[i]);
 
1944
    igraph_real_t xx=VECTOR(x)[i];
 
1945
    igraph_real_t yy=VECTOR(y)[i];
 
1946
    igraph_real_t rr=VECTOR(r)[i]/VECTOR(nr)[i];
 
1947
    igraph_matrix_t *mat=VECTOR(*coords)[i];
 
1948
    IGRAPH_ALLOW_INTERRUPTION();
 
1949
    if (VECTOR(nr)[i]==0) { rr=1; }
 
1950
    for (j=0; j<size; j++) {
 
1951
      MATRIX(*res, respos, 0)=rr*(MATRIX(*mat, j, 0)-VECTOR(nx)[i]);
 
1952
      MATRIX(*res, respos, 1)=rr*(MATRIX(*mat, j, 1)-VECTOR(ny)[i]);
 
1953
      MATRIX(*res, respos, 0)+=xx;
 
1954
      MATRIX(*res, respos, 1)+=yy;
 
1955
      ++respos;
 
1956
    }
 
1957
  }
 
1958
 
 
1959
  igraph_i_layout_mergegrid_destroy(&grid);
 
1960
  igraph_vector_destroy(&sizes);
 
1961
  igraph_vector_destroy(&x);
 
1962
  igraph_vector_destroy(&y);
 
1963
  igraph_vector_destroy(&r);
 
1964
  igraph_vector_destroy(&nx);
 
1965
  igraph_vector_destroy(&ny);
 
1966
  igraph_vector_destroy(&nr);
 
1967
  IGRAPH_FINALLY_CLEAN(8);
 
1968
  return 0;
 
1969
}
 
1970
 
 
1971
int igraph_i_layout_sphere_2d(igraph_matrix_t *coords, igraph_real_t *x, igraph_real_t *y,
 
1972
                              igraph_real_t *r) {
 
1973
  long int nodes=igraph_matrix_nrow(coords);
 
1974
  long int i;
 
1975
  igraph_real_t xmin, xmax, ymin, ymax;
 
1976
  
 
1977
  xmin=xmax=MATRIX(*coords,0,0);
 
1978
  ymin=ymax=MATRIX(*coords,0,1);
 
1979
  for (i=1; i<nodes; i++) {
 
1980
 
 
1981
    if (MATRIX(*coords,i,0) < xmin) {
 
1982
      xmin=MATRIX(*coords,i,0);
 
1983
    } else if (MATRIX(*coords,i,0)>xmax) {
 
1984
      xmax=MATRIX(*coords,i,0);
 
1985
    }
 
1986
 
 
1987
    if (MATRIX(*coords,i,1) < ymin) {
 
1988
      ymin=MATRIX(*coords,i,1);
 
1989
    } else if (MATRIX(*coords,i,1)>ymax) {
 
1990
      ymax=MATRIX(*coords,i,1);
 
1991
    }
 
1992
    
 
1993
  }
 
1994
 
 
1995
  *x=(xmin+xmax)/2;
 
1996
  *y=(ymin+ymax)/2;
 
1997
  *r=sqrt( (xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin) ) / 2;
 
1998
 
 
1999
  return 0;
 
2000
}
 
2001
 
 
2002
int igraph_i_layout_sphere_3d(igraph_matrix_t *coords, igraph_real_t *x, igraph_real_t *y,
 
2003
                              igraph_real_t *z, igraph_real_t *r) {
 
2004
  long int nodes=igraph_matrix_nrow(coords);
 
2005
  long int i;
 
2006
  igraph_real_t xmin, xmax, ymin, ymax, zmin, zmax;
 
2007
  
 
2008
  xmin=xmax=MATRIX(*coords,0,0);
 
2009
  ymin=ymax=MATRIX(*coords,0,1);
 
2010
  zmin=zmax=MATRIX(*coords,0,2);
 
2011
  for (i=1; i<nodes; i++) {
 
2012
    
 
2013
    if (MATRIX(*coords,i,0) < xmin) {
 
2014
      xmin=MATRIX(*coords,i,0);
 
2015
    } else if (MATRIX(*coords,i,0)>xmax) {
 
2016
      xmax=MATRIX(*coords,i,0);
 
2017
    }
 
2018
 
 
2019
    if (MATRIX(*coords,i,1) < ymin) {
 
2020
      ymin=MATRIX(*coords,i,1);
 
2021
    } else if (MATRIX(*coords,i,1)>ymax) {
 
2022
      ymax=MATRIX(*coords,i,1);
 
2023
    }
 
2024
    
 
2025
    if (MATRIX(*coords,i,2) < zmin) {
 
2026
      zmin=MATRIX(*coords,i,2);
 
2027
    } else if (MATRIX(*coords,i,2)>zmax) {
 
2028
      zmax=MATRIX(*coords,i,2);
 
2029
    }
 
2030
 
 
2031
  }
 
2032
  
 
2033
  *x=(xmin+xmax)/2;
 
2034
  *y=(ymin+ymax)/2;
 
2035
  *z=(zmin+zmax)/2;
 
2036
  *r=sqrt( (xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)+
 
2037
           (zmax-zmin)*(zmax-zmin) ) / 2;
 
2038
  
 
2039
  return 0;
 
2040
}
 
2041
 
 
2042
#define DIST(x,y) (sqrt(pow((x)-cx,2)+pow((y)-cy,2)))
 
2043
 
 
2044
int igraph_i_layout_merge_dla(igraph_i_layout_mergegrid_t *grid, 
 
2045
                              long int actg, igraph_real_t *x, igraph_real_t *y, igraph_real_t r,
 
2046
                              igraph_real_t cx, igraph_real_t cy, igraph_real_t startr, 
 
2047
                              igraph_real_t killr) {
 
2048
  long int sp=-1;
 
2049
  igraph_real_t angle, len;
 
2050
  long int steps=0;
 
2051
 
 
2052
  while (sp < 0) {
 
2053
    /* start particle */
 
2054
    do {
 
2055
      steps++;
 
2056
      angle=RNG_UNIF(0,2*M_PI);
 
2057
      len=RNG_UNIF(.5*startr, startr);
 
2058
      *x=cx+len*cos(angle);
 
2059
      *y=cy+len*sin(angle);
 
2060
      sp=igraph_i_layout_mergegrid_get_sphere(grid, *x, *y, r);
 
2061
    } while (sp >= 0);
 
2062
 
 
2063
    while (sp < 0 && DIST(*x,*y)<killr) {
 
2064
      igraph_real_t nx, ny;
 
2065
      steps++;
 
2066
      angle=RNG_UNIF(0,2*M_PI);
 
2067
      len=RNG_UNIF(0, startr/100);
 
2068
      nx= *x + len * cos(angle);
 
2069
      ny= *y + len * sin(angle);      
 
2070
      sp=igraph_i_layout_mergegrid_get_sphere(grid, nx, ny, r);
 
2071
      if (sp < 0) {
 
2072
        *x = nx; *y = ny;
 
2073
      }
 
2074
    }
 
2075
  }
 
2076
 
 
2077
/*   fprintf(stderr, "%li ", steps); */
 
2078
  return 0;
 
2079
}