31static double norm(
int n,
const double *x) {
32 return sqrt(std::inner_product(x, x + n, x, 0.0));
35static double sqr_dist(
int dim,
const double *x,
const double *y) {
38 for (i = 0; i <
dim; i++)
39 res += (x[i] - y[i]) * (x[i] - y[i]);
43static double dist(
int dim,
const double *x,
const double *y) {
68 e.
wgts = std::vector<double>(np - 1, wgt);
78 double dist1,
dist2, len1, len2;
82 const double *u1 = e1.
x.data();
84 const double *u2 = e2.
x.data();
95 dist1 = std::max(0.1, dist1 / (len1 + len2 + 0.0001 * dist1));
108 double dist1,
dist2, len1, len2,
len;
109 double tmp, ca, cp, cs;
111 bool flipped =
false;
113 const double *u1 = e1.
x.data();
115 const double *u2 = e2.
x.data();
125 len = 0.5 * (len1 + len2);
129 for (i = 0; i <
dim; i++)
130 ca += (v1[i] - u1[i]) * (v2[i] - u2[i]);
131 ca = fabs(ca / (len1 * len2));
135 cs = 2 / (std::max(len1, len2) /
len +
len / std::min(len1, len2));
136 assert(cs > -0.001 && cs < 1.001);
140 for (i = 0; i <
dim; i++) {
141 tmp = .5 * (v1[i] + u1[i]) - .5 * (v2[i] + u2[i]);
146 assert(cp > -0.001 && cp < 1.001);
150 dist1 = cp * ca * cs;
159 fprintf(fp,
"#%02x%02x%02x%02x", r, g, b,
alpha);
165 fprintf(fp,
"strict graph{\n");
167 for (
size_t i = 0; i < ne; i++) {
169 const std::vector<double> &x =
edge.
x;
172 const int sto =
edge.npoints - 1;
174 fprintf(fp,
"%" PRISIZE_T " [pos=\"", i);
175 for (
int k = 0; k <
dim; k++) {
178 fprintf(fp,
"%f", x[sta *
dim + k]);
180 fprintf(fp,
"\"];\n");
182 fprintf(fp,
"%" PRISIZE_T " [pos=\"", i + ne);
183 for (
int k = 0; k <
dim; k++) {
186 fprintf(fp,
"%f", x[sto *
dim + k]);
188 fprintf(fp,
"\"];\n");
192 for (
size_t i = 0; i < ne; i++) {
194 if (!
edge.wgts.empty()) {
195 for (
int j = 0; j <
edge.npoints - 1; j++) {
196 maxwgt = std::max(maxwgt,
edge.wgts[j]);
202 for (
size_t i = 0; i < ne; i++) {
205 const std::vector<double> &x =
edge.
x;
208 for (
int j = 0; j <
edge.npoints; j++) {
216 const double tt1[] = {0.15, 0.5, 0.85};
217 const double tt2[] = {0.15, 0.4, 0.6, 0.85};
218 if (j == 1 || j ==
edge.npoints - 1) {
225 for (
int kk = 1; kk <= mm; kk++) {
226 const double t = tt[kk - 1];
227 for (
int k = 0; k <
dim; k++) {
231 x[(j - 1) *
dim + k] * (1 - t) + x[j *
dim + k] * t);
236 if (j == 0 || j ==
edge.npoints - 1) {
237 for (
int k = 0; k <
dim; k++) {
240 fprintf(fp,
"%f", x[j *
dim + k]);
245 if (!
edge.wgts.empty()) {
246 fprintf(fp,
"\", wgts=\"");
247 for (
int j = 0; j <
edge.npoints - 1; j++) {
250 fprintf(fp,
"%f",
edge.wgts[j]);
253 double len_total0 = 0;
254 fprintf(fp,
"\", color=\"");
255 for (
int j = 0; j <
edge.npoints - 1; j++) {
258 for (k = 0; k <
dim; k++) {
265 for (
int j = 0; j <
edge.npoints - 1; j++) {
268 for (k = 0; k <
dim; k++) {
273 const double t =
edge.wgts[j] / maxwgt;
275 const int r = 255 * t;
277 const int b = 255 * (1 - t);
281 if (j <
edge.npoints - 2)
282 fprintf(fp,
";%f",
len / len_total0);
285 fprintf(fp,
"\"];\n");
291static void pedge_print(
char *comments,
const pedge &e) {
294 fprintf(stderr,
"%s", comments);
295 for (i = 0; i < e.
npoints; i++) {
297 fprintf(stderr,
",");
298 fprintf(stderr,
"{");
299 for (j = 0; j <
dim; j++) {
301 fprintf(stderr,
",");
302 fprintf(stderr,
"%f", e.
x[
dim * i + j]);
304 fprintf(stderr,
"}");
306 fprintf(stderr,
"\n");
314 e.
x.resize(e.
dim * n, 0);
315 if (e.
wgts.empty()) {
316 e.
wgts.resize(n - 1);
317 for (i = 0; i < e.
npoints; i++)
320 e.
wgts.resize(n - 1);
331 assert(npoints >= 2);
332 if (npoints * 2 - 1 >
len) {
336 std::vector<double> &x = e.
x;
338 for (i = npoints - 1; i >= 0; i--) {
340 for (j = 0; j <
dim; j++) {
341 x[
dim * ii + j] = x[
dim * i + j];
345 for (i = 0; i < npoints - 1; i++) {
348 for (j = 0; j <
dim; j++) {
349 x[
dim * (2 * i + 1) + j] = 0.5 * (x[
dim * ii + j] + x[
dim * ii2 + j]);
358 const std::vector<double> &x = e.
x;
368 for (i = 1; i <= np - 2; i++) {
371 for (j = 0; j <
dim; j++)
373 for (j = 0; j <
dim; j++)
379 const pedge &e2, std::vector<double> &force) {
381 const std::vector<double> &x1 = e1.
x, &x2 = e2.
x;
391 if (similarity > 0) {
392 const double s = similarity * edge_length;
393 for (
int i = 1; i <= np - 2; i++) {
397 const double ss =
s / (
dist + 0.1 * edge_length * sqrt(
dist));
398 for (
int j = 0; j <
dim; j++)
399 force[i *
dim + j] += ss * (x2[i *
dim + j] - x1[i *
dim + j]);
402 const double s = -similarity * edge_length;
403 for (
int i = 1; i <= np - 2; i++) {
408 const double ss =
s / (
dist + 0.1 * edge_length * sqrt(
dist));
409 for (
int j = 0; j <
dim; j++)
410 force[i *
dim + j] +=
411 ss * (x2[(np - 1 - i) *
dim + j] - x1[i *
dim + j]);
417 std::vector<pedge> &edges,
int maxit,
418 double step0,
double K) {
419 int i, j, ne =
A->
n, k;
420 int *ia =
A->ia, *ja =
A->ja, iter = 0;
421 double *a = (
double *)
A->a;
422 const int np = edges[0].npoints,
dim = edges[0].dim;
424 double fnorm_a, fnorm_t, edge_length, start;
429 ", avg neighbors per edge = %f\n",
430 A->nz,
A->m *
A->m, (
double)
A->nz / (
double)
A->m);
432 std::vector<double> force_t(
dim * np);
433 std::vector<double> force_a(
dim * np);
434 while (step > 0.001 && iter <
maxit) {
437 for (i = 0; i < ne; i++) {
438 for (j = 0; j <
dim * np; j++) {
442 pedge &e1 = edges[i];
443 std::vector<double> &x = e1.
x;
445 for (j = ia[i]; j < ia[i + 1]; j++) {
446 const pedge &e2 = edges[ja[j]];
453 for (j = 1; j <= np - 2; j++) {
454 for (k = 0; k <
dim; k++) {
455 x[j *
dim + k] += step * edge_length *
456 (force_t[j *
dim + k] + K * force_a[j *
dim + k]) /
457 hypot(fnorm_t, K * fnorm_a);
463 fprintf(stderr,
"iter ==== %d cpu = %f npoints = %d\n", iter,
464 (
double)(clock() - start) / CLOCKS_PER_SEC, np - 2);
469 std::vector<pedge> &edges,
470 double angle_param,
double angle) {
471 int *assignment =
nullptr, nclusters;
473 int *clusterp, *clusters;
488 fprintf(stderr,
"there are %d clusters, modularity = %f\n", nclusters,
493 for (
size_t i = 0; i < ne; i++) {
502 for (
int i = 0; i < nclusters; i++) {
503 ink1 =
ink(edges, clusterp[i + 1] - clusterp[i], &clusters[clusterp[i]],
504 &ink0, &meet1, &meet2, angle_param, angle);
506 fprintf(stderr,
"nedges = %d ink0 = %f, ink1 = %f\n",
507 clusterp[i + 1] - clusterp[i], ink0,
ink1);
509 for (j = clusterp[i]; j < clusterp[i + 1]; j++) {
514 pedge &e = edges[clusters[j]];
515 e.
x[1 *
dim] = meet1.
x;
516 e.
x[1 *
dim + 1] = meet1.
y;
517 e.
x[2 *
dim] = meet2.
x;
518 e.
x[2 *
dim + 1] = meet2.
y;
520 e.
x[3 *
dim + 1] = e.
x[4 *
dim + 1];
529 const std::vector<pedge> &edges,
530 int compatibility_method,
double tol) {
541 for (
size_t i = 0; i < ne; i++) {
542 for (j = ia[i]; j < ia[i + 1]; j++) {
562 fprintf(stderr,
"edge compatibilitu time = %f\n",
563 ((
double)(clock() - start)) / CLOCKS_PER_SEC);
568 const std::vector<double> &x,
int maxit_outer,
569 double K,
int method,
int nneighbor,
570 int compatibility_method,
int max_recursion,
571 double angle_param,
double angle) {
587 const size_t ne = A0->
m;
591 double step0 = 0.1, start = 0.0;
594 assert((
size_t)
A->n == ne);
595 std::vector<pedge> edges;
598 for (
size_t i = 0; i < ne; i++) {
623 for (k = 0; k < maxit_outer; k++) {
624 for (
size_t i = 0; i < ne; i++) {
637 fprintf(stderr,
"total edge bundling cpu = %f\n",
638 (
double)(clock() - start) / CLOCKS_PER_SEC);
SparseMatrix SparseMatrix_new(size_t m, int n, size_t nz, int type, int format)
SparseMatrix SparseMatrix_from_coordinate_format(SparseMatrix A)
SparseMatrix SparseMatrix_symmetrize(SparseMatrix A, bool pattern_symmetric_only)
void SparseMatrix_delete(SparseMatrix A)
SparseMatrix SparseMatrix_copy(SparseMatrix A)
SparseMatrix SparseMatrix_apply_fun(SparseMatrix A, double(*fun)(double x))
#define SparseMatrix_coordinate_form_add_entry(A, irn, jcn, val)
wrap SparseMatrix_coordinate_form_add_entry_ for type safety
void agglomerative_ink_bundling(int dim, SparseMatrix A, std::vector< pedge > &edges, int nneighbor, int MAX_RECURSE_LEVEL, double angle_param, double angle)
void modularity_clustering(SparseMatrix A, bool inplace, int ncluster_target, int *nclusters, int **assignment, double *modularity)
pedge pedge_wgt_new(int np, int dim, double *x, double wgt)
static SparseMatrix check_compatibility(SparseMatrix A, size_t ne, const std::vector< pedge > &edges, int compatibility_method, double tol)
static void force_directed_edge_bundling(SparseMatrix A, std::vector< pedge > &edges, int maxit, double step0, double K)
void pedge_wgts_realloc(pedge &e, int n)
static void edge_attraction_force(double similarity, const pedge &e1, const pedge &e2, std::vector< double > &force)
static void fprint_rgb(FILE *fp, int r, int g, int b, int alpha)
std::vector< pedge > edge_bundling(SparseMatrix A0, int dim, const std::vector< double > &x, int maxit_outer, double K, int method, int nneighbor, int compatibility_method, int max_recursion, double angle_param, double angle)
static double norm(int n, const double *x)
static void edge_tension_force(std::vector< double > &force, const pedge &e)
static void modularity_ink_bundling(int dim, size_t ne, SparseMatrix B, std::vector< pedge > &edges, double angle_param, double angle)
static double edge_compatibility(const pedge &e1, const pedge &e2)
void pedge_double(pedge &e)
static double edge_compatibility_full(const pedge &e1, const pedge &e2)
static double sqr_dist(int dim, const double *x, const double *y)
void pedge_export_gv(FILE *fp, size_t ne, const std::vector< pedge > &edges)
static double dist(int dim, const double *x, const double *y)
void pedge_delete(pedge &)
static pedge pedge_new(int np, int dim, const double *x)
static double len(glCompPoint p)
double ink(const std::vector< pedge > &edges, int numEdges, int *pick, double *ink0, point_t *meet1, point_t *meet2, double angle_param, double angle)
double ink1(const pedge &e)
PATHUTIL_API COORD dist2(Ppoint_t, Ppoint_t)
std::vector< double > x
coordinates of the npoints poly points. Dimension dim*npoints
std::vector< double > wgts
graphs, nodes and edges info: Agraphinfo_t, Agnodeinfo_t and Agedgeinfo_t