Graphviz
14.1.2~dev.20251218.0900
Loading...
Searching...
No Matches
partition.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
#include <assert.h>
13
#include <
common/boxes.h
>
14
#include <
common/geomprocs.h
>
15
#include <limits.h>
16
#include <
ortho/partition.h
>
17
#include <
ortho/trap.h
>
18
#include <math.h>
19
#include <stdbool.h>
20
#include <stdint.h>
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <
util/alloc.h
>
24
#include <
util/bitarray.h
>
25
#include <
util/gv_math.h
>
26
#include <
util/list.h
>
27
#include <
util/prisize_t.h
>
28
29
#ifndef DEBUG
30
#define DEBUG 0
31
#endif
32
33
#define NPOINTS 4
/* only rectangles */
34
35
#define TR_FROM_UP 1
/* for traverse-direction */
36
#define TR_FROM_DN 2
37
38
#define SP_SIMPLE_LRUP 1
/* for splitting trapezoids */
39
#define SP_SIMPLE_LRDN 2
40
#define SP_2UP_2DN 3
41
#define SP_2UP_LEFT 4
42
#define SP_2UP_RIGHT 5
43
#define SP_2DN_LEFT 6
44
#define SP_2DN_RIGHT 7
45
#define SP_NOSPLIT -1
46
47
#define DOT(v0, v1) ((v0).x * (v1).x + (v0).y * (v1).y)
48
#define CROSS_SINE(v0, v1) ((v0).x * (v1).y - (v1).x * (v0).y)
49
#define LENGTH(v0) hypot((v0).x, (v0).y)
50
51
#ifndef HAVE_SRAND48
52
#define srand48 srand
53
#endif
54
#ifdef _WIN32
55
extern
double
drand48
(
void
);
56
#endif
57
58
typedef
struct
{
59
int
vnum
;
60
int
next
;
/* Circularly linked list */
61
int
prev
;
/* describing the monotone */
62
int
marked
;
/* polygon */
63
}
monchain_t
;
64
65
typedef
LIST
(
monchain_t
) monchains_t;
66
75
static
monchain_t
monchains_get(
const
monchains_t *chain,
int
index) {
76
assert(chain !=
NULL
);
77
78
// infer zeroed data for out of range entries
79
if
(index < 0 || (
size_t
)index >=
LIST_SIZE
(chain)) {
80
return
(
monchain_t
){0};
81
}
82
83
return
LIST_GET
(chain, (
size_t
)index);
84
}
85
94
static
monchain_t
*
monchains_at
(monchains_t *chain,
int
index) {
95
assert(chain !=
NULL
);
96
assert(index >= 0);
97
98
// expand on demand
99
while
((
size_t
)index >=
LIST_SIZE
(chain)) {
100
LIST_APPEND
(chain, (
monchain_t
){0});
101
}
102
103
return
LIST_AT
(chain, (
size_t
)index);
104
}
105
106
typedef
struct
{
107
pointf
pt
;
108
int
vnext[4];
/* next vertices for the 4 chains */
109
int
vpos[4];
/* position of v in the 4 chains */
110
int
nextfree
;
111
}
vertexchain_t
;
112
113
static
int
chain_idx
;
114
static
size_t
mon_idx
;
115
/* chain init. information. This */
116
/* is used to decide which */
117
/* monotone polygon to split if */
118
/* there are several other */
119
/* polygons touching at the same */
120
/* vertex */
121
static
vertexchain_t
*
vert
;
122
/* contains position of any vertex in */
123
/* the monotone chain for the polygon */
124
static
int
*
mon
;
125
126
/* return a new mon structure from the table */
127
#define newmon() (++mon_idx)
128
/* return a new chain element from the table */
129
#define new_chain_element() (++chain_idx)
130
131
static
void
132
convert
(
boxf
bb,
int
flip,
int
ccw
,
pointf
* pts)
133
{
134
pts[0] = bb.
LL
;
135
pts[2] = bb.
UR
;
136
if
(
ccw
) {
137
pts[1].
x
= bb.
UR
.
x
;
138
pts[1].
y
= bb.
LL
.
y
;
139
pts[3].
x
= bb.
LL
.
x
;
140
pts[3].
y
= bb.
UR
.
y
;
141
}
142
else
{
143
pts[1].
x
= bb.
LL
.
x
;
144
pts[1].
y
= bb.
UR
.
y
;
145
pts[3].
x
= bb.
UR
.
x
;
146
pts[3].
y
= bb.
LL
.
y
;
147
}
148
if
(flip) {
149
int
i;
150
for
(i = 0; i <
NPOINTS
; i++) {
151
pts[i] =
perp
(pts[i]);
152
}
153
}
154
}
155
156
static
int
157
store
(
segment_t
* seg,
int
first,
pointf
* pts)
158
{
159
int
i,
last
= first +
NPOINTS
- 1;
160
int
j = 0;
161
162
for
(i = first; i <=
last
; i++, j++) {
163
if
(i == first) {
164
seg[i].
next
= first+1;
165
seg[i].
prev
=
last
;
166
}
167
else
if
(i ==
last
) {
168
seg[i].
next
= first;
169
seg[i].
prev
=
last
-1;
170
}
171
else
{
172
seg[i].
next
= i+1;
173
seg[i].
prev
= i-1;
174
}
175
seg[i].
is_inserted
=
false
;
176
seg[seg[i].
prev
].
v1
= seg[i].
v0
= pts[j];
177
}
178
return
(
last
+1);
179
}
180
181
static
void
genSegments
(
cell
*cells,
size_t
ncells,
boxf
bb,
segment_t
*seg,
182
int
flip) {
183
int
i = 1;
184
pointf
pts[4];
185
186
convert
(bb, flip, 1, pts);
187
i =
store
(seg, i, pts);
188
for
(
size_t
j = 0; j < ncells; j++) {
189
convert
(cells[j].bb, flip, 0, pts);
190
i =
store
(seg, i, pts);
191
}
192
}
193
194
/* Generate a random permutation of the segments 1..n */
195
static
void
generateRandomOrdering
(
size_t
n,
int
*permute) {
196
for
(
size_t
i = 0; i < n; i++) {
197
assert(i < INT_MAX);
198
permute[i] = (int)i + 1;
199
}
200
201
for
(
size_t
i = 0; i < n; i++) {
202
const
size_t
j = (size_t)((
double
)i +
drand48
() * (double)(n - i));
203
if
(j != i) {
204
SWAP
(&permute[i], &permute[j]);
205
}
206
}
207
}
208
209
/* Function returns true if the trapezoid lies inside the polygon */
210
static
bool
211
inside_polygon
(
trap_t
*t,
segment_t
* seg)
212
{
213
int
rseg = t->
rseg
;
214
215
if
(!t->
is_valid
)
216
return
false
;
217
218
if
(t->
lseg
<= 0 || t->
rseg
<= 0)
219
return
false
;
220
221
if
((!
is_valid_trap
(t->
u0
) && !
is_valid_trap
(t->
u1
)) || (!
is_valid_trap
(t->
d0
) && !
is_valid_trap
(t->
d1
)))
// triangle
222
return
greater_than
(seg[rseg].v1, seg[rseg].v0);
223
224
return
false
;
225
}
226
227
static
double
228
get_angle
(
pointf
*vp0,
pointf
*vpnext,
pointf
*vp1)
229
{
230
pointf
v0, v1;
231
232
v0.
x
= vpnext->
x
- vp0->
x
;
233
v0.
y
= vpnext->
y
- vp0->
y
;
234
235
v1.
x
= vp1->
x
- vp0->
x
;
236
v1.
y
= vp1->
y
- vp0->
y
;
237
238
if
(
CROSS_SINE
(v0, v1) >= 0)
/* sine is positive */
239
return
DOT
(v0, v1)/
LENGTH
(v0)/
LENGTH
(v1);
240
else
241
return
-1.0 *
DOT
(v0, v1)/
LENGTH
(v0)/
LENGTH
(v1) - 2;
242
}
243
244
/* (v0, v1) is the new diagonal to be added to the polygon. Find which */
245
/* chain to use and return the positions of v0 and v1 in p and q */
246
static
void
247
get_vertex_positions
(
int
v0,
int
v1,
int
*ip,
int
*iq)
248
{
249
vertexchain_t
*vp0, *vp1;
250
int
i;
251
double
angle, temp;
252
int
tp = 0, tq = 0;
253
254
vp0 = &
vert
[v0];
255
vp1 = &
vert
[v1];
256
257
/* p is identified as follows. Scan from (v0, v1) rightwards till */
258
/* you hit the first segment starting from v0. That chain is the */
259
/* chain of our interest */
260
261
angle = -4.0;
262
for
(i = 0; i < 4; i++)
263
{
264
if
(vp0->
vnext
[i] <= 0)
265
continue
;
266
if
((temp =
get_angle
(&vp0->
pt
, &(
vert
[vp0->
vnext
[i]].
pt
),
267
&vp1->
pt
)) > angle)
268
{
269
angle = temp;
270
tp = i;
271
}
272
}
273
274
*ip = tp;
275
276
/* Do similar actions for q */
277
278
angle = -4.0;
279
for
(i = 0; i < 4; i++)
280
{
281
if
(vp1->
vnext
[i] <= 0)
282
continue
;
283
if
((temp =
get_angle
(&vp1->
pt
, &(
vert
[vp1->
vnext
[i]].
pt
),
284
&vp0->
pt
)) > angle)
285
{
286
angle = temp;
287
tq = i;
288
}
289
}
290
291
*iq = tq;
292
}
293
294
/* v0 and v1 are specified in anti-clockwise order with respect to
295
* the current monotone polygon mcur. Split the current polygon into
296
* two polygons using the diagonal (v0, v1)
297
*
298
* @param chain Monotone polygon chain to operate on
299
*/
300
static
size_t
make_new_monotone_poly
(monchains_t *chain,
size_t
mcur,
int
v0,
301
int
v1) {
302
int
p, q, ip, iq;
303
const
size_t
mnew =
newmon
();
304
int
i, j, nf0, nf1;
305
vertexchain_t
*vp0, *vp1;
306
307
vp0 = &
vert
[v0];
308
vp1 = &
vert
[v1];
309
310
get_vertex_positions
(v0, v1, &ip, &iq);
311
312
p = vp0->
vpos
[ip];
313
q = vp1->
vpos
[iq];
314
315
/* At this stage, we have got the positions of v0 and v1 in the */
316
/* desired chain. Now modify the linked lists */
317
318
i =
new_chain_element
();
/* for the new list */
319
j =
new_chain_element
();
320
321
monchains_at
(chain, i)->
vnum
= v0;
322
monchains_at
(chain, j)->
vnum
= v1;
323
324
monchains_at
(chain, i)->
next
= monchains_get(chain, p).next;
325
monchains_at
(chain, monchains_get(chain, p).next)->
prev
= i;
326
monchains_at
(chain, i)->
prev
= j;
327
monchains_at
(chain, j)->
next
= i;
328
monchains_at
(chain, j)->
prev
= monchains_get(chain, q).prev;
329
monchains_at
(chain, monchains_get(chain, q).
prev
)->
next
= j;
330
331
monchains_at
(chain, p)->
next
= q;
332
monchains_at
(chain, q)->
prev
= p;
333
334
nf0 = vp0->
nextfree
;
335
nf1 = vp1->
nextfree
;
336
337
vp0->
vnext
[ip] = v1;
338
339
vp0->
vpos
[nf0] = i;
340
vp0->
vnext
[nf0] = monchains_get(chain, monchains_get(chain, i).next).vnum;
341
vp1->
vpos
[nf1] = j;
342
vp1->
vnext
[nf1] = v0;
343
344
vp0->
nextfree
++;
345
vp1->
nextfree
++;
346
347
#if DEBUG > 0
348
fprintf(stderr,
"make_poly: mcur = %"
PRISIZE_T
", (v0, v1) = (%d, %d)\n"
,
349
mcur, v0, v1);
350
fprintf(stderr,
"next posns = (p, q) = (%d, %d)\n"
, p, q);
351
#endif
352
353
mon
[mcur] = p;
354
mon
[mnew] = i;
355
return
mnew;
356
}
357
361
static
void
traverse_polygon
(
bitarray_t
*visited, boxes_t *decomp,
362
segment_t
*seg, traps_t *tr,
size_t
mcur,
363
size_t
trnum,
size_t
from,
int
flip,
int
dir,
364
monchains_t *chain) {
365
size_t
mnew;
366
int
v0, v1;
367
368
if
(!
is_valid_trap
(trnum) ||
bitarray_get
(*visited, trnum))
369
return
;
370
371
trap_t
*t =
LIST_AT
(tr, trnum);
372
373
bitarray_set
(visited, trnum,
true
);
374
375
if
(t->
hi
.
y
> t->
lo
.
y
+
C_EPS
&&
fp_equal
(seg[t->
lseg
].
v0
.
x
, seg[t->
lseg
].
v1
.
x
) &&
376
fp_equal
(seg[t->
rseg
].
v0
.
x
, seg[t->
rseg
].
v1
.
x
)) {
377
boxf
newbox = {0};
378
if
(flip) {
379
newbox.
LL
.
x
= t->
lo
.
y
;
380
newbox.
LL
.
y
= -seg[t->
rseg
].
v0
.
x
;
381
newbox.
UR
.
x
= t->
hi
.
y
;
382
newbox.
UR
.
y
= -seg[t->
lseg
].
v0
.
x
;
383
}
else
{
384
newbox.
LL
.
x
= seg[t->
lseg
].
v0
.
x
;
385
newbox.
LL
.
y
= t->
lo
.
y
;
386
newbox.
UR
.
x
= seg[t->
rseg
].
v0
.
x
;
387
newbox.
UR
.
y
= t->
hi
.
y
;
388
}
389
LIST_APPEND
(decomp, newbox);
390
}
391
392
/* We have much more information available here. */
393
/* rseg: goes upwards */
394
/* lseg: goes downwards */
395
396
/* Initially assume that dir = TR_FROM_DN (from the left) */
397
/* Switch v0 and v1 if necessary afterwards */
398
399
400
/* special cases for triangles with cusps at the opposite ends. */
401
/* take care of this first */
402
if
(!
is_valid_trap
(t->
u0
) && !
is_valid_trap
(t->
u1
)) {
403
if
(
is_valid_trap
(t->
d0
) &&
is_valid_trap
(t->
d1
)) {
// downward opening triangle
404
v0 =
LIST_GET
(tr, t->
d1
).lseg;
405
v1 = t->
lseg
;
406
if
(from == t->
d1
)
407
{
408
mnew =
make_new_monotone_poly
(chain, mcur, v1, v0);
409
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
410
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
411
}
412
else
413
{
414
mnew =
make_new_monotone_poly
(chain, mcur, v0, v1);
415
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
416
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
417
}
418
}
419
else
420
{
421
/* Just traverse all neighbours */
422
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
423
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
424
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
425
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
426
}
427
}
428
429
else
if
(!
is_valid_trap
(t->
d0
) && !
is_valid_trap
(t->
d1
)) {
430
if
(
is_valid_trap
(t->
u0
) &&
is_valid_trap
(t->
u1
)) {
// upward opening triangle
431
v0 = t->
rseg
;
432
v1 =
LIST_GET
(tr, t->
u0
).rseg;
433
if
(from == t->
u1
)
434
{
435
mnew =
make_new_monotone_poly
(chain, mcur, v1, v0);
436
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
437
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
438
}
439
else
440
{
441
mnew =
make_new_monotone_poly
(chain, mcur, v0, v1);
442
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
443
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
444
}
445
}
446
else
447
{
448
/* Just traverse all neighbours */
449
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
450
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
451
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
452
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
453
}
454
}
455
456
else
if
(
is_valid_trap
(t->
u0
) &&
is_valid_trap
(t->
u1
)) {
457
if
(
is_valid_trap
(t->
d0
) &&
is_valid_trap
(t->
d1
)) {
// downward + upward cusps
458
v0 =
LIST_GET
(tr, t->
d1
).lseg;
459
v1 =
LIST_GET
(tr, t->
u0
).rseg;
460
if
((dir ==
TR_FROM_DN
&& t->
d1
== from) ||
461
(dir ==
TR_FROM_UP
&& t->
u1
== from))
462
{
463
mnew =
make_new_monotone_poly
(chain, mcur, v1, v0);
464
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
465
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
466
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
467
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
468
}
469
else
470
{
471
mnew =
make_new_monotone_poly
(chain, mcur, v0, v1);
472
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
473
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
474
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
475
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
476
}
477
}
478
else
/* only downward cusp */
479
{
480
if
(
equal_to
(t->
lo
, seg[t->
lseg
].
v1
)) {
481
v0 =
LIST_GET
(tr, t->
u0
).rseg;
482
v1 = seg[t->
lseg
].
next
;
483
484
if
(dir ==
TR_FROM_UP
&& t->
u0
== from)
485
{
486
mnew =
make_new_monotone_poly
(chain, mcur, v1, v0);
487
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
488
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
489
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
490
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
491
}
492
else
493
{
494
mnew =
make_new_monotone_poly
(chain, mcur, v0, v1);
495
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
496
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
497
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
498
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
499
}
500
}
501
else
502
{
503
v0 = t->
rseg
;
504
v1 =
LIST_GET
(tr, t->
u0
).rseg;
505
if
(dir ==
TR_FROM_UP
&& t->
u1
== from)
506
{
507
mnew =
make_new_monotone_poly
(chain, mcur, v1, v0);
508
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
509
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
510
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
511
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
512
}
513
else
514
{
515
mnew =
make_new_monotone_poly
(chain, mcur, v0, v1);
516
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
517
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
518
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
519
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
520
}
521
}
522
}
523
}
524
else
if
(
is_valid_trap
(t->
u0
) ||
is_valid_trap
(t->
u1
)) {
// no downward cusp
525
if
(
is_valid_trap
(t->
d0
) &&
is_valid_trap
(t->
d1
)) {
// only upward cusp
526
if
(
equal_to
(t->
hi
, seg[t->
lseg
].
v0
)) {
527
v0 =
LIST_GET
(tr, t->
d1
).lseg;
528
v1 = t->
lseg
;
529
if
(!(dir ==
TR_FROM_DN
&& t->
d0
== from))
530
{
531
mnew =
make_new_monotone_poly
(chain, mcur, v1, v0);
532
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
533
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
534
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
535
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
536
}
537
else
538
{
539
mnew =
make_new_monotone_poly
(chain, mcur, v0, v1);
540
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
541
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
542
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
543
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
544
}
545
}
546
else
547
{
548
v0 =
LIST_GET
(tr, t->
d1
).lseg;
549
v1 = seg[t->
rseg
].
next
;
550
551
if
(dir ==
TR_FROM_DN
&& t->
d1
== from)
552
{
553
mnew =
make_new_monotone_poly
(chain, mcur, v1, v0);
554
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
555
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
556
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
557
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
558
}
559
else
560
{
561
mnew =
make_new_monotone_poly
(chain, mcur, v0, v1);
562
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
563
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
564
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
565
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
566
}
567
}
568
}
569
else
/* no cusp */
570
{
571
if
(
equal_to
(t->
hi
, seg[t->
lseg
].
v0
) &&
equal_to
(t->
lo
, seg[t->
rseg
].
v0
)) {
572
v0 = t->
rseg
;
573
v1 = t->
lseg
;
574
if
(dir ==
TR_FROM_UP
)
575
{
576
mnew =
make_new_monotone_poly
(chain, mcur, v1, v0);
577
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
578
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
579
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
580
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
581
}
582
else
583
{
584
mnew =
make_new_monotone_poly
(chain, mcur, v0, v1);
585
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
586
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
587
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
588
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
589
}
590
}
591
else
if
(
equal_to
(t->
hi
, seg[t->
rseg
].
v1
) &&
592
equal_to
(t->
lo
, seg[t->
lseg
].
v1
)) {
593
v0 = seg[t->
rseg
].
next
;
594
v1 = seg[t->
lseg
].
next
;
595
596
if
(dir ==
TR_FROM_UP
)
597
{
598
mnew =
make_new_monotone_poly
(chain, mcur, v1, v0);
599
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
600
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
601
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
602
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
603
}
604
else
605
{
606
mnew =
make_new_monotone_poly
(chain, mcur, v0, v1);
607
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
608
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
609
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
610
traverse_polygon
(visited, decomp, seg, tr, mnew, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
611
}
612
}
613
else
/* no split possible */
614
{
615
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u0
, trnum, flip,
TR_FROM_DN
, chain);
616
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d0
, trnum, flip,
TR_FROM_UP
, chain);
617
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
u1
, trnum, flip,
TR_FROM_DN
, chain);
618
traverse_polygon
(visited, decomp, seg, tr, mcur, t->
d1
, trnum, flip,
TR_FROM_UP
, chain);
619
}
620
}
621
}
622
}
623
624
static
void
625
monotonate_trapezoids
(
int
nsegs,
segment_t
*seg, traps_t *tr,
626
int
flip, boxes_t *decomp) {
627
int
i;
628
bitarray_t
visited =
bitarray_new
(
LIST_SIZE
(tr));
629
630
// Table to hold all the monotone polygons. Each monotone polygon is a
631
// circularly linked list
632
monchains_t mchain = {0};
633
634
vert
=
gv_calloc
(nsegs + 1,
sizeof
(
vertexchain_t
));
635
mon
=
gv_calloc
(nsegs,
sizeof
(
int
));
636
637
/* First locate a trapezoid which lies inside the polygon */
638
/* and which is triangular */
639
size_t
j;
640
for
(j = 0; j <
LIST_SIZE
(tr); j++)
641
if
(
inside_polygon
(
LIST_AT
(tr, j), seg))
break
;
642
const
size_t
tr_start = j;
643
644
/* Initialise the mon data-structure and start spanning all the */
645
/* trapezoids within the polygon */
646
647
for
(i = 1; i <= nsegs; i++) {
648
monchains_at
(&mchain, i)->
prev
= seg[i].
prev
;
649
monchains_at
(&mchain, i)->
next
= seg[i].
next
;
650
monchains_at
(&mchain, i)->
vnum
= i;
651
vert
[i].
pt
= seg[i].
v0
;
652
vert
[i].
vnext
[0] = seg[i].
next
;
/* next vertex */
653
vert
[i].
vpos
[0] = i;
/* locn. of next vertex */
654
vert
[i].
nextfree
= 1;
655
}
656
657
chain_idx
= nsegs;
658
mon_idx
= 0;
659
mon
[0] = 1;
/* position of any vertex in the first */
660
/* chain */
661
662
/* traverse the polygon */
663
if
(
is_valid_trap
(
LIST_GET
(tr, tr_start).u0))
664
traverse_polygon
(&visited, decomp, seg, tr, 0, tr_start,
665
LIST_GET
(tr, tr_start).u0, flip,
TR_FROM_UP
, &mchain);
666
else
if
(
is_valid_trap
(
LIST_GET
(tr, tr_start).d0))
667
traverse_polygon
(&visited, decomp, seg, tr, 0, tr_start,
668
LIST_GET
(tr, tr_start).d0, flip,
TR_FROM_DN
, &mchain);
669
670
bitarray_reset
(&visited);
671
LIST_FREE
(&mchain);
672
free
(
vert
);
673
free
(
mon
);
674
}
675
676
static
bool
rectIntersect
(
boxf
*d,
const
boxf
r0,
const
boxf
r1) {
677
double
t = fmax(r0.
LL
.
x
, r1.
LL
.
x
);
678
d->
UR
.
x
= fmin(r0.
UR
.
x
, r1.
UR
.
x
);
679
d->
LL
.
x
= t;
680
681
t = fmax(r0.
LL
.
y
, r1.
LL
.
y
);
682
d->
UR
.
y
= fmin(r0.
UR
.
y
, r1.
UR
.
y
);
683
d->
LL
.
y
= t;
684
685
return
!(d->
LL
.
x
>= d->
UR
.
x
|| d->
LL
.
y
>= d->
UR
.
y
);
686
}
687
688
#if DEBUG > 1
689
static
void
690
dumpTrap (
trap_t
* tr,
int
n)
691
{
692
int
i;
693
for
(i = 1; i <= n; i++) {
694
tr++;
695
fprintf(stderr,
"%d : %d %d (%f,%f) (%f,%f) %"
PRISIZE_T
" %"
PRISIZE_T
696
" %"
PRISIZE_T
" %"
PRISIZE_T
"\n"
, i, tr->
lseg
, tr->
rseg
,
697
tr->
hi
.
x
, tr->
hi
.
y
, tr->
lo
.
x
, tr->
lo
.
y
, tr->
u0
, tr->
u1
, tr->
d0
,
698
tr->
d1
);
699
fprintf(stderr,
" %"
PRISIZE_T
" %"
PRISIZE_T
" %d %s\n"
, tr->
sink
,
700
tr->
usave
, tr->
uside
, tr->
is_valid
?
"valid"
:
"invalid"
);
701
}
702
fprintf (stderr,
"====\n"
);
703
}
704
705
static
void
706
dumpSegs (
segment_t
* sg,
int
n)
707
{
708
int
i;
709
for
(i = 1; i <= n; i++) {
710
sg++;
711
fprintf(stderr,
"%d : (%f,%f) (%f,%f) %d %"
PRISIZE_T
" %"
PRISIZE_T
712
" %d %d\n"
, i, sg->
v0
.
x
, sg->
v0
.
y
, sg->
v1
.
x
, sg->
v1
.
y
,
713
(
int
)sg->
is_inserted
, sg->
root0
, sg->
root1
, sg->
next
, sg->
prev
);
714
}
715
fprintf (stderr,
"====\n"
);
716
}
717
#endif
718
719
boxf
*
partition
(
cell
*cells,
size_t
ncells,
size_t
*nrects,
boxf
bb) {
720
const
size_t
nsegs = 4 * (ncells + 1);
721
segment_t
* segs =
gv_calloc
(nsegs + 1,
sizeof
(
segment_t
));
722
int
* permute =
gv_calloc
(nsegs,
sizeof
(
int
));
723
724
if
(
DEBUG
) {
725
fprintf(stderr,
"cells = %"
PRISIZE_T
" segs = %"
PRISIZE_T
726
" traps = dynamic\n"
, ncells, nsegs);
727
}
728
genSegments
(cells, ncells, bb, segs, 0);
729
if
(
DEBUG
) {
730
fprintf(stderr,
"%"
PRISIZE_T
"\n\n"
, ncells + 1);
731
for
(
size_t
i = 1; i <= nsegs; i++) {
732
if
(i%4 == 1) fprintf(stderr,
"4\n"
);
733
fprintf (stderr,
"%f %f\n"
, segs[i].v0.x, segs[i].
v0
.
y
);
734
if
(i%4 == 0) fprintf(stderr,
"\n"
);
735
}
736
}
737
srand48
(173);
738
generateRandomOrdering
(nsegs, permute);
739
assert(nsegs <= INT_MAX);
740
traps_t hor_traps =
construct_trapezoids
((
int
)nsegs, segs, permute);
741
if
(
DEBUG
) {
742
fprintf(stderr,
"hor traps = %"
PRISIZE_T
"\n"
,
LIST_SIZE
(&hor_traps));
743
}
744
boxes_t hor_decomp = {0};
745
monotonate_trapezoids
((
int
)nsegs, segs, &hor_traps, 0, &hor_decomp);
746
LIST_FREE
(&hor_traps);
747
748
genSegments
(cells, ncells, bb, segs, 1);
749
generateRandomOrdering
(nsegs, permute);
750
traps_t ver_traps =
construct_trapezoids
((
int
)nsegs, segs, permute);
751
if
(
DEBUG
) {
752
fprintf(stderr,
"ver traps = %"
PRISIZE_T
"\n"
,
LIST_SIZE
(&ver_traps));
753
}
754
boxes_t vert_decomp = {0};
755
monotonate_trapezoids
((
int
)nsegs, segs, &ver_traps, 1, &vert_decomp);
756
LIST_FREE
(&ver_traps);
757
758
boxes_t rs = {0};
759
for
(
size_t
i = 0; i <
LIST_SIZE
(&vert_decomp); ++i)
760
for
(
size_t
j = 0; j <
LIST_SIZE
(&hor_decomp); ++j) {
761
boxf
newbox = {0};
762
if
(
rectIntersect
(&newbox,
LIST_GET
(&vert_decomp, i),
763
LIST_GET
(&hor_decomp, j)))
764
LIST_APPEND
(&rs, newbox);
765
}
766
767
free
(segs);
768
free
(permute);
769
LIST_FREE
(&hor_decomp);
770
LIST_FREE
(&vert_decomp);
771
boxf
*ret;
772
LIST_DETACH
(&rs, &ret, nrects);
773
return
ret;
774
}
last
static agxbuf last
last message
Definition
agerror.c:29
alloc.h
Memory allocation wrappers that exit on failure.
gv_calloc
static void * gv_calloc(size_t nmemb, size_t size)
Definition
alloc.h:26
bitarray.h
API for compacted arrays of booleans.
bitarray_new
static bitarray_t bitarray_new(size_t size_bits)
create an array of the given element length
Definition
bitarray.h:47
bitarray_get
static bool bitarray_get(bitarray_t self, size_t index)
get the value of the given element
Definition
bitarray.h:65
bitarray_set
static void bitarray_set(bitarray_t *self, size_t index, bool value)
set or clear the value of the given element
Definition
bitarray.h:80
bitarray_reset
static void bitarray_reset(bitarray_t *self)
free underlying resources and leave a bit array empty
Definition
bitarray.h:114
boxes.h
drand48
double drand48(void)
Definition
utils.c:1547
geomprocs.h
geometric functions (e.g. on points and boxes)
perp
static WUR pointf perp(pointf p)
Definition
geomprocs.h:140
free
void free(void *)
NULL
node NULL
Definition
grammar.y:181
gv_math.h
Arithmetic helper functions.
SWAP
#define SWAP(a, b)
Definition
gv_math.h:134
prev
$2 prev
Definition
htmlparse.y:291
list.h
type-generic dynamically expanding list
LIST_DETACH
#define LIST_DETACH(list, datap, sizep)
Definition
list.h:443
LIST_AT
#define LIST_AT(list, index)
Definition
list.h:168
LIST
#define LIST(type)
Definition
list.h:55
LIST_SIZE
#define LIST_SIZE(list)
Definition
list.h:80
LIST_APPEND
#define LIST_APPEND(list, item)
Definition
list.h:120
LIST_FREE
#define LIST_FREE(list)
Definition
list.h:370
LIST_GET
#define LIST_GET(list, index)
Definition
list.h:155
get_vertex_positions
static void get_vertex_positions(int v0, int v1, int *ip, int *iq)
Definition
partition.c:247
partition
boxf * partition(cell *cells, size_t ncells, size_t *nrects, boxf bb)
partitions space around cells (nodes) into rectangular tiles
Definition
partition.c:719
mon_idx
static size_t mon_idx
Definition
partition.c:114
NPOINTS
#define NPOINTS
Definition
partition.c:33
genSegments
static void genSegments(cell *cells, size_t ncells, boxf bb, segment_t *seg, int flip)
Definition
partition.c:181
newmon
#define newmon()
Definition
partition.c:127
TR_FROM_DN
#define TR_FROM_DN
Definition
partition.c:36
DOT
#define DOT(v0, v1)
Definition
partition.c:47
convert
static void convert(boxf bb, int flip, int ccw, pointf *pts)
Definition
partition.c:132
monchains_at
static monchain_t * monchains_at(monchains_t *chain, int index)
Definition
partition.c:94
get_angle
static double get_angle(pointf *vp0, pointf *vpnext, pointf *vp1)
Definition
partition.c:228
srand48
#define srand48
Definition
partition.c:52
chain_idx
static int chain_idx
Definition
partition.c:113
generateRandomOrdering
static void generateRandomOrdering(size_t n, int *permute)
Definition
partition.c:195
LENGTH
#define LENGTH(v0)
Definition
partition.c:49
traverse_polygon
static void traverse_polygon(bitarray_t *visited, boxes_t *decomp, segment_t *seg, traps_t *tr, size_t mcur, size_t trnum, size_t from, int flip, int dir, monchains_t *chain)
Definition
partition.c:361
mon
static int * mon
Definition
partition.c:124
make_new_monotone_poly
static size_t make_new_monotone_poly(monchains_t *chain, size_t mcur, int v0, int v1)
Definition
partition.c:300
rectIntersect
static bool rectIntersect(boxf *d, const boxf r0, const boxf r1)
Definition
partition.c:676
monotonate_trapezoids
static void monotonate_trapezoids(int nsegs, segment_t *seg, traps_t *tr, int flip, boxes_t *decomp)
Definition
partition.c:625
new_chain_element
#define new_chain_element()
Definition
partition.c:129
TR_FROM_UP
#define TR_FROM_UP
Definition
partition.c:35
inside_polygon
static bool inside_polygon(trap_t *t, segment_t *seg)
Definition
partition.c:211
DEBUG
#define DEBUG
Definition
partition.c:30
CROSS_SINE
#define CROSS_SINE(v0, v1)
Definition
partition.c:48
store
static int store(segment_t *seg, int first, pointf *pts)
Definition
partition.c:157
vert
static vertexchain_t * vert
Definition
partition.c:121
partition.h
function partition, subroutine of mkMaze
prisize_t.h
PRISIZE_T
#define PRISIZE_T
Definition
prisize_t.h:25
bitarray_t
Definition
bitarray.h:38
boxf
Definition
geom.h:41
boxf::UR
pointf UR
Definition
geom.h:41
boxf::LL
pointf LL
Definition
geom.h:41
cell
result of partitioning available space, part of maze
Definition
grid.h:33
monchain_t
Definition
partition.c:58
monchain_t::next
int next
Definition
partition.c:60
monchain_t::vnum
int vnum
Definition
partition.c:59
monchain_t::prev
int prev
Definition
partition.c:61
monchain_t::marked
int marked
Definition
partition.c:62
pointf_s
Definition
geom.h:29
pointf_s::x
double x
Definition
geom.h:29
pointf_s::y
double y
Definition
geom.h:29
segment_t
Definition
trap.h:29
segment_t::root0
size_t root0
Definition
trap.h:32
segment_t::v0
pointf v0
Definition
trap.h:30
segment_t::root1
size_t root1
root nodes in Q
Definition
trap.h:32
segment_t::prev
int prev
Definition
trap.h:34
segment_t::next
int next
Definition
trap.h:33
segment_t::v1
pointf v1
Definition
trap.h:30
segment_t::is_inserted
bool is_inserted
Definition
trap.h:31
trap_t
Definition
trap.h:40
trap_t::d1
size_t d1
Definition
trap.h:44
trap_t::rseg
int rseg
Definition
trap.h:41
trap_t::sink
size_t sink
pointer to corresponding in Q
Definition
trap.h:45
trap_t::lo
pointf lo
Definition
trap.h:42
trap_t::d0
size_t d0
Definition
trap.h:44
trap_t::usave
size_t usave
I forgot what this means.
Definition
trap.h:46
trap_t::u1
size_t u1
Definition
trap.h:43
trap_t::hi
pointf hi
Definition
trap.h:42
trap_t::u0
size_t u0
Definition
trap.h:43
trap_t::uside
int uside
I forgot what this means.
Definition
trap.h:47
trap_t::is_valid
bool is_valid
Definition
trap.h:48
trap_t::lseg
int lseg
Definition
trap.h:41
vertexchain_t
Definition
partition.c:106
vertexchain_t::nextfree
int nextfree
Definition
partition.c:110
vertexchain_t::vpos
int vpos[4]
Definition
partition.c:109
vertexchain_t::vnext
int vnext[4]
Definition
partition.c:108
vertexchain_t::pt
pointf pt
Definition
partition.c:107
trap.h
trapezoid elements and utilities for partition.c
is_valid_trap
static bool is_valid_trap(size_t index)
Definition
trap.h:56
construct_trapezoids
traps_t construct_trapezoids(int, segment_t *, int *)
Definition
trapezoid.c:862
equal_to
static bool equal_to(pointf v0, pointf v1)
Definition
trap.h:88
greater_than
static bool greater_than(pointf v0, pointf v1)
Definition
trap.h:92
C_EPS
#define C_EPS
Definition
trap.h:63
fp_equal
static bool fp_equal(double s, double t)
Definition
trap.h:69
ccw
int ccw(Ppoint_t p1, Ppoint_t p2, Ppoint_t p3)
are the given points counter-clockwise, clockwise, or co-linear?
Definition
triang.c:23
lib
ortho
partition.c
Generated by
1.9.8