00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00024 
00025 
00026 
00027 #define VMDFROPTIMIZED 1
00028 
00029 
00030 #include <math.h>
00031 #include <stdio.h>
00032 #include <algorithm>
00033 #include "GraphLayout.h"
00034 #include "utilities.h"   
00035 
00036 GraphLayout::GraphLayout(int numverts, int numedges) {
00037   pos_x.set_size(numverts);
00038   pos_y.set_size(numverts);
00039   dsp_x.set_size(numverts);
00040   dsp_y.set_size(numverts);
00041 
00042   if (numedges > 0) {
00043     edges_v0.set_size(numedges);
00044     edges_v1.set_size(numedges);
00045     weights.set_size(numedges);
00046   }
00047 
00048   weight_matrix = NULL;
00049 }
00050 
00051 
00052 GraphLayout::~GraphLayout() {
00053   pos_x.clear();
00054   pos_y.clear();
00055   dsp_x.clear();
00056   dsp_y.clear();
00057 
00058   edges_v0.clear();
00059   edges_v1.clear();
00060   weights.clear();
00061 }
00062 
00063 
00064 void GraphLayout::add_edge(int v0, int v1, float weight) {
00065   
00066   
00067   if (v0 == v1 || weight == 0.f) {
00068     return;
00069   }
00070 
00071   
00072   
00073   
00074   long maxvert = std::max(v0, v1);
00075   if (maxvert > pos_x.num()) {
00076     long extra = maxvert - pos_x.num(); 
00077     pos_x.extend(extra);
00078     pos_y.extend(extra);
00079     dsp_x.extend(extra);
00080     dsp_y.extend(extra);
00081   }
00082 
00083   edges_v0.append(v0);
00084   edges_v1.append(v1);
00085   weights.append(weight);
00086 }
00087 
00088 
00089 void GraphLayout::add_weight_matrix(const float *weight_matrix) {
00090   this->weight_matrix = weight_matrix;
00091 }
00092 
00093 
00094 
00095 void GraphLayout::init_positions_box() {
00096   int numverts = pos_x.num();
00097   float rm_inv = 1.0f / float(RAND_MAX);
00098 
00099   srand(314159); 
00100   int v;
00101   for (v=0; v<numverts; v++) {
00102     pos_x[v] = rm_inv * rand() - 0.5f;
00103     pos_y[v] = rm_inv * rand() - 0.5f;
00104   }
00105 
00106   
00107   memset(&dsp_x[0], 0, numverts * sizeof(float));
00108   memset(&dsp_y[0], 0, numverts * sizeof(float));
00109 }
00110 
00111 
00112 
00113 void GraphLayout::init_positions_circle() {
00114   int numverts = pos_x.num();
00115   float radscale = 0.5f;
00116   float angle = 0.0f;
00117   float delta_angle = 2.0f * VMD_PIF / numverts;
00118 
00119   int v;
00120   for (v=0; v<numverts; v++) {
00121     float sa, ca;
00122     sincosf(angle, &sa, &ca);
00123     pos_x[v] = radscale * ca;
00124     pos_y[v] = radscale * sa;
00125     angle += delta_angle;
00126   }
00127 }
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 void GraphLayout::compute(int iters, float area, float kscale, 
00140                           float tempscale, float distance_epsilon) {
00141   int numverts = pos_x.num();
00142   int numedges = edges_v0.num();
00143 
00144 printf("GraphLayout::compute(iters: %d  verts: %d  edges: %d  area: %g  kscale: %g  tempscale: %g\n", 
00145        iters, numverts, numedges, area, kscale, tempscale);
00146 
00147   if (iters < 1) 
00148     return;
00149 
00150 
00151 
00152 
00153 
00154 
00155   float k2 = area / numverts;
00156   float k = sqrtf(k2) * kscale;
00157   float k_inv = 1.0f / k;
00158   float iters_inv = 1.0f / iters; 
00159 
00160   for (int i=0; i<iters; i++) {
00161 printf("iter: %d\r", i); fflush(stdout);
00162 
00163     
00164     
00165     float temp = (1.f -  i * iters_inv);
00166 
00167     
00168     
00169     
00170     
00171     
00172     float tempsquared = (temp * temp) * tempscale;
00173 
00174     
00175     
00176     
00177     int v0, v1;
00178     for (v0=0; v0<numverts; v0++) {
00179       float posx = pos_x[v0];
00180       float posy = pos_y[v0];
00181       float dispx = 0.0f;
00182       float dispy = 0.0f;
00183 
00184       
00185       
00186       for (v1=0; v1<v0; v1++) {
00187         float dx = posx - pos_x[v1];
00188         float dy = posy - pos_y[v1];
00189         float dxy2 = dx*dx + dy*dy + distance_epsilon; 
00190 #if defined(VMDFROPTIMIZED)
00191         float repulsion = k2 / dxy2;
00192         dispx += dx * repulsion;
00193         dispy += dy * repulsion;
00194 #else
00195         float d_1 = 1.0f / sqrtf(dxy2);
00196         float repulsion = k2 * d_1;
00197         dispx += dx * d_1 * repulsion;
00198         dispy += dy * d_1 * repulsion;
00199 #endif
00200       }
00201 
00202       
00203       
00204       for (v1=v0+1; v1<numverts; v1++) {
00205         float dx = posx - pos_x[v1];
00206         float dy = posy - pos_y[v1];
00207         float dxy2 = dx*dx + dy*dy + distance_epsilon;
00208 #if defined(VMDFROPTIMIZED)
00209         float repulsion = k2 / dxy2;
00210         dispx += dx * repulsion;
00211         dispy += dy * repulsion;
00212 #else
00213         float d_1 = 1.0f / sqrtf(dxy2);
00214         float repulsion = k2 * d_1;
00215         dispx += dx * d_1 * repulsion;
00216         dispy += dy * d_1 * repulsion;
00217 #endif
00218       }
00219 
00220       
00221       dsp_x[v0] = dispx;
00222       dsp_y[v0] = dispy;
00223     }
00224 
00225     
00226     
00227     
00228     
00229     
00230     if (numedges == 0) {
00231       if (weight_matrix == NULL) {
00232         
00233         for (v0=0; v0<numverts; v0++) {
00234           float posx = pos_x[v0];
00235           float posy = pos_y[v0];
00236           float dispx = dsp_x[v0];
00237           float dispy = dsp_y[v0];
00238 
00239           for (v1=0; v1<v0; v1++) {
00240             float dx = posx - pos_x[v1];
00241             float dy = posy - pos_y[v1];
00242             float dxy2 = dx*dx + dy*dy;
00243 #if defined(VMDFROPTIMIZED)
00244             float attraction = sqrtf(dxy2) * k_inv;
00245             float dxa = dx * attraction;
00246             float dya = dy * attraction;
00247 #else
00248             float attraction = dxy2 * k_inv;
00249             float d_1 = 1.0f / sqrtf(dxy2 + distance_epsilon);
00250             float dxa = dx * d_1 * attraction;
00251             float dya = dy * d_1 * attraction;
00252 #endif
00253 
00254             
00255             dispx     -= dxa;
00256             dispy     -= dya;
00257             dsp_x[v1] += dxa;
00258             dsp_y[v1] += dya;
00259           }
00260 
00261           
00262           dsp_x[v0] = dispx;
00263           dsp_y[v0] = dispy;
00264         }
00265       } else {
00266         
00267         for (v0=0; v0<numverts; v0++) {
00268           float posx = pos_x[v0];
00269           float posy = pos_y[v0];
00270           float dispx = dsp_x[v0];
00271           float dispy = dsp_y[v0];
00272 
00273           for (v1=0; v1<v0; v1++) {
00274             
00275             float weight = weight_matrix[v1*numverts + v0];
00276 
00277             float dx = posx - pos_x[v1];
00278             float dy = posy - pos_y[v1];
00279             float dxy2 = dx*dx + dy*dy;
00280 #if defined(VMDFROPTIMIZED)
00281             float attraction = sqrtf(dxy2) * k_inv * weight;
00282             float dxa = dx * attraction;
00283             float dya = dy * attraction;
00284 #else
00285             float attraction = dxy2 * k_inv * weight;
00286             float d_1 = 1.0f / sqrtf(dxy2 + distance_epsilon);
00287             float dxa = dx * d_1 * attraction;
00288             float dya = dy * d_1 * attraction;
00289 #endif
00290 
00291             
00292             dispx     -= dxa;
00293             dispy     -= dya;
00294             dsp_x[v1] += dxa;
00295             dsp_y[v1] += dya;
00296           }
00297 
00298           
00299           dsp_x[v0] = dispx;
00300           dsp_y[v0] = dispy;
00301         }
00302       }
00303     } else {
00304       int e;
00305       for (e=0; e<numedges; e++) {
00306         int v0 = edges_v0[e];
00307         int v1 = edges_v1[e];
00308         float weight = weights[e];
00309 
00310         float dx = pos_x[v0] - pos_x[v1];
00311         float dy = pos_y[v0] - pos_y[v1];
00312         float dxy2 = dx*dx + dy*dy;
00313 #if defined(VMDFROPTIMIZED)
00314         float attraction = sqrtf(dxy2) * k_inv * weight;
00315         float dxa = dx * attraction;
00316         float dya = dy * attraction;
00317 #else
00318         float attraction = dxy2 * k_inv * weight;
00319         float d_1 = 1.0f / sqrtf(dxy2 + distance_epsilon);
00320         float dxa = dx * d_1 * attraction;
00321         float dya = dy * d_1 * attraction;
00322 #endif
00323 
00324         
00325         dsp_x[v0] -= dxa;
00326         dsp_y[v0] -= dya;
00327         dsp_x[v1] += dxa;
00328         dsp_y[v1] += dya;
00329       }
00330     }
00331 
00332     
00333     
00334     
00335     
00336     
00337     
00338     for (v0=0; v0<numverts; v0++) {
00339       float dx = dsp_x[v0];
00340       float dy = dsp_y[v0];
00341 
00342       float dxy2 = dx*dx + dy*dy;
00343 
00344       
00345       
00346       
00347       if (dxy2 > tempsquared * tempsquared) {
00348         float d = sqrtf(dxy2);
00349         float rescale = tempsquared / d;
00350         dx *= rescale;
00351         dy *= rescale;
00352       }
00353 
00354       pos_x[v0] += dx;
00355       pos_y[v0] += dy;
00356     } 
00357   }
00358 printf("\n");
00359 
00360 }
00361 
00362 
00363