]> granicus.if.org Git - graphviz/commitdiff
Changed get_overlap_graph
authorYifan Hu <yifanhu@yahoo.com>
Wed, 9 Oct 2013 19:23:15 +0000 (15:23 -0400)
committerYifan Hu <yifanhu@yahoo.com>
Wed, 9 Oct 2013 19:23:15 +0000 (15:23 -0400)
1. added check_overlap_only for fast checking when we only want to check if any overlap exist
2. Fix a bug when two y intervals are [a,b] and [c,d], with [a,b] inside [c,d] (c < a < b < d). When both are in the GB tree, and [a,b] is leaving, previously code starts with b, find a, then finish and found no overlap. How we finds all interval end points below b (thus a and c), and check if their corresponding interval intersects with [a,b]. This can double count overlaps in the case when [c,d] is inside [a,b], but I think that is OK.

Fixed a bug for the graph

graph G {
  node [shape=box]

  a [pos="100,0", width = 0.75, height = 0.5]
  b [pos="0,100", width = 0.75, height = 0.5]
  c [pos="200,100", width = 0.75, height = 0.5]
  d [pos="100,300", width = 0.75, height=8]
  a -- b -- c -- a
  d -- b
  d -- c
}

where the default scaling of 4 x edgelength gives no overlap, but the amount of shrinking calculated is based on the edges, and missed the overlap caused by nodes a and d for which no edge exist. We now added overlap_scaling which uses bisection to find thebest scaling. This can also be used for simple scaling only based overlap removal.

lib/neatogen/overlap.c
lib/neatogen/overlap.h

index b912fbf9877c91cef4f550aea815d9501c3357ed..77670695a2ef3047cbd96836796553e9157e62f6 100644 (file)
@@ -136,11 +136,12 @@ void InfoDest(void *a){
   ;
 }
 
-static SparseMatrix get_overlap_graph(int dim, int n, real *x, real *width){
+static SparseMatrix get_overlap_graph(int dim, int n, real *x, real *width, int check_overlap_only){
+  /* if check_overlap_only = TRUE, we only check whether there is one overlap */
   scan_point *scanpointsx, *scanpointsy;
   int i, k, neighbor;
   SparseMatrix A = NULL, B = NULL;
-  rb_red_blk_node *newNode, *newNode0;
+  rb_red_blk_node *newNode, *newNode0, *newNode2 = NULL;
   rb_red_blk_tree* treey;
   real one = 1;
 
@@ -193,22 +194,38 @@ static SparseMatrix get_overlap_graph(int dim, int n, real *x, real *width){
 
       RBTreeInsert(treey, &(scanpointsy[k+n]), NULL);
     } else {
+      real bsta, bbsta, bsto, bbsto; int ii; 
+
       assert(scanpointsx[i].node >= n);
 
       newNode = newNode0 = RBExactQuery(treey, &(scanpointsy[k + n]));
+      ii = ((scan_point *)newNode->key)->node;
+      assert(ii < n);
+      bsta = scanpointsy[ii].x; bsto = scanpointsy[ii+n].x;
 
 #ifdef DEBUG_RBTREE
-      fprintf(stderr, "poping..%d....", scanpointsy[k + n].node);
+      fprintf(stderr, "poping..%d....yinterval={%f,%f}\n", scanpointsy[k + n].node, bsta, bsto);
       treey->PrintKey(newNode->key);
 #endif
 
-      assert(treey->nil != newNode);
-      while ((newNode) && ((newNode = TreePredecessor(treey, newNode)) != treey->nil) && ((scan_point *)newNode->key)->node != k){
+     assert(treey->nil != newNode);
+      while ((newNode) && ((newNode = TreePredecessor(treey, newNode)) != treey->nil)){
        neighbor = (((scan_point *)newNode->key)->node)%n;
-       A = SparseMatrix_coordinate_form_add_entries(A, 1, &neighbor, &k, &one);
+       bbsta = scanpointsy[neighbor].x; bbsto = scanpointsy[neighbor+n].x;/* the y-interval of the node that has one end of the interval lower than the top of the leaving interval (bsto) */
+#ifdef DEBUG_RBTREE
+       fprintf(stderr," predecessor is node %d y = %f\n", ((scan_point *)newNode->key)->node, ((scan_point *)newNode->key)->x);
+#endif
+       if (neighbor != k){
+         if (ABS(0.5*(bsta+bsto) - 0.5*(bbsta+bbsto)) < 0.5*(bsto-bsta) + 0.5*(bbsto-bbsta)){/* if the distance of the centers of the interval is less than sum of width, we have overlap */
+           A = SparseMatrix_coordinate_form_add_entries(A, 1, &neighbor, &k, &one);
 #ifdef DEBUG_RBTREE
-       fprintf(stderr,"%d %d\n",k,neighbor);
+           fprintf(stderr,"======================================  %d %d\n",k,neighbor);
 #endif
+           if (check_overlap_only) goto check_overlap_RETURN;
+         }
+       } else {
+         newNode2 = newNode;
+       }
 
       }
 
@@ -218,19 +235,23 @@ static SparseMatrix get_overlap_graph(int dim, int n, real *x, real *width){
 #endif
 
       if (newNode0) RBDelete(treey,newNode0);
-      if (newNode != treey->nil && newNode != newNode0) {
+
+
+     if (newNode2 && newNode2 != treey->nil && newNode2 != newNode0) {
 
 #ifdef DEBUG_RBTREE
-       fprintf(stderr, "deleting2...");
-       treey->PrintKey(newNode->key)
+       fprintf(stderr, "deleteing2...");
+       treey->PrintKey(newNode2->key);
 #endif
 
-       if (newNode0) RBDelete(treey,newNode);
+       if (newNode0) RBDelete(treey,newNode2);
       }
+
     }
   }
 
-  FREE(scanpointsx);
+check_overlap_RETURN:
+   FREE(scanpointsx);
   FREE(scanpointsy);
   RBTreeDestroy(treey);
 
@@ -273,14 +294,94 @@ static relative_position_constraints relative_position_constraints_new(SparseMat
 
     return data;
 }
+static void scale_coord(int dim, int m, real *x, real scale){
+  int i;
+  for (i = 0; i < dim*m; i++) {
+    x[i] *= scale;
+  }
+}
+
+real overlap_scaling(int dim, int m, real *x, real *width, real scale_sta, real scale_sto, real epsilon, int maxiter){
+  /* do a bisection between scale_sta and scale_sto, up to maxiter iterations or till interval <= epsilon, to find the best scaling to avoid overlap
+     m: number of points
+     x: the coordinates
+     width: label size
+     scale_sta: starting bracket. If <= 0, assumed 0. If > 0, we will test this first and if no overlap, return.
+     scale_sto: stopping bracket. This must be overlap free if positive. If <= 0, we will find automatically by doubling from scale_sta, or epsilon if scale_sta <= 0.
+     typically usage: 
+     - for shrinking down a layout to reduce white space, we will assume scale_sta and scale_sto are both given and positive, and scale_sta is the current guess.
+     - for scaling up, we assume scale_sta, scale_sto <= 0
+   */
+  real scale = -1, scale_best = -1;
+  SparseMatrix C = NULL;
+  int check_overlap_only = 1;
+  int overlap = 0;
+  real two = 2;
+  int iter = 0;
+
+  assert(epsilon > 0);
+
+  if (scale_sta <= 0) {
+    scale_sta = 0;
+  } else {
+    scale_coord(dim, m, x, scale_sta);
+    C = get_overlap_graph(dim, m, x, width, check_overlap_only);
+    if (!C || C->nz == 0) {
+      if (Verbose) fprintf(stderr," shrinking with with %f works\n", scale_sta);
+      SparseMatrix_delete(C);
+      return scale_sta;
+    }
+    scale_coord(dim, m, x, 1./scale_sta);
+    SparseMatrix_delete(C);
+  }
 
+  if (scale_sto < 0){
+    if (scale_sta == 0) {
+      scale_sto = epsilon;
+    } else {
+      scale_sto = scale_sta;
+    }
+    scale_coord(dim, m, x, scale_sto);
+    do {
+      scale_sto *= two;
+      scale_coord(dim, m, x, two);
+      C = get_overlap_graph(dim, m, x, width, check_overlap_only);
+      overlap = (C && C->nz > 0);
+      SparseMatrix_delete(C);
+    } while (overlap);
+    scale_coord(dim, m, x, 1/scale_sto);/* unscale */
+  }
+
+  scale_best = scale_sto;
+  while (iter++ < maxiter && scale_sto - scale_sta > epsilon){
+
+    fprintf(stderr,"in overlap_scaling iter=%d, maxiter=%d, scaling bracket: {%f,%f}\n", iter, maxiter, scale_sta, scale_sto);
+
+    scale = 0.5*(scale_sta + scale_sto);
+    scale_coord(dim, m, x, scale);
+    C = get_overlap_graph(dim, m, x, width, check_overlap_only);
+    scale_coord(dim, m, x, 1./scale);/* unscale */
+    overlap = (C && C->nz > 0);
+    SparseMatrix_delete(C);
+    if (overlap){
+      scale_sta = scale;
+    } else {
+      scale_best = scale_sto = scale;
+    }
+  }
+
+  /* final scaling */
+  scale_coord(dim, m, x, scale_best);
+  return scale_best;
+}
 OverlapSmoother OverlapSmoother_new(SparseMatrix A, int m, 
                                    int dim, real lambda0, real *x, real *width, int include_original_graph, int neighborhood_only, 
                                    real *max_overlap, real *min_overlap,
                                    int edge_labeling_scheme, int n_constr_nodes, int *constr_nodes, SparseMatrix A_constr, int shrink
                                    ){
   OverlapSmoother sm;
-  int i, j, k, *iw, *jw, *id, *jd, jdiag;
+  int i, j, k, *iw, *jw, jdiag;
   SparseMatrix B;
   real *lambda, *d, *w, diag_d, diag_w, dist;
 
@@ -306,7 +407,7 @@ OverlapSmoother OverlapSmoother_new(SparseMatrix A, int m,
 
   if (!neighborhood_only){
     SparseMatrix C, D;
-    C = get_overlap_graph(dim, m, x, width);
+    C = get_overlap_graph(dim, m, x, width, 0);
     D = SparseMatrix_add(B, C);
     SparseMatrix_delete(B);
     SparseMatrix_delete(C);
@@ -340,16 +441,17 @@ OverlapSmoother OverlapSmoother_new(SparseMatrix A, int m,
 
   /* no overlap at all! */
   if (*max_overlap < 1 && shrink){
+    real scale_sta = MIN(1, *max_overlap*1.0001), scale_sto = 1;
+
     if (Verbose) fprintf(stderr," no overlap (overlap = %f), rescale to shrink\n", *max_overlap - 1);
-    for (i = 0; i < dim*m; i++) {
-      x[i] *= (*max_overlap);
-    }
+
+    scale_sta = overlap_scaling(dim, m, x, width, scale_sta, scale_sto, 0.0001, 15);
+
     *max_overlap = 1;
     goto RETURN;
   }
 
   iw = sm->Lw->ia; jw = sm->Lw->ja;
-  id = sm->Lwd->ia; jd = sm->Lwd->ja;
   w = (real*) sm->Lw->a; d = (real*) sm->Lwd->a;
 
   for (i = 0; i < m; i++){
@@ -541,8 +643,7 @@ void remove_overlap(int dim, SparseMatrix A, real *x, real *label_sizes, int ntr
 #endif
     OverlapSmoother_delete(sm);
   }
-  if (Verbose) 
-    fprintf(stderr, "overlap removal neighbors only?= %d iter -- %d, overlap factor = %g underlap factor = %g\n", neighborhood_only, i, max_overlap - 1, min_overlap);
+  if (Verbose) fprintf(stderr, "overlap removal neighbors only?= %d iter -- %d, overlap factor = %g underlap factor = %g\n", neighborhood_only, i, max_overlap - 1, min_overlap);
 
 #ifdef ANIMATE
   fprintf(fp,"}");
index 06f82ed423afe4304bb63654c85bc4581e2d3d7c..efb20e9e97fd69b603f71fab6850cbb238947f17 100644 (file)
@@ -54,5 +54,5 @@ real OverlapSmoother_smooth(OverlapSmoother sm, int dim, real *x);
 
 void remove_overlap(int dim, SparseMatrix A, real *x, real *label_sizes, int ntry, real initial_scaling, 
                    int edge_labeling_scheme, int n_constr_nodes, int *constr_nodes, SparseMatrix A_constr, int *flag);
-
+real overlap_scaling(int dim, int m, real *x, real *width, real scale_sta, real scale_sto, real epsilon, int maxiter);
 #endif