static real edge_compatibility(pedge e1, pedge e2){ /* two edges are u1->v1, u2->v2. return 1 if two edges are exactly the same, 0 if they are very different. */ real *u1, *v1, *u2, *v2, *u, dist1, dist2, len1, len2; int dim = e1->dim, flipped = FALSE; u1 = e1->x; v1 = (e1->x)+(e1->npoints)*dim-dim; u2 = e2->x; v2 = (e2->x)+(e2->npoints)*dim-dim; dist1 = sqr_dist(dim, u1, u2) + sqr_dist(dim, v1, v2); dist2 = sqr_dist(dim, u1, v2) + sqr_dist(dim, v1, u2); if (dist1 > dist2){ u = u2; u2 = v2; v2 = u; dist1 = dist2; flipped = TRUE; } len1 = dist(dim, u1, v1); len2 = dist(dim, u2, v2); //dist1 = MAX(0.1, dist1/(len1+len2+dist1)); dist1 = MAX(0.1, dist1/(len1+len2+0.0001*dist1)); if (flipped){ return -1/dist1; } else { return 1/dist1; } }
static real edge_compatibility_full(pedge e1, pedge e2){ /* two edges are u1->v1, u2->v2. return 1 if two edges are exactly the same, 0 if they are very different. This is based on Holten and van Wijk's paper */ real *u1, *v1, *u2, *v2, *u, dist1, dist2, len1, len2, len; real tmp, ca, cp, cs; int dim = e1->dim, flipped = FALSE, i; u1 = e1->x; v1 = (e1->x)+(e1->npoints)*dim-dim; u2 = e2->x; v2 = (e2->x)+(e2->npoints)*dim-dim; dist1 = sqr_dist(dim, u1, u2) + sqr_dist(dim, v1, v2); dist2 = sqr_dist(dim, u1, v2) + sqr_dist(dim, v1, u2); if (dist1 > dist2){ u = u2; u2 = v2; v2 = u; dist1 = dist2; flipped = TRUE; } len1 = MAX(dist(dim, u1, v1), SMALL); len2 = MAX(dist(dim, u2, v2), SMALL); len = 0.5*(len1+len2); /* angle compatibility */ ca = 0; for (i = 0; i < dim; i++) ca += (v1[i]-u1[i])*(v2[i]-u2[i]); ca = ABS(ca/(len1*len2)); assert(ca > -0.001); /* scale compatibility */ //cs = 2/(len1/len2+len2/len1); cs = 2/(MAX(len1,len2)/len + len/MIN(len1, len2)); assert(cs > -0.001 && cs < 1.001); /* position compatibility */ cp = 0; for (i = 0; i < dim; i++) { tmp = .5*(v1[i]+u1[i])-.5*(v2[i]+u2[i]); cp += tmp*tmp; } cp = sqrt(cp); cp = len/(len + cp); assert(cp > -0.001 && cp < 1.001); /* visibility compatibility */ //dist1 = MAX(0.1, dist1/(len1+len2+dist1)); dist1 = cp*ca*cs; if (flipped){ return -dist1; } else { return dist1; } }
static void edge_attraction_force(real similarity, pedge e1, pedge e2, real *force){ /* attrractive force from x2 applied to x1 */ real *x1 = e1->x, *x2 = e2->x; int dim = e1->dim; int np = e1->npoints; int i, j; real dist, s, ss; real edge_length = e1->edge_length; assert(e1->npoints == e2->npoints); /* attractive force = 1/d where d = D/||e1|| is the relative distance, D is the distance between e1 and e2. so the force is norminal and unitless */ if (similarity > 0){ s = edge_length; s = similarity*edge_length; for (i = 1; i <= np - 2; i++){ dist = sqr_dist(dim, &(x1[i*dim]), &(x2[i*dim])); if (dist < SMALL) dist = SMALL; ss = s/(dist+0.1*edge_length*sqrt(dist)); for (j = 0; j < dim; j++) force[i*dim + j] += ss*(x2[i*dim + j] - x1[i*dim + j]); } } else {/* clip e2 */ s = -edge_length; s = -similarity*edge_length; for (i = 1; i <= np - 2; i++){ dist = sqr_dist(dim, &(x1[i*dim]), &(x2[(np - 1 - i)*dim])); if (dist < SMALL) dist = SMALL; ss = s/(dist+0.1*edge_length*sqrt(dist)); for (j = 0; j < dim; j++) force[i*dim + j] += ss*(x2[(np - 1 - i)*dim + j] - x1[i*dim + j]); } } }
double MSLPoint3d::distance(const MSLPoint3d& q) const { return sqrt(sqr_dist(q)); }
static real dist(int dim, real *x, real *y){ return sqrt(sqr_dist(dim,x,y)); }