Graphviz 14.1.3~dev.20260201.2050
Loading...
Searching...
No Matches
voronoi.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 "config.h"
12
13#include <neatogen/geometry.h>
14#include <neatogen/edges.h>
15#include <neatogen/hedges.h>
16#include <neatogen/heap.h>
17#include <neatogen/voronoi.h>
18#include <util/gv_math.h>
19#include <util/list.h>
20
21void voronoi(Site *(*nextsite)(void *context), void *context) {
22 Site *newsite, *bot, *top, *p;
23 Site *v;
24 Point newintstar = {0};
25 char pm;
26 Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector;
27 Edge *e;
28
29 pq_t *pq = PQinitialize();
30 bottomsite = nextsite(context);
31 el_state_t st = {0};
32 ELinitialize(&st);
33
34 newsite = nextsite(context);
35 while (1) {
36 if (!PQempty(pq))
37 newintstar = PQ_min(pq);
38
39 if (newsite != NULL &&
40 (PQempty(pq) || newsite->coord.y < newintstar.y ||
41 (newsite->coord.y ==newintstar.y && newsite->coord.x < newintstar.x))) {
42 /* new site is smallest */
43 lbnd = ELleftbnd(&st, &newsite->coord);
44 rbnd = ELright(lbnd);
45 bot = rightreg(lbnd);
46 e = gvbisect(bot, newsite, &st.allocated);
47 bisector = HEcreate(&st, e, le);
48 ELinsert(lbnd, bisector);
49 if ((p = hintersect(lbnd, bisector, &st.allocated)) != NULL) {
50 PQdelete(pq, lbnd);
51 PQinsert(pq, lbnd, p, ngdist(p, newsite));
52 }
53 lbnd = bisector;
54 bisector = HEcreate(&st, e, re);
55 ELinsert(lbnd, bisector);
56 if ((p = hintersect(bisector, rbnd, &st.allocated)) != NULL)
57 PQinsert(pq, bisector, p, ngdist(p, newsite));
58 newsite = nextsite(context);
59 } else if (!PQempty(pq)) {
60 /* intersection is smallest */
61 lbnd = PQextractmin(pq);
62 llbnd = ELleft(lbnd);
63 rbnd = ELright(lbnd);
64 rrbnd = ELright(rbnd);
65 bot = leftreg(lbnd);
66 top = rightreg(rbnd);
67 v = lbnd->vertex;
68 endpoint(lbnd->ELedge, lbnd->ELpm, v, &st.allocated);
69 endpoint(rbnd->ELedge, rbnd->ELpm, v, &st.allocated);
70 ELdelete(lbnd);
71 PQdelete(pq, rbnd);
72 ELdelete(rbnd);
73 pm = le;
74 if (bot->coord.y > top->coord.y) {
75 SWAP(&bot, &top);
76 pm = re;
77 }
78 e = gvbisect(bot, top, &st.allocated);
79 bisector = HEcreate(&st, e, pm);
80 ELinsert(llbnd, bisector);
81 endpoint(e, re - pm, v, &st.allocated);
82 if ((p = hintersect(llbnd, bisector, &st.allocated)) != NULL) {
83 PQdelete(pq, llbnd);
84 PQinsert(pq, llbnd, p, ngdist(p, bot));
85 }
86 if ((p = hintersect(bisector, rrbnd, &st.allocated)) != NULL) {
87 PQinsert(pq, bisector, p, ngdist(p, bot));
88 }
89 } else
90 break;
91 }
92
93 for (lbnd = ELright(st.leftend); lbnd != st.rightend;
94 lbnd = ELright(lbnd)) {
95 e = lbnd->ELedge;
96 clip_line(e);
97 }
98
99 ELcleanup(&st);
100
101 // `PQcleanup` relies on the number of sites, so should be discarded and
102 // at least every time we use `vAdjust`. See note in adjust.c:cleanup().
103 PQcleanup(pq);
104}
void clip_line(Edge *e)
Definition edges.c:61
void endpoint(Edge *e, int lr, Site *s, arena_t *allocator)
Definition edges.c:177
Edge * gvbisect(Site *s1, Site *s2, arena_t *allocator)
Definition edges.c:23
#define le
Definition edges.h:29
#define re
Definition edges.h:30
node NULL
Definition grammar.y:181
Arithmetic helper functions.
#define SWAP(a, b)
Definition gv_math.h:134
Point PQ_min(pq_t *pq)
Definition heap.c:96
void PQcleanup(pq_t *pq)
Definition heap.c:114
bool PQempty(const pq_t *pq)
Definition heap.c:92
void PQdelete(pq_t *pq, Halfedge *he)
Definition heap.c:79
pq_t * PQinitialize(void)
Definition heap.c:121
Halfedge * PQextractmin(pq_t *pq)
Definition heap.c:107
void PQinsert(pq_t *pq, Halfedge *he, Site *v, double offset)
Definition heap.c:64
Site * hintersect(Halfedge *el1, Halfedge *el2, arena_t *allocator)
Definition hedges.c:45
Halfedge * ELright(Halfedge *he)
Definition hedges.c:228
void ELcleanup(el_state_t *st)
Definition hedges.c:23
void ELinitialize(el_state_t *st)
Definition hedges.c:28
void ELinsert(Halfedge *lb, Halfedge *new)
Definition hedges.c:141
Site * rightreg(Halfedge *he)
Definition hedges.c:246
Halfedge * ELleft(Halfedge *he)
Definition hedges.c:233
Halfedge * ELleftbnd(el_state_t *st, Point *p)
Definition hedges.c:182
void ELdelete(Halfedge *he)
Definition hedges.c:220
Halfedge * HEcreate(el_state_t *st, Edge *e, char pm)
Definition hedges.c:131
Site * leftreg(Halfedge *he)
Definition hedges.c:239
static Agedge_t * top(edge_stack_t *sp)
Definition tred.c:75
type-generic dynamically expanding list
double ngdist(Site *s, Site *t)
Definition site.c:18
Site * bottomsite
Definition site.c:16
Definition edges.h:23
Edge * ELedge
Definition hedges.h:25
char ELpm
Definition hedges.h:26
Site * vertex
Definition hedges.h:27
double x
Definition geometry.h:24
double y
Definition geometry.h:24
Definition site.h:23
Point coord
Definition site.h:24
Halfedge * leftend
Definition hedges.h:36
arena_t allocated
outstanding dynamic allocations
Definition hedges.h:33
Halfedge * rightend
Definition hedges.h:37
Definition heap.c:20
void voronoi(Site *(*nextsite)(void *context), void *context)
Definition voronoi.c:21