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