Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
hedges.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include <neatogen/mem.h>
12#include <neatogen/hedges.h>
13#include <common/render.h>
14#include <stdbool.h>
15#include <util/alloc.h>
16
17#define DELETED -2
18
20
22static int ELhashsize;
24
25void ELcleanup(void)
26{
27 freeinit(&hfl, sizeof(**ELhash));
28 free(ELhash);
29 ELhash = NULL;
30}
31
32void ELinitialize(void)
33{
34 int i;
35
36 freeinit(&hfl, sizeof(**ELhash));
38 if (ELhash == NULL)
39 ELhash = gv_calloc(ELhashsize, sizeof(Halfedge *));
40 for (i = 0; i < ELhashsize; ++i)
41 ELhash[i] = NULL;
48 ELhash[0] = ELleftend;
50}
51
52
54{
55 Edge *e1, *e2, *e;
56 Halfedge *el;
57 double d, xint, yint;
58 bool right_of_site;
59 Site *v;
60
61 e1 = el1->ELedge;
62 e2 = el2->ELedge;
63 if (e1 == NULL || e2 == NULL)
64 return NULL;
65 if (e1->reg[1] == e2->reg[1])
66 return NULL;
67
68 d = e1->a * e2->b - e1->b * e2->a;
69 if (-1.0e-10 < d && d < 1.0e-10)
70 return NULL;
71
72 xint = (e1->c * e2->b - e2->c * e1->b) / d;
73 yint = (e2->c * e1->a - e1->c * e2->a) / d;
74
75 if (e1->reg[1]->coord.y < e2->reg[1]->coord.y ||
76 (e1->reg[1]->coord.y == e2->reg[1]->coord.y &&
77 e1->reg[1]->coord.x < e2->reg[1]->coord.x)) {
78 el = el1;
79 e = e1;
80 } else {
81 el = el2;
82 e = e2;
83 }
84 right_of_site = xint >= e->reg[1]->coord.x;
85 if ((right_of_site && el->ELpm == le) || (!right_of_site && el->ELpm == re))
86 return NULL;
87
88 v = getsite();
89 v->refcnt = 0;
90 v->coord.x = xint;
91 v->coord.y = yint;
92 return v;
93}
94
95/* returns 1 if p is to right of halfedge e */
96int right_of(Halfedge * el, Point * p)
97{
98 Edge *e;
99 Site *topsite;
100 int above, fast;
101 double dxp, dyp, dxs, t1, t2, t3, yl;
102
103 e = el->ELedge;
104 topsite = e->reg[1];
105 bool right_of_site = p->x > topsite->coord.x;
106 if (right_of_site && el->ELpm == le)
107 return 1;
108 if (!right_of_site && el->ELpm == re)
109 return 0;
110
111 if (e->a == 1.0) {
112 dyp = p->y - topsite->coord.y;
113 dxp = p->x - topsite->coord.x;
114 fast = 0;
115 if ((!right_of_site && e->b < 0.0) || (right_of_site && e->b >= 0.0)) {
116 above = dyp >= e->b * dxp;
117 fast = above;
118 } else {
119 above = p->x + p->y * e->b > e->c;
120 if (e->b < 0.0)
121 above = !above;
122 if (!above)
123 fast = 1;
124 }
125 if (!fast) {
126 dxs = topsite->coord.x - (e->reg[0])->coord.x;
127 above = e->b * (dxp * dxp - dyp * dyp) <
128 dxs * dyp * (1.0 + 2.0 * dxp / dxs + e->b * e->b);
129 if (e->b < 0.0)
130 above = !above;
131 }
132 } else { /*e->b==1.0 */
133 yl = e->c - e->a * p->x;
134 t1 = p->y - yl;
135 t2 = p->x - topsite->coord.x;
136 t3 = yl - topsite->coord.y;
137 above = t1 * t1 > t2 * t2 + t3 * t3;
138 }
139 return el->ELpm == le ? above : !above;
140}
141
142Halfedge *HEcreate(Edge * e, char pm)
143{
144 Halfedge *answer;
145 answer = getfree(&hfl);
146 answer->ELedge = e;
147 answer->ELpm = pm;
148 answer->PQnext = NULL;
149 answer->vertex = NULL;
150 answer->ELrefcnt = 0;
151 return answer;
152}
153
154
155void ELinsert(Halfedge * lb, Halfedge * new)
156{
157 new->ELleft = lb;
158 new->ELright = lb->ELright;
159 (lb->ELright)->ELleft = new;
160 lb->ELright = new;
161}
162
163/* Get entry from hash table, pruning any deleted nodes */
164static Halfedge *ELgethash(int b)
165{
166 Halfedge *he;
167
168 if (b < 0 || b >= ELhashsize)
169 return NULL;
170 he = ELhash[b];
171 if (he == NULL || he->ELedge != (Edge *) DELETED)
172 return he;
173
174/* Hash table points to deleted half edge. Patch as necessary. */
175 ELhash[b] = NULL;
176 if (--he->ELrefcnt == 0)
177 makefree(he, &hfl);
178 return NULL;
179}
180
182{
183 int i, bucket;
184 Halfedge *he;
185
186/* Use hash table to get close to desired halfedge */
187 bucket = (p->x - xmin) / deltax * ELhashsize;
188 if (bucket < 0)
189 bucket = 0;
190 if (bucket >= ELhashsize)
191 bucket = ELhashsize - 1;
192 he = ELgethash(bucket);
193 if (he == NULL) {
194 for (i = 1; ; ++i) {
195 if ((he = ELgethash(bucket - i)) != NULL)
196 break;
197 if ((he = ELgethash(bucket + i)) != NULL)
198 break;
199 }
200 }
201/* Now search linear list of halfedges for the corect one */
202 if (he == ELleftend || (he != ELrightend && right_of(he, p))) {
203 do {
204 he = he->ELright;
205 } while (he != ELrightend && right_of(he, p));
206 he = he->ELleft;
207 } else
208 do {
209 he = he->ELleft;
210 } while (he != ELleftend && !right_of(he, p));
211
212/* Update hash table and reference counts */
213 if (bucket > 0 && bucket < ELhashsize - 1) {
214 if (ELhash[bucket] != NULL)
215 --ELhash[bucket]->ELrefcnt;
216 ELhash[bucket] = he;
217 ++ELhash[bucket]->ELrefcnt;
218 }
219 return he;
220}
221
222
223/* This delete routine can't reclaim node, since pointers from hash
224 table may be present. */
226{
227 (he->ELleft)->ELright = he->ELright;
228 (he->ELright)->ELleft = he->ELleft;
229 he->ELedge = (Edge *) DELETED;
230}
231
232
234{
235 return he->ELright;
236}
237
239{
240 return he->ELleft;
241}
242
243
245{
246 if (he->ELedge == NULL)
247 return (bottomsite);
248 return he->ELpm == le ? he->ELedge->reg[le] : he->ELedge->reg[re];
249}
250
252{
253 if (he->ELedge == NULL)
254 return (bottomsite);
255 return he->ELpm == le ? he->ELedge->reg[re] : he->ELedge->reg[le];
256}
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
#define le
Definition edges.h:25
#define re
Definition edges.h:26
double deltax
Definition geometry.c:16
double xmin
Definition geometry.c:15
int sqrt_nsites
Definition geometry.c:19
void free(void *)
node NULL
Definition grammar.y:163
static Halfedge ** ELhash
Definition hedges.c:23
Halfedge * ELright(Halfedge *he)
Definition hedges.c:233
static int ELhashsize
Definition hedges.c:22
void ELinsert(Halfedge *lb, Halfedge *new)
Definition hedges.c:155
Halfedge * ELrightend
Definition hedges.c:19
Site * hintersect(Halfedge *el1, Halfedge *el2)
Definition hedges.c:53
Halfedge * ELleftbnd(Point *p)
Definition hedges.c:181
Site * rightreg(Halfedge *he)
Definition hedges.c:251
void ELinitialize(void)
Definition hedges.c:32
Halfedge * ELleft(Halfedge *he)
Definition hedges.c:238
Halfedge * HEcreate(Edge *e, char pm)
Definition hedges.c:142
void ELcleanup(void)
Definition hedges.c:25
Halfedge * ELleftend
Definition hedges.c:19
#define DELETED
Definition hedges.c:17
static Halfedge * ELgethash(int b)
Definition hedges.c:164
int right_of(Halfedge *el, Point *p)
Definition hedges.c:96
void ELdelete(Halfedge *he)
Definition hedges.c:225
Site * leftreg(Halfedge *he)
Definition hedges.c:244
static Freelist hfl
Definition hedges.c:21
void * getfree(Freelist *)
Definition memory.c:60
void makefree(void *, Freelist *)
Definition memory.c:83
void freeinit(Freelist *, int)
Definition memory.c:41
pointf coord(node_t *n)
Definition utils.c:150
Site * getsite(void)
Definition site.c:29
Site * bottomsite
Definition site.c:17
Definition edges.h:19
double b
Definition edges.h:20
double c
Definition edges.h:20
Site * reg[2]
Definition edges.h:22
double a
Definition edges.h:20
Edge * ELedge
Definition hedges.h:22
struct Halfedge * PQnext
Definition hedges.h:27
char ELpm
Definition hedges.h:24
Site * vertex
Definition hedges.h:25
struct Halfedge * ELleft
Definition hedges.h:21
int ELrefcnt
Definition hedges.h:23
struct Halfedge * ELright
Definition hedges.h:21
double x
Definition geometry.h:23
double y
Definition geometry.h:23
Definition site.h:22
Point coord
Definition site.h:23
unsigned refcnt
Definition site.h:25
Definition mem.h:21
double x
Definition geom.h:29