/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/neatogen/hedges.c

Go to the documentation of this file.
00001 /* $Id: hedges.c,v 1.1.1.1 2004/12/23 04:05:12 ellson Exp $ $Revision: 1.1.1.1 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 #include "mem.h"
00018 #include "hedges.h"
00019 #include "render.h"
00020 
00021 
00022 #define DELETED -2
00023 
00024 Halfedge *ELleftend, *ELrightend;
00025 
00026 static Freelist hfl;
00027 static int ELhashsize;
00028 static Halfedge **ELhash;
00029 static int ntry, totalsearch;
00030 
00031 void ELcleanup()
00032 {
00033     freeinit(&hfl, sizeof **ELhash);
00034     free(ELhash);
00035     ELhash = NULL;
00036 }
00037 
00038 void ELinitialize()
00039 {
00040     int i;
00041 
00042     freeinit(&hfl, sizeof **ELhash);
00043     ELhashsize = 2 * sqrt_nsites;
00044     if (ELhash == NULL)
00045         ELhash = N_GNEW(ELhashsize, Halfedge *);
00046     for (i = 0; i < ELhashsize; i += 1)
00047         ELhash[i] = (Halfedge *) NULL;
00048     ELleftend = HEcreate((Edge *) NULL, 0);
00049     ELrightend = HEcreate((Edge *) NULL, 0);
00050     ELleftend->ELleft = (Halfedge *) NULL;
00051     ELleftend->ELright = ELrightend;
00052     ELrightend->ELleft = ELleftend;
00053     ELrightend->ELright = (Halfedge *) NULL;
00054     ELhash[0] = ELleftend;
00055     ELhash[ELhashsize - 1] = ELrightend;
00056 }
00057 
00058 
00059 Site *hintersect(Halfedge * el1, Halfedge * el2)
00060 {
00061     Edge *e1, *e2, *e;
00062     Halfedge *el;
00063     double d, xint, yint;
00064     int right_of_site;
00065     Site *v;
00066 
00067     e1 = el1->ELedge;
00068     e2 = el2->ELedge;
00069     if (e1 == (Edge *) NULL || e2 == (Edge *) NULL)
00070         return ((Site *) NULL);
00071     if (e1->reg[1] == e2->reg[1])
00072         return ((Site *) NULL);
00073 
00074     d = e1->a * e2->b - e1->b * e2->a;
00075     if (-1.0e-10 < d && d < 1.0e-10)
00076         return ((Site *) NULL);
00077 
00078     xint = (e1->c * e2->b - e2->c * e1->b) / d;
00079     yint = (e2->c * e1->a - e1->c * e2->a) / d;
00080 
00081     if ((e1->reg[1]->coord.y < e2->reg[1]->coord.y) ||
00082         (e1->reg[1]->coord.y == e2->reg[1]->coord.y &&
00083          e1->reg[1]->coord.x < e2->reg[1]->coord.x)) {
00084         el = el1;
00085         e = e1;
00086     } else {
00087         el = el2;
00088         e = e2;
00089     };
00090     right_of_site = xint >= e->reg[1]->coord.x;
00091     if ((right_of_site && el->ELpm == le) ||
00092         (!right_of_site && el->ELpm == re))
00093         return ((Site *) NULL);
00094 
00095     v = getsite();
00096     v->refcnt = 0;
00097     v->coord.x = xint;
00098     v->coord.y = yint;
00099     return (v);
00100 }
00101 
00102 /* returns 1 if p is to right of halfedge e */
00103 int right_of(Halfedge * el, Point * p)
00104 {
00105     Edge *e;
00106     Site *topsite;
00107     int right_of_site, above, fast;
00108     double dxp, dyp, dxs, t1, t2, t3, yl;
00109 
00110     e = el->ELedge;
00111     topsite = e->reg[1];
00112     right_of_site = p->x > topsite->coord.x;
00113     if (right_of_site && el->ELpm == le)
00114         return (1);
00115     if (!right_of_site && el->ELpm == re)
00116         return (0);
00117 
00118     if (e->a == 1.0) {
00119         dyp = p->y - topsite->coord.y;
00120         dxp = p->x - topsite->coord.x;
00121         fast = 0;
00122         if ((!right_of_site & (e->b < 0.0)) |
00123             (right_of_site & (e->b >= 0.0))) {
00124             above = dyp >= e->b * dxp;
00125             fast = above;
00126         } else {
00127             above = p->x + p->y * e->b > e->c;
00128             if (e->b < 0.0)
00129                 above = !above;
00130             if (!above)
00131                 fast = 1;
00132         };
00133         if (!fast) {
00134             dxs = topsite->coord.x - (e->reg[0])->coord.x;
00135             above = e->b * (dxp * dxp - dyp * dyp) <
00136                 dxs * dyp * (1.0 + 2.0 * dxp / dxs + e->b * e->b);
00137             if (e->b < 0.0)
00138                 above = !above;
00139         };
00140     } else {                    /*e->b==1.0 */
00141         yl = e->c - e->a * p->x;
00142         t1 = p->y - yl;
00143         t2 = p->x - topsite->coord.x;
00144         t3 = yl - topsite->coord.y;
00145         above = t1 * t1 > t2 * t2 + t3 * t3;
00146     };
00147     return (el->ELpm == le ? above : !above);
00148 }
00149 
00150 Halfedge *HEcreate(Edge * e, char pm)
00151 {
00152     Halfedge *answer;
00153     answer = (Halfedge *) getfree(&hfl);
00154     answer->ELedge = e;
00155     answer->ELpm = pm;
00156     answer->PQnext = (Halfedge *) NULL;
00157     answer->vertex = (Site *) NULL;
00158     answer->ELrefcnt = 0;
00159     return (answer);
00160 }
00161 
00162 
00163 void ELinsert(Halfedge * lb, Halfedge * new)
00164 {
00165     new->ELleft = lb;
00166     new->ELright = lb->ELright;
00167     (lb->ELright)->ELleft = new;
00168     lb->ELright = new;
00169 }
00170 
00171 /* Get entry from hash table, pruning any deleted nodes */
00172 static Halfedge *ELgethash(int b)
00173 {
00174     Halfedge *he;
00175 
00176     if (b < 0 || b >= ELhashsize)
00177         return ((Halfedge *) NULL);
00178     he = ELhash[b];
00179     if (he == (Halfedge *) NULL || he->ELedge != (Edge *) DELETED)
00180         return (he);
00181 
00182 /* Hash table points to deleted half edge.  Patch as necessary. */
00183     ELhash[b] = (Halfedge *) NULL;
00184     if ((he->ELrefcnt -= 1) == 0)
00185         makefree(he, &hfl);
00186     return ((Halfedge *) NULL);
00187 }
00188 
00189 Halfedge *ELleftbnd(Point * p)
00190 {
00191     int i, bucket;
00192     Halfedge *he;
00193 
00194 /* Use hash table to get close to desired halfedge */
00195     bucket = (p->x - xmin) / deltax * ELhashsize;
00196     if (bucket < 0)
00197         bucket = 0;
00198     if (bucket >= ELhashsize)
00199         bucket = ELhashsize - 1;
00200     he = ELgethash(bucket);
00201     if (he == (Halfedge *) NULL) {
00202         for (i = 1; 1; i += 1) {
00203             if ((he = ELgethash(bucket - i)) != (Halfedge *) NULL)
00204                 break;
00205             if ((he = ELgethash(bucket + i)) != (Halfedge *) NULL)
00206                 break;
00207         };
00208         totalsearch += i;
00209     };
00210     ntry += 1;
00211 /* Now search linear list of halfedges for the corect one */
00212     if (he == ELleftend || (he != ELrightend && right_of(he, p))) {
00213         do {
00214             he = he->ELright;
00215         } while (he != ELrightend && right_of(he, p));
00216         he = he->ELleft;
00217     } else
00218         do {
00219             he = he->ELleft;
00220         } while (he != ELleftend && !right_of(he, p));
00221 
00222 /* Update hash table and reference counts */
00223     if (bucket > 0 && bucket < ELhashsize - 1) {
00224         if (ELhash[bucket] != (Halfedge *) NULL)
00225             ELhash[bucket]->ELrefcnt -= 1;
00226         ELhash[bucket] = he;
00227         ELhash[bucket]->ELrefcnt += 1;
00228     };
00229     return (he);
00230 }
00231 
00232 
00233 /* This delete routine can't reclaim node, since pointers from hash
00234    table may be present.   */
00235 void ELdelete(Halfedge * he)
00236 {
00237     (he->ELleft)->ELright = he->ELright;
00238     (he->ELright)->ELleft = he->ELleft;
00239     he->ELedge = (Edge *) DELETED;
00240 }
00241 
00242 
00243 Halfedge *ELright(Halfedge * he)
00244 {
00245     return (he->ELright);
00246 }
00247 
00248 Halfedge *ELleft(Halfedge * he)
00249 {
00250     return (he->ELleft);
00251 }
00252 
00253 
00254 Site *leftreg(Halfedge * he)
00255 {
00256     if (he->ELedge == (Edge *) NULL)
00257         return (bottomsite);
00258     return (he->ELpm == le ? he->ELedge->reg[le] : he->ELedge->reg[re]);
00259 }
00260 
00261 Site *rightreg(Halfedge * he)
00262 {
00263     if (he->ELedge == (Edge *) NULL)
00264         return (bottomsite);
00265     return (he->ELpm == le ? he->ELedge->reg[re] : he->ELedge->reg[le]);
00266 }

Generated on Mon Mar 31 19:03:27 2008 for Graphviz by  doxygen 1.5.1