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