]> granicus.if.org Git - graphviz/commitdiff
Provide optional non-recursive partitioning function
authorEmden Gansner <erg@research.att.com>
Wed, 15 Aug 2012 21:10:57 +0000 (17:10 -0400)
committerEmden Gansner <erg@research.att.com>
Wed, 15 Aug 2012 21:10:57 +0000 (17:10 -0400)
lib/ortho/partition.c

index 1bb668690a5f61b9f6dda948fd677219654cd828..c0814ec708f519be8167130cb7001b0eae7474b2 100644 (file)
@@ -316,6 +316,7 @@ make_new_monotone_poly (int mcur, int v0, int v1)
   return mnew;
 }
 
+#ifndef NO_RECURSE
 /* recursively visit all the trapezoids */
 static int
 traverse_polygon (int* visited, boxf* decomp, int size, segment_t* seg, trap_t* tr,
@@ -612,6 +613,342 @@ traverse_polygon (int* visited, boxf* decomp, int size, segment_t* seg, trap_t*
 
   return size;
 }
+#else
+typedef struct {
+  int mcur, trnum, from, dir;
+} frame_t;
+
+typedef struct {
+  frame_t* data;
+  int top, size;
+} stk_t;
+
+static stk_t*
+stkOpen ()
+{
+  stk_t* sp = NEW(stk_t);
+  sp->size=1024;
+  sp->data=N_NEW(sp->size,frame_t);
+  sp->top=0;
+  return sp;
+}
+
+static void
+stkGrow (stk_t* sp)
+{
+  sp->size *= 2;
+  sp->data = RALLOC(sp->size,sp->data,frame_t);
+}
+
+static void
+stkClose (stk_t* sp)
+{
+  free (sp->data);
+  free (sp);
+}
+
+#define stkSize(s) (s->top)
+#define stkPush(s,m,t,f,d) {if(s->top==s->size)stkGrow(s); \
+ fp=s->data+s->top; \
+ fp->mcur=m; \
+ fp->trnum=t; \
+ fp->from=f; \
+ fp->dir=d; \
+ s->top++;}
+
+#define stkPop(s,m,t,f,d) {s->top--; \
+ fp=s->data+s->top; \
+ m=fp->mcur; \
+ t=fp->trnum; \
+ f=fp->from; \
+ d=fp->dir; }
+
+static int
+traverse_polygon (int* visited, boxf* decomp, int size, segment_t* seg, trap_t* tr,
+    int mcur0, int trnum0, int from0, int flip, int dir0)
+{
+  trap_t *t;
+  int mnew;
+  int v0, v1;
+  stk_t* stk = stkOpen();
+  int mcur, trnum, from, dir;
+  frame_t* fp; 
+
+  stkPush (stk, mcur0, trnum0, from0, dir0);
+  
+  while (stkSize(stk)) {
+    stkPop(stk, mcur, trnum, from, dir);
+    t = &tr[trnum];
+
+    if ((trnum <= 0) || visited[trnum])
+      continue;
+  
+    visited[trnum] = TRUE;
+    
+    if ((t->hi.y > t->lo.y) &&
+        (seg[t->lseg].v0.x == seg[t->lseg].v1.x) &&
+        (seg[t->rseg].v0.x == seg[t->rseg].v1.x)) {
+        if (flip) {
+            decomp[size].LL.x = t->lo.y;
+            decomp[size].LL.y = -seg[t->rseg].v0.x;
+            decomp[size].UR.x = t->hi.y;
+            decomp[size].UR.y = -seg[t->lseg].v0.x;
+        } else {
+            decomp[size].LL.x = seg[t->lseg].v0.x;
+            decomp[size].LL.y = t->lo.y;
+            decomp[size].UR.x = seg[t->rseg].v0.x;
+            decomp[size].UR.y = t->hi.y;
+        }
+        size++;
+    }
+    
+    /* We have much more information available here. */
+    /* rseg: goes upwards   */
+    /* lseg: goes downwards */
+  
+    /* Initially assume that dir = TR_FROM_DN (from the left) */
+    /* Switch v0 and v1 if necessary afterwards */
+  
+  
+    /* special cases for triangles with cusps at the opposite ends. */
+    /* take care of this first */
+    if ((t->u0 <= 0) && (t->u1 <= 0))
+      {
+        if ((t->d0 > 0) && (t->d1 > 0)) /* downward opening triangle */
+       {
+         v0 = tr[t->d1].lseg;
+         v1 = t->lseg;
+         if (from == t->d1)
+           {
+             mnew = make_new_monotone_poly(mcur, v1, v0);
+             stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP);        
+             stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);
+           }
+         else
+           {
+             mnew = make_new_monotone_poly(mcur, v0, v1);
+             stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP);
+             stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+           }
+       }
+        else
+       {
+         stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);
+         stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+         stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+         stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+       }
+      }
+    
+    else if ((t->d0 <= 0) && (t->d1 <= 0))
+      {
+        if ((t->u0 > 0) && (t->u1 > 0)) /* upward opening triangle */
+       {
+         v0 = t->rseg;
+         v1 = tr[t->u0].rseg;
+         if (from == t->u1)
+           {
+             mnew = make_new_monotone_poly(mcur, v1, v0);
+             stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN);        
+             stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+           }
+         else
+           {
+             mnew = make_new_monotone_poly(mcur, v0, v1);
+             stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN);
+             stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+           }
+       }
+        else
+       {
+         stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);
+         stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+         stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+         stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+       }
+      }
+    
+    else if ((t->u0 > 0) && (t->u1 > 0)) 
+      {
+        if ((t->d0 > 0) && (t->d1 > 0)) /* downward + upward cusps */
+       {
+         v0 = tr[t->d1].lseg;
+         v1 = tr[t->u0].rseg;
+         if (((dir == TR_FROM_DN) && (t->d1 == from)) ||
+             ((dir == TR_FROM_UP) && (t->u1 == from)))
+           {
+             mnew = make_new_monotone_poly(mcur, v1, v0);
+             stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP);
+             stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN);
+             stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);
+             stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+           }
+         else
+           {
+             mnew = make_new_monotone_poly(mcur, v0, v1);
+             stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP);          
+             stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN);
+             stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+             stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+           }
+       }
+        else                   /* only downward cusp */
+       {
+         if (_equal_to(&t->lo, &seg[t->lseg].v1))
+           {
+             v0 = tr[t->u0].rseg;
+             v1 = seg[t->lseg].next;
+  
+             if ((dir == TR_FROM_UP) && (t->u0 == from))
+               {
+                 mnew = make_new_monotone_poly(mcur, v1, v0);
+                 stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP);
+                 stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN);
+                 stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+               }
+             else
+               {
+                 mnew = make_new_monotone_poly(mcur, v0, v1);
+                 stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN);
+                 stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+               }
+           }
+         else
+           {
+             v0 = t->rseg;
+             v1 = tr[t->u0].rseg;      
+             if ((dir == TR_FROM_UP) && (t->u1 == from))
+               {
+                 mnew = make_new_monotone_poly(mcur, v1, v0);
+                 stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN);
+                 stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+               }
+             else
+               {
+                 mnew = make_new_monotone_poly(mcur, v0, v1);
+                 stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN);
+                 stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+               }
+           }
+       }
+      }
+    else if ((t->u0 > 0) || (t->u1 > 0)) /* no downward cusp */
+      {
+        if ((t->d0 > 0) && (t->d1 > 0)) /* only upward cusp */
+       {
+         if (_equal_to(&t->hi, &seg[t->lseg].v0))
+           {
+             v0 = tr[t->d1].lseg;
+             v1 = t->lseg;
+             if (!((dir == TR_FROM_DN) && (t->d0 == from)))
+               {
+                 mnew = make_new_monotone_poly(mcur, v1, v0);
+                 stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+                 stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+               }
+             else
+               {
+                 mnew = make_new_monotone_poly(mcur, v0, v1);
+                 stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP);              
+                 stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN);
+                 stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN);
+                 stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+               }
+           }
+         else
+           {
+             v0 = tr[t->d1].lseg;
+             v1 = seg[t->rseg].next;
+  
+             if ((dir == TR_FROM_DN) && (t->d1 == from))
+               {
+                 mnew = make_new_monotone_poly(mcur, v1, v0);
+                 stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN);
+                 stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN);
+                 stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);
+               }
+             else
+               {
+                 mnew = make_new_monotone_poly(mcur, v0, v1);
+                 stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+                 stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+               }
+           }
+       }
+        else                   /* no cusp */
+       {
+         if (_equal_to(&t->hi, &seg[t->lseg].v0) &&
+             _equal_to(&t->lo, &seg[t->rseg].v0))
+           {
+             v0 = t->rseg;
+             v1 = t->lseg;
+             if (dir == TR_FROM_UP)
+               {
+                 mnew = make_new_monotone_poly(mcur, v1, v0);
+                 stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+                 stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+               }
+             else
+               {
+                 mnew = make_new_monotone_poly(mcur, v0, v1);
+                 stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN);
+                 stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN);
+                 stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);
+               }
+           }
+         else if (_equal_to(&t->hi, &seg[t->rseg].v1) &&
+                  _equal_to(&t->lo, &seg[t->lseg].v1))
+           {
+             v0 = seg[t->rseg].next;
+             v1 = seg[t->lseg].next;
+  
+             if (dir == TR_FROM_UP)
+               {
+                 mnew = make_new_monotone_poly(mcur, v1, v0);
+                 stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+                 stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+               }
+             else
+               {
+                 mnew = make_new_monotone_poly(mcur, v0, v1);
+                 stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN);
+                 stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN);
+                 stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+                 stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);
+               }
+           }
+         else                  /* no split possible */
+           {
+             stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP);                  
+             stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN);
+             stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP);
+             stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN);
+           }
+       }
+      }
+    }
+
+  stkClose (stk);
+  return size;
+}
+#endif
 
 static int
 monotonate_trapezoids(int nsegs, segment_t*seg, trap_t* tr,