Blender V4.3
scanfill.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
18#include <limits.h>
19#include <math.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "MEM_guardedalloc.h"
25
26#include "BLI_listbase.h"
27#include "BLI_math_geom.h"
28#include "BLI_math_matrix.h"
29#include "BLI_math_vector.h"
30#include "BLI_memarena.h"
31#include "BLI_utildefines.h"
32
33#include "BLI_scanfill.h" /* own include */
34
35#include "BLI_strict_flags.h" /* Keep last. */
36
37/* local types */
38typedef struct PolyFill {
40 float min_xy[2], max_xy[2];
44
49
50/* Local functions. */
51
52#define SF_EPSILON 0.00003f
53#define SF_EPSILON_SQ (SF_EPSILON * SF_EPSILON)
54
56#define SF_VERT_NEW 0 /* all new verts have this flag set */
57#define SF_VERT_AVAILABLE 1 /* available - in an edge */
58#define SF_VERT_ZERO_LEN 2
59
61/* Optionally set ScanFillEdge f to this to mark original boundary edges.
62 * Only needed if there are internal diagonal edges passed to BLI_scanfill_calc. */
63#define SF_EDGE_NEW 0 /* all new edges have this flag set */
64// #define SF_EDGE_BOUNDARY 1 /* UNUSED */
65#define SF_EDGE_INTERNAL 2 /* edge is created while scan-filling */
66
68#define SF_POLY_NEW 0 /* all polys initialized to this */
69#define SF_POLY_VALID 1 /* has at least 3 verts */
70
71/* **** FUNCTIONS FOR QSORT *************************** */
72
73static int vergscdata(const void *a1, const void *a2)
74{
75 const ScanFillVertLink *x1 = a1, *x2 = a2;
76
77 if (x1->vert->xy[1] < x2->vert->xy[1]) {
78 return 1;
79 }
80 if (x1->vert->xy[1] > x2->vert->xy[1]) {
81 return -1;
82 }
83 if (x1->vert->xy[0] > x2->vert->xy[0]) {
84 return 1;
85 }
86 if (x1->vert->xy[0] < x2->vert->xy[0]) {
87 return -1;
88 }
89
90 return 0;
91}
92
93/* **** FILL ROUTINES *************************** */
94
96{
97 ScanFillVert *sf_v;
98
99 sf_v = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillVert));
100
101 BLI_addtail(&sf_ctx->fillvertbase, sf_v);
102
103 sf_v->tmp.p = NULL;
104 copy_v3_v3(sf_v->co, vec);
105
106 /* just zero out the rest */
107 zero_v2(sf_v->xy);
108 sf_v->keyindex = 0;
109 sf_v->poly_nr = sf_ctx->poly_nr;
110 sf_v->edge_count = 0;
111 sf_v->f = SF_VERT_NEW;
112 sf_v->user_flag = 0;
113
114 return sf_v;
115}
116
118{
119 ScanFillEdge *sf_ed;
120
121 sf_ed = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillEdge));
122 BLI_addtail(&sf_ctx->filledgebase, sf_ed);
123
124 sf_ed->v1 = v1;
125 sf_ed->v2 = v2;
126
127 /* just zero out the rest */
128 sf_ed->poly_nr = sf_ctx->poly_nr;
129 sf_ed->f = SF_EDGE_NEW;
130 sf_ed->user_flag = 0;
131 sf_ed->tmp.c = 0;
132
133 return sf_ed;
134}
135
136static void addfillface(ScanFillContext *sf_ctx,
137 ScanFillVert *v1,
139 ScanFillVert *v3)
140{
141 /* does not make edges */
142 ScanFillFace *sf_tri;
143
144 sf_tri = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillFace));
145 BLI_addtail(&sf_ctx->fillfacebase, sf_tri);
146
147 sf_tri->v1 = v1;
148 sf_tri->v2 = v2;
149 sf_tri->v3 = v3;
150}
151
152static bool boundisect(const PolyFill *pf2, const PolyFill *pf1)
153{
154 /* has pf2 been touched (intersected) by pf1 ? with bounding box */
155 /* test first if polys exist */
156
157 if (pf1->edges == 0 || pf2->edges == 0) {
158 return false;
159 }
160
161 if (pf2->max_xy[0] < pf1->min_xy[0]) {
162 return false;
163 }
164 if (pf2->max_xy[1] < pf1->min_xy[1]) {
165 return false;
166 }
167
168 if (pf2->min_xy[0] > pf1->max_xy[0]) {
169 return false;
170 }
171 if (pf2->min_xy[1] > pf1->max_xy[1]) {
172 return false;
173 }
174
175 return true;
176}
177
178static void fill_target_map_recursive(const PolyFill *__restrict pf_list,
179 const uint pf_len,
180 const uint pf_target,
181 const uint pf_test,
182 uint *__restrict target_map)
183{
184 const PolyFill *pf_a = pf_list + pf_test;
185 for (uint pf_b_index = pf_target + 1; pf_b_index < pf_len; pf_b_index++) {
186 if (target_map[pf_b_index] != pf_b_index) {
187 /* All intersections have already been identified for this polygon. */
188 continue;
189 }
190 BLI_assert(pf_b_index != pf_test);
191 const PolyFill *pf_b = pf_list + pf_b_index;
192 if (boundisect(pf_a, pf_b)) {
193 target_map[pf_b_index] = pf_target;
194 fill_target_map_recursive(pf_list, pf_len, pf_target, pf_b_index, target_map);
195 }
196 }
197}
198
199/* add pf2 to pf1 */
201{
202 ScanFillVert *eve;
203 ScanFillEdge *eed;
204
205 /* replace old poly numbers */
206 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
207 if (eve->poly_nr == pf2->nr) {
208 eve->poly_nr = pf1->nr;
209 }
210 }
211
212 for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
213 if (eed->poly_nr == pf2->nr) {
214 eed->poly_nr = pf1->nr;
215 }
216 }
217
218 /* Join. */
219 pf1->verts += pf2->verts;
220 pf1->edges += pf2->edges;
221
222 if (pf1->max_xy[0] < pf2->max_xy[0]) {
223 pf1->max_xy[0] = pf2->max_xy[0];
224 }
225 if (pf1->max_xy[1] < pf2->max_xy[1]) {
226 pf1->max_xy[1] = pf2->max_xy[1];
227 }
228
229 if (pf1->min_xy[0] > pf2->min_xy[0]) {
230 pf1->min_xy[0] = pf2->min_xy[0];
231 }
232 if (pf1->min_xy[1] > pf2->min_xy[1]) {
233 pf1->min_xy[1] = pf2->min_xy[1];
234 }
235
236 pf1->f = (pf1->f | pf2->f);
237
238 /* Clear the other one. */
239 pf2->verts = pf2->edges = 0;
240}
241
242static bool testedgeside(const float v1[2], const float v2[2], const float v3[2])
243/* is v3 to the right of v1-v2 ? With exception: v3 == v1 || v3 == v2 */
244{
245 float inp;
246
247 inp = (v2[0] - v1[0]) * (v1[1] - v3[1]) + (v1[1] - v2[1]) * (v1[0] - v3[0]);
248
249 if (inp < 0.0f) {
250 return false;
251 }
252 if (inp == 0.0f) {
253 if (v1[0] == v3[0] && v1[1] == v3[1]) {
254 return false;
255 }
256 if (v2[0] == v3[0] && v2[1] == v3[1]) {
257 return false;
258 }
259 }
260 return true;
261}
262
264{
265 /* find first edge to the right of eed, and insert eed before that */
266 ScanFillEdge *ed;
267 float fac, fac1, x, y;
268
269 if (sc->edge_first == NULL) {
270 sc->edge_first = sc->edge_last = eed;
271 eed->prev = eed->next = NULL;
272 return 1;
273 }
274
275 x = eed->v1->xy[0];
276 y = eed->v1->xy[1];
277
278 fac1 = eed->v2->xy[1] - y;
279 if (fac1 == 0.0f) {
280 fac1 = 1.0e10f * (eed->v2->xy[0] - x);
281 }
282 else {
283 fac1 = (x - eed->v2->xy[0]) / fac1;
284 }
285
286 for (ed = sc->edge_first; ed; ed = ed->next) {
287
288 if (ed->v2 == eed->v2) {
289 return false;
290 }
291
292 fac = ed->v2->xy[1] - y;
293 if (fac == 0.0f) {
294 fac = 1.0e10f * (ed->v2->xy[0] - x);
295 }
296 else {
297 fac = (x - ed->v2->xy[0]) / fac;
298 }
299
300 if (fac > fac1) {
301 break;
302 }
303 }
304 if (ed) {
305 BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed, eed);
306 }
307 else {
308 BLI_addtail((ListBase *)&(sc->edge_first), eed);
309 }
310
311 return true;
312}
313
315{
316 /* inserts edge at correct location in ScanFillVertLink list */
317 /* returns sc when edge already exists */
318 ScanFillVertLink *sc, scsearch;
319 ScanFillVert *eve;
320
321 /* which vert is left-top? */
322 if (eed->v1->xy[1] == eed->v2->xy[1]) {
323 if (eed->v1->xy[0] > eed->v2->xy[0]) {
324 eve = eed->v1;
325 eed->v1 = eed->v2;
326 eed->v2 = eve;
327 }
328 }
329 else if (eed->v1->xy[1] < eed->v2->xy[1]) {
330 eve = eed->v1;
331 eed->v1 = eed->v2;
332 eed->v2 = eve;
333 }
334 /* find location in list */
335 scsearch.vert = eed->v1;
336 sc = (ScanFillVertLink *)bsearch(&scsearch, scdata, len, sizeof(ScanFillVertLink), vergscdata);
337
338 if (UNLIKELY(sc == NULL)) {
339 printf("Error in search edge: %p\n", (void *)eed);
340 }
341 else if (addedgetoscanvert(sc, eed) == false) {
342 return sc;
343 }
344
345 return NULL;
346}
347
351static bool boundinsideEV(const ScanFillEdge *eed, const ScanFillVert *eve)
352{
353 float minx, maxx, miny, maxy;
354
355 if (eed->v1->xy[0] < eed->v2->xy[0]) {
356 minx = eed->v1->xy[0];
357 maxx = eed->v2->xy[0];
358 }
359 else {
360 minx = eed->v2->xy[0];
361 maxx = eed->v1->xy[0];
362 }
363 if (eve->xy[0] >= minx && eve->xy[0] <= maxx) {
364 if (eed->v1->xy[1] < eed->v2->xy[1]) {
365 miny = eed->v1->xy[1];
366 maxy = eed->v2->xy[1];
367 }
368 else {
369 miny = eed->v2->xy[1];
370 maxy = eed->v1->xy[1];
371 }
372 if (eve->xy[1] >= miny && eve->xy[1] <= maxy) {
373 return true;
374 }
375 }
376 return false;
377}
378
380{
381 /* only vertices with (->edge_count == 1) are being tested for
382 * being close to an edge, if true insert */
383
384 ScanFillVert *eve;
385 ScanFillEdge *eed, *ed1;
386
387 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
388 if (eve->edge_count == 1) {
389 /* find the edge which has vertex eve,
390 * NOTE: we _know_ this will crash if 'ed1' becomes NULL
391 * but this will never happen. */
392 for (ed1 = sf_ctx->filledgebase.first; !(ed1->v1 == eve || ed1->v2 == eve); ed1 = ed1->next)
393 {
394 /* do nothing */
395 }
396
397 if (ed1->v1 == eve) {
398 ed1->v1 = ed1->v2;
399 ed1->v2 = eve;
400 }
401
402 for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
403 if (eve != eed->v1 && eve != eed->v2 && eve->poly_nr == eed->poly_nr) {
404 if (compare_v2v2(eve->xy, eed->v1->xy, SF_EPSILON)) {
405 ed1->v2 = eed->v1;
406 eed->v1->edge_count++;
407 eve->edge_count = 0;
408 break;
409 }
410 if (compare_v2v2(eve->xy, eed->v2->xy, SF_EPSILON)) {
411 ed1->v2 = eed->v2;
412 eed->v2->edge_count++;
413 eve->edge_count = 0;
414 break;
415 }
416
417 if (boundinsideEV(eed, eve)) {
418 const float dist = dist_squared_to_line_v2(eed->v1->xy, eed->v2->xy, eve->xy);
419 if (dist < SF_EPSILON_SQ) {
420 /* new edge */
421 ed1 = BLI_scanfill_edge_add(sf_ctx, eed->v1, eve);
422
423 // printf("fill: vertex near edge %x\n", eve);
424 ed1->poly_nr = eed->poly_nr;
425 eed->v1 = eve;
426 eve->edge_count = 3;
427 break;
428 }
429 }
430 }
431 }
432 }
433 }
434}
435
436static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *temped, ushort nr)
437{
438 /* Everything is in temp-list, write only poly nr to fill-list. */
439 ScanFillVert *eve, *eve_next;
440 ScanFillEdge *eed, *eed_next;
441
442 BLI_movelisttolist(tempve, &sf_ctx->fillvertbase);
443 BLI_movelisttolist(temped, &sf_ctx->filledgebase);
444
445 for (eve = tempve->first; eve; eve = eve_next) {
446 eve_next = eve->next;
447 if (eve->poly_nr == nr) {
448 BLI_remlink(tempve, eve);
449 BLI_addtail(&sf_ctx->fillvertbase, eve);
450 }
451 }
452
453 for (eed = temped->first; eed; eed = eed_next) {
454 eed_next = eed->next;
455 if (eed->poly_nr == nr) {
456 BLI_remlink(temped, eed);
457 BLI_addtail(&sf_ctx->filledgebase, eed);
458 }
459 }
460}
461
462static uint scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
463{
464 ScanFillVertLink *scdata;
465 ScanFillVertLink *sc = NULL, *sc1;
466 ScanFillVert *eve, *v1, *v2, *v3;
467 ScanFillEdge *eed, *eed_next, *ed1, *ed2, *ed3;
468 uint a, b, verts, maxface, totface;
469 const ushort nr = pf->nr;
470 bool twoconnected = false;
471
472 /* PRINTS */
473#if 0
474 verts = pf->verts;
475 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
476 printf("vert: %x co: %f %f\n", eve, eve->xy[0], eve->xy[1]);
477 }
478
479 for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
480 printf("edge: %x verts: %x %x\n", eed, eed->v1, eed->v2);
481 }
482#endif
483
484 /* STEP 0: remove zero sized edges */
486 for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
487 if (equals_v2v2(eed->v1->xy, eed->v2->xy)) {
488 if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) {
489 eed->v2->f = SF_VERT_ZERO_LEN;
490 eed->v2->tmp.v = eed->v1->tmp.v;
491 }
492 else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) {
493 eed->v1->f = SF_VERT_ZERO_LEN;
494 eed->v1->tmp.v = eed->v2->tmp.v;
495 }
496 else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) {
497 eed->v1->tmp.v = eed->v2->tmp.v;
498 }
499 else {
500 eed->v2->f = SF_VERT_ZERO_LEN;
501 eed->v2->tmp.v = eed->v1;
502 }
503 }
504 }
505 }
506
507 /* STEP 1: make using FillVert and FillEdge lists a sorted
508 * ScanFillVertLink list
509 */
510 sc = scdata = MEM_mallocN(sizeof(*scdata) * pf->verts, "Scanfill1");
511 verts = 0;
512 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
513 if (eve->poly_nr == nr) {
514 if (eve->f != SF_VERT_ZERO_LEN) {
515 verts++;
516 eve->f = SF_VERT_NEW; /* Flag for connect edges later on. */
517 sc->vert = eve;
518 sc->edge_first = sc->edge_last = NULL;
519 /* NOTE: debug print only will work for curve poly-fill, union is in use for mesh. */
520#if 0
521 if (even->tmp.v == NULL) {
522 eve->tmp.u = verts;
523 }
524#endif
525 sc++;
526 }
527 }
528 }
529
530 qsort(scdata, verts, sizeof(ScanFillVertLink), vergscdata);
531
533 for (eed = sf_ctx->filledgebase.first; eed; eed = eed_next) {
534 eed_next = eed->next;
535 BLI_remlink(&sf_ctx->filledgebase, eed);
536 /* This code is for handling zero-length edges that get
537 * collapsed in step 0. It was removed for some time to
538 * fix trunk bug #4544, so if that comes back, this code
539 * may need some work, or there will have to be a better
540 * fix to #4544.
541 *
542 * warning, this can hang on un-ordered edges, see: #33281.
543 * for now disable 'BLI_SCANFILL_CALC_REMOVE_DOUBLES' for ngons.
544 */
545 if (eed->v1->f == SF_VERT_ZERO_LEN) {
546 v1 = eed->v1;
547 while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) &&
548 (eed->v1 != eed->v1->tmp.v))
549 {
550 eed->v1 = eed->v1->tmp.v;
551 }
552 }
553 if (eed->v2->f == SF_VERT_ZERO_LEN) {
554 v2 = eed->v2;
555 while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) &&
556 (eed->v2 != eed->v2->tmp.v))
557 {
558 eed->v2 = eed->v2->tmp.v;
559 }
560 }
561 if (eed->v1 != eed->v2) {
562 addedgetoscanlist(scdata, eed, verts);
563 }
564 }
565 }
566 else {
567 for (eed = sf_ctx->filledgebase.first; eed; eed = eed_next) {
568 eed_next = eed->next;
569 BLI_remlink(&sf_ctx->filledgebase, eed);
570 if (eed->v1 != eed->v2) {
571 addedgetoscanlist(scdata, eed, verts);
572 }
573 }
574 }
575#if 0
576 sc = sf_ctx->_scdata;
577 for (a = 0; a < verts; a++) {
578 printf("\nscvert: %x\n", sc->vert);
579 for (eed = sc->edge_first; eed; eed = eed->next) {
580 printf(" ed %x %x %x\n", eed, eed->v1, eed->v2);
581 }
582 sc++;
583 }
584#endif
585
586 /* STEP 2: FILL LOOP */
587
588 if (pf->f == SF_POLY_NEW) {
589 twoconnected = true;
590 }
591
592 /* (temporal) security: never much more faces than vertices */
593 totface = 0;
595 maxface = 2 * verts; /* 2*verts: based at a filled circle within a triangle */
596 }
597 else {
598 /* when we don't calc any holes, we assume face is a non overlapping loop */
599 maxface = verts - 2;
600 }
601
602 sc = scdata;
603 for (a = 0; a < verts; a++) {
604 // printf("VERTEX %d index %d\n", a, sc->vert->tmp.u);
605 /* Set connect-flags. */
606 for (ed1 = sc->edge_first; ed1; ed1 = eed_next) {
607 eed_next = ed1->next;
608 if (ed1->v1->edge_count == 1 || ed1->v2->edge_count == 1) {
609 BLI_remlink((ListBase *)&(sc->edge_first), ed1);
610 BLI_addtail(&sf_ctx->filledgebase, ed1);
611 if (ed1->v1->edge_count > 1) {
612 ed1->v1->edge_count--;
613 }
614 if (ed1->v2->edge_count > 1) {
615 ed1->v2->edge_count--;
616 }
617 }
618 else {
619 ed1->v2->f = SF_VERT_AVAILABLE;
620 }
621 }
622 while (sc->edge_first) { /* for as long there are edges */
623 ed1 = sc->edge_first;
624 ed2 = ed1->next;
625
626 /* Commented out: the ESC here delivers corrupted memory
627 * (and doesn't work during grab). */
628#if 0
629 if (callLocalInterruptCallBack()){
630 break;
631 }
632#endif
633 if (totface >= maxface) {
634 // printf("Fill error: endless loop. Escaped at vert %d, tot: %d.\n", a, verts);
635 a = verts;
636 break;
637 }
638 if (ed2 == NULL) {
639 sc->edge_first = sc->edge_last = NULL;
640 // printf("just 1 edge to vert\n");
641 BLI_addtail(&sf_ctx->filledgebase, ed1);
642 ed1->v2->f = SF_VERT_NEW;
643 ed1->v1->edge_count--;
644 ed1->v2->edge_count--;
645 }
646 else {
647 /* test rest of vertices */
648 ScanFillVertLink *best_sc = NULL;
649 float angle_best_cos = -1.0f;
650 float miny;
651 bool firsttime = false;
652
653 v1 = ed1->v2;
654 v2 = ed1->v1;
655 v3 = ed2->v2;
656
657 /* this happens with a serial of overlapping edges */
658 if (v1 == v2 || v2 == v3) {
659 break;
660 }
661
662 // printf("test verts %d %d %d\n", v1->tmp.u, v2->tmp.u, v3->tmp.u);
663 miny = min_ff(v1->xy[1], v3->xy[1]);
664 sc1 = sc + 1;
665
666 for (b = a + 1; b < verts; b++, sc1++) {
667 if (sc1->vert->f == SF_VERT_NEW) {
668 if (sc1->vert->xy[1] <= miny) {
669 break;
670 }
671 if (testedgeside(v1->xy, v2->xy, sc1->vert->xy)) {
672 if (testedgeside(v2->xy, v3->xy, sc1->vert->xy)) {
673 if (testedgeside(v3->xy, v1->xy, sc1->vert->xy)) {
674 /* point is in triangle */
675
676 /* Because multiple points can be inside triangle
677 * (concave holes) we continue searching and pick the
678 * one with sharpest corner. */
679 if (best_sc == NULL) {
680 /* even without holes we need to keep checking #35861. */
681 best_sc = sc1;
682 }
683 else {
684 /* Prevent angle calc for the simple cases
685 * only 1 vertex is found. */
686 if (firsttime == false) {
687 angle_best_cos = cos_v2v2v2(v2->xy, v1->xy, best_sc->vert->xy);
688 firsttime = true;
689 }
690
691 const float angle_test_cos = cos_v2v2v2(v2->xy, v1->xy, sc1->vert->xy);
692 if (angle_test_cos > angle_best_cos) {
693 best_sc = sc1;
694 angle_best_cos = angle_test_cos;
695 }
696 }
697 }
698 }
699 }
700 }
701 }
702
703 if (best_sc) {
704 /* make new edge, and start over */
705 // printf("add new edge %d %d and start again\n", v2->tmp.u, best_sc->vert->tmp.u);
706
707 ed3 = BLI_scanfill_edge_add(sf_ctx, v2, best_sc->vert);
708 BLI_remlink(&sf_ctx->filledgebase, ed3);
709 BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed2, ed3);
710 ed3->v2->f = SF_VERT_AVAILABLE;
711 ed3->f = SF_EDGE_INTERNAL;
712 ed3->v1->edge_count++;
713 ed3->v2->edge_count++;
714 }
715 else {
716 /* new triangle */
717 // printf("add face %d %d %d\n", v1->tmp.u, v2->tmp.u, v3->tmp.u);
718 addfillface(sf_ctx, v1, v2, v3);
719 totface++;
720 BLI_remlink((ListBase *)&(sc->edge_first), ed1);
721 BLI_addtail(&sf_ctx->filledgebase, ed1);
722 ed1->v2->f = SF_VERT_NEW;
723 ed1->v1->edge_count--;
724 ed1->v2->edge_count--;
725 /* ed2 can be removed when it's a boundary edge */
726 if (((ed2->f == SF_EDGE_NEW) && twoconnected) /* || (ed2->f == SF_EDGE_BOUNDARY) */) {
727 BLI_remlink((ListBase *)&(sc->edge_first), ed2);
728 BLI_addtail(&sf_ctx->filledgebase, ed2);
729 ed2->v2->f = SF_VERT_NEW;
730 ed2->v1->edge_count--;
731 ed2->v2->edge_count--;
732 }
733
734 /* new edge */
735 ed3 = BLI_scanfill_edge_add(sf_ctx, v1, v3);
736 BLI_remlink(&sf_ctx->filledgebase, ed3);
737 ed3->f = SF_EDGE_INTERNAL;
738 ed3->v1->edge_count++;
739 ed3->v2->edge_count++;
740
741 // printf("add new edge %x %x\n", v1, v3);
742 sc1 = addedgetoscanlist(scdata, ed3, verts);
743
744 if (sc1) { /* ed3 already exists: remove if a boundary */
745 // printf("Edge exists\n");
746 ed3->v1->edge_count--;
747 ed3->v2->edge_count--;
748
749 for (ed3 = sc1->edge_first; ed3; ed3 = ed3->next) {
750 if ((ed3->v1 == v1 && ed3->v2 == v3) || (ed3->v1 == v3 && ed3->v2 == v1)) {
751 if (twoconnected /* || (ed3->f == SF_EDGE_BOUNDARY) */) {
752 BLI_remlink((ListBase *)&(sc1->edge_first), ed3);
753 BLI_addtail(&sf_ctx->filledgebase, ed3);
754 ed3->v1->edge_count--;
755 ed3->v2->edge_count--;
756 }
757 break;
758 }
759 }
760 }
761 }
762 }
763
764 /* test for loose edges */
765 for (ed1 = sc->edge_first; ed1; ed1 = eed_next) {
766 eed_next = ed1->next;
767 if (ed1->v1->edge_count < 2 || ed1->v2->edge_count < 2) {
768 BLI_remlink((ListBase *)&(sc->edge_first), ed1);
769 BLI_addtail(&sf_ctx->filledgebase, ed1);
770 if (ed1->v1->edge_count > 1) {
771 ed1->v1->edge_count--;
772 }
773 if (ed1->v2->edge_count > 1) {
774 ed1->v2->edge_count--;
775 }
776 }
777 }
778 /* done with loose edges */
779 }
780
781 sc++;
782 }
783
784 MEM_freeN(scdata);
785
786 BLI_assert(totface <= maxface);
787
788 return totface;
789}
790
792{
793 memset(sf_ctx, 0, sizeof(*sf_ctx));
794 sf_ctx->poly_nr = SF_POLY_UNSET;
796}
797
799{
800 memset(sf_ctx, 0, sizeof(*sf_ctx));
801 sf_ctx->poly_nr = SF_POLY_UNSET;
802 sf_ctx->arena = arena;
803}
804
806{
807 BLI_memarena_free(sf_ctx->arena);
808 sf_ctx->arena = NULL;
809
813}
814
816{
817 BLI_memarena_clear(arena);
818 BLI_assert(sf_ctx->arena == arena);
819
823}
824
825uint BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3])
826{
827 /*
828 * - fill works with its own lists, so create that first (no faces!)
829 * - for vertices, put in ->tmp.v the old pointer
830 * - struct elements xs en ys are not used here: don't hide stuff in it
831 * - edge flag ->f becomes 2 when it's a new edge
832 * - mode: & 1 is check for crossings, then create edges (TO DO )
833 * - returns number of triangle faces added.
834 */
835 ListBase tempve, temped;
836 ScanFillVert *eve;
837 ScanFillEdge *eed, *eed_next;
838 PolyFill *pflist, *pf;
839 float *min_xy_p, *max_xy_p;
840 uint totfaces = 0; /* total faces added */
841 ushort a, poly = 0;
842 bool ok;
843 float mat_2d[3][3];
844
845 BLI_assert(!nor_proj || len_squared_v3(nor_proj) > FLT_EPSILON);
846
847#ifndef NDEBUG
848 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
849 /* these values used to be set,
850 * however they should always be zero'd so check instead */
851 BLI_assert(eve->f == 0);
852 BLI_assert(sf_ctx->poly_nr || eve->poly_nr == 0);
853 BLI_assert(eve->edge_count == 0);
854 }
855#endif
856
857 /* first test vertices if they are in edges */
858 /* including resetting of flags */
859 for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
861 eed->v1->f = SF_VERT_AVAILABLE;
862 eed->v2->f = SF_VERT_AVAILABLE;
863 }
864
865 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
866 if (eve->f == SF_VERT_AVAILABLE) {
867 break;
868 }
869 }
870
871 if (UNLIKELY(eve == NULL)) {
872 return 0;
873 }
874
875 float n[3];
876
877 if (nor_proj) {
878 copy_v3_v3(n, nor_proj);
879 }
880 else {
881 /* define projection: with 'best' normal */
882 /* Newell's Method */
883 /* Similar code used elsewhere, but this checks for double ups
884 * which historically this function supports so better not change */
885
886 /* WARNING: this only gives stable direction with single polygons,
887 * ideally we'd calculate connectivity and each polys normal, see #41047 */
888 const float *v_prev;
889
890 zero_v3(n);
891 eve = sf_ctx->fillvertbase.last;
892 v_prev = eve->co;
893
894 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
895 if (LIKELY(!compare_v3v3(v_prev, eve->co, SF_EPSILON))) {
896 add_newell_cross_v3_v3v3(n, v_prev, eve->co);
897 v_prev = eve->co;
898 }
899 }
900 }
901
902 if (UNLIKELY(normalize_v3(n) == 0.0f)) {
903 return 0;
904 }
905
907
908 /* STEP 1: COUNT POLYS */
909 if (sf_ctx->poly_nr != SF_POLY_UNSET) {
910 poly = (ushort)(sf_ctx->poly_nr + 1);
911 sf_ctx->poly_nr = SF_POLY_UNSET;
912 }
913
914 if (flag & BLI_SCANFILL_CALC_POLYS && (poly == 0)) {
915 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
916 mul_v2_m3v3(eve->xy, mat_2d, eve->co);
917
918 /* get first vertex with no poly number */
919 if (eve->poly_nr == SF_POLY_UNSET) {
920 uint toggle = 0;
921 /* now a sort of select connected */
922 ok = true;
923 eve->poly_nr = poly;
924
925 while (ok) {
926
927 ok = false;
928
929 toggle++;
930 for (eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last; eed;
931 eed = (toggle & 1) ? eed->next : eed->prev)
932 {
933 if (eed->v1->poly_nr == SF_POLY_UNSET && eed->v2->poly_nr == poly) {
934 eed->v1->poly_nr = poly;
935 eed->poly_nr = poly;
936 ok = true;
937 }
938 else if (eed->v2->poly_nr == SF_POLY_UNSET && eed->v1->poly_nr == poly) {
939 eed->v2->poly_nr = poly;
940 eed->poly_nr = poly;
941 ok = true;
942 }
943 else if (eed->poly_nr == SF_POLY_UNSET) {
944 if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) {
945 eed->poly_nr = poly;
946 ok = true;
947 }
948 }
949 }
950 }
951
952 poly++;
953 }
954 }
955 // printf("amount of poly's: %d\n", poly);
956 }
957 else if (poly) {
958 /* we pre-calculated poly_nr */
959 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
960 mul_v2_m3v3(eve->xy, mat_2d, eve->co);
961 }
962 }
963 else {
964 poly = 1;
965
966 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
967 mul_v2_m3v3(eve->xy, mat_2d, eve->co);
968 eve->poly_nr = 0;
969 }
970
971 for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
972 eed->poly_nr = 0;
973 }
974 }
975
976 /* STEP 2: remove loose edges and strings of edges */
978 uint toggle = 0;
979 for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
980 if (eed->v1->edge_count++ > 250) {
981 break;
982 }
983 if (eed->v2->edge_count++ > 250) {
984 break;
985 }
986 }
987 if (eed) {
988 /* otherwise it's impossible to be sure you can clear vertices */
989#ifndef NDEBUG
990 printf("No vertices with 250 edges allowed!\n");
991#endif
992 return 0;
993 }
994
995 /* does it only for vertices with (->edge_count == 1) */
996 testvertexnearedge(sf_ctx);
997
998 ok = true;
999 while (ok) {
1000 ok = false;
1001
1002 toggle++;
1003 for (eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last; eed;
1004 eed = eed_next)
1005 {
1006 eed_next = (toggle & 1) ? eed->next : eed->prev;
1007 if (eed->v1->edge_count == 1) {
1008 eed->v2->edge_count--;
1009 BLI_remlink(&sf_ctx->fillvertbase, eed->v1);
1010 BLI_remlink(&sf_ctx->filledgebase, eed);
1011 ok = true;
1012 }
1013 else if (eed->v2->edge_count == 1) {
1014 eed->v1->edge_count--;
1015 BLI_remlink(&sf_ctx->fillvertbase, eed->v2);
1016 BLI_remlink(&sf_ctx->filledgebase, eed);
1017 ok = true;
1018 }
1019 }
1020 }
1021 if (BLI_listbase_is_empty(&sf_ctx->filledgebase)) {
1022 // printf("All edges removed\n");
1023 return 0;
1024 }
1025 }
1026 else {
1027 /* skip checks for loose edges */
1028 for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
1029 eed->v1->edge_count++;
1030 eed->v2->edge_count++;
1031 }
1032#ifndef NDEBUG
1033 /* ensure we're right! */
1034 for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
1035 BLI_assert(eed->v1->edge_count != 1);
1036 BLI_assert(eed->v2->edge_count != 1);
1037 }
1038#endif
1039 }
1040
1041 /* CURRENT STATUS:
1042 * - `eve->f`: 1 = available in edges.
1043 * - `eve->poly_nr`: poly-number.
1044 * - `eve->edge_count`: amount of edges connected to vertex.
1045 * - `eve->tmp.v`: store! original vertex number.
1046 *
1047 * - `eed->f`: 1 = boundary edge (optionally set by caller).
1048 * - `eed->poly_nr`: poly number.
1049 */
1050
1051 /* STEP 3: MAKE POLYFILL STRUCT */
1052 pflist = MEM_mallocN(sizeof(*pflist) * (size_t)poly, "edgefill");
1053 pf = pflist;
1054 for (a = 0; a < poly; a++) {
1055 pf->edges = pf->verts = 0;
1056 pf->min_xy[0] = pf->min_xy[1] = 1.0e20f;
1057 pf->max_xy[0] = pf->max_xy[1] = -1.0e20f;
1058 pf->f = SF_POLY_NEW;
1059 pf->nr = a;
1060 pf++;
1061 }
1062 for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
1063 pflist[eed->poly_nr].edges++;
1064 }
1065
1066 for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
1067 pflist[eve->poly_nr].verts++;
1068 min_xy_p = pflist[eve->poly_nr].min_xy;
1069 max_xy_p = pflist[eve->poly_nr].max_xy;
1070
1071 min_xy_p[0] = (min_xy_p[0]) < (eve->xy[0]) ? (min_xy_p[0]) : (eve->xy[0]);
1072 min_xy_p[1] = (min_xy_p[1]) < (eve->xy[1]) ? (min_xy_p[1]) : (eve->xy[1]);
1073 max_xy_p[0] = (max_xy_p[0]) > (eve->xy[0]) ? (max_xy_p[0]) : (eve->xy[0]);
1074 max_xy_p[1] = (max_xy_p[1]) > (eve->xy[1]) ? (max_xy_p[1]) : (eve->xy[1]);
1075 if (eve->edge_count > 2) {
1076 pflist[eve->poly_nr].f = SF_POLY_VALID;
1077 }
1078 }
1079
1080 /* STEP 4: FIND HOLES OR BOUNDS, JOIN THEM
1081 * ( bounds just to divide it in pieces for optimization,
1082 * the edgefill itself has good auto-hole detection). */
1083
1084 if ((flag & BLI_SCANFILL_CALC_HOLES) && (poly > 1)) {
1085#if 0
1086 pf = pflist;
1087 for (a = 0; a < poly; a++) {
1088 printf("poly:%d edges:%d verts:%d flag: %d\n", a, pf->edges, pf->verts, pf->f);
1089 PRINT2(f, f, pf->min[0], pf->min[1]);
1090 pf++;
1091 }
1092#endif
1093
1094 uint *target_map = MEM_mallocN(sizeof(*target_map) * (size_t)poly, "polycache");
1095 range_vn_u(target_map, poly, 0);
1096
1097 for (a = 0; a < poly; a++) {
1098 if (target_map[a] != a) {
1099 continue;
1100 }
1101 fill_target_map_recursive(pflist, poly, a, a, target_map);
1102 }
1103
1104 /* Join polygons. */
1105 for (a = 0; a < poly; a++) {
1106 if (target_map[a] != a) {
1107 PolyFill *pf_src = pflist + a;
1108 PolyFill *pf_dst = pflist + target_map[a];
1109 mergepolysSimp(sf_ctx, pf_dst, pf_src);
1110 }
1111 }
1112
1113 MEM_freeN(target_map);
1114 }
1115
1116#if 0
1117 printf("after merge\n");
1118 pf = pflist;
1119 for (a = 0; a < poly; a++) {
1120 printf("poly:%d edges:%d verts:%d flag: %d\n", a, pf->edges, pf->verts, pf->f);
1121 pf++;
1122 }
1123#endif
1124
1125 /* STEP 5: MAKE TRIANGLES */
1126
1127 tempve.first = sf_ctx->fillvertbase.first;
1128 tempve.last = sf_ctx->fillvertbase.last;
1129 temped.first = sf_ctx->filledgebase.first;
1130 temped.last = sf_ctx->filledgebase.last;
1133
1134 pf = pflist;
1135 for (a = 0; a < poly; a++) {
1136 if (pf->edges > 1) {
1137 splitlist(sf_ctx, &tempve, &temped, pf->nr);
1138 totfaces += scanfill(sf_ctx, pf, flag);
1139 }
1140 pf++;
1141 }
1142 BLI_movelisttolist(&sf_ctx->fillvertbase, &tempve);
1143 BLI_movelisttolist(&sf_ctx->filledgebase, &temped);
1144
1145 /* FREE */
1146
1147 MEM_freeN(pflist);
1148
1149 return totfaces;
1150}
1151
1153{
1154 return BLI_scanfill_calc_ex(sf_ctx, flag, NULL);
1155}
#define BLI_assert(a)
Definition BLI_assert.h:50
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:370
MINLINE float min_ff(float a, float b)
void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
float dist_squared_to_line_v2(const float p[2], const float l1[2], const float l2[2])
Definition math_geom.cc:276
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
float cos_v2v2v2(const float p1[2], const float p2[2], const float p3[2]) ATTR_WARN_UNUSED_RESULT
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE bool compare_v2v2(const float v1[2], const float v2[2], float limit) ATTR_WARN_UNUSED_RESULT
MINLINE bool compare_v3v3(const float v1[3], const float v2[3], float limit) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v2(float r[2])
void range_vn_u(unsigned int *array_tar, int size, unsigned int start)
MINLINE void zero_v3(float r[3])
MINLINE float normalize_v3(float n[3])
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
@ BLI_SCANFILL_CALC_LOOSE
@ BLI_SCANFILL_CALC_POLYS
@ BLI_SCANFILL_CALC_HOLES
@ BLI_SCANFILL_CALC_REMOVE_DOUBLES
#define SF_POLY_UNSET
#define BLI_SCANFILL_ARENA_SIZE
unsigned char uchar
unsigned short ushort
unsigned int uint
#define UNLIKELY(x)
#define LIKELY(x)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
local_group_size(16, 16) .push_constant(Type b
#define printf
#define NULL
int len
static float verts[][3]
#define pf2(_x, _i)
Prefetch 128.
Definition gim_memory.h:50
#define pf(_x, _i)
Prefetch 64.
Definition gim_memory.h:48
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2, ScanFillVert *v3)
Definition scanfill.c:136
static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *temped, ushort nr)
Definition scanfill.c:436
#define SF_POLY_VALID
Definition scanfill.c:69
static bool testedgeside(const float v1[2], const float v2[2], const float v3[2])
Definition scanfill.c:242
void BLI_scanfill_begin(ScanFillContext *sf_ctx)
Definition scanfill.c:791
#define SF_VERT_NEW
Definition scanfill.c:56
struct ScanFillVertLink ScanFillVertLink
void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, MemArena *arena)
Definition scanfill.c:815
#define SF_EPSILON
Definition scanfill.c:52
void BLI_scanfill_end(ScanFillContext *sf_ctx)
Definition scanfill.c:805
#define SF_EDGE_NEW
Definition scanfill.c:63
struct PolyFill PolyFill
static void mergepolysSimp(ScanFillContext *sf_ctx, PolyFill *pf1, PolyFill *pf2)
Definition scanfill.c:200
static bool boundinsideEV(const ScanFillEdge *eed, const ScanFillVert *eve)
Definition scanfill.c:351
#define SF_VERT_ZERO_LEN
Definition scanfill.c:58
static int vergscdata(const void *a1, const void *a2)
Definition scanfill.c:73
#define SF_EDGE_INTERNAL
Definition scanfill.c:65
uint BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3])
Definition scanfill.c:825
void BLI_scanfill_begin_arena(ScanFillContext *sf_ctx, MemArena *arena)
Definition scanfill.c:798
static void fill_target_map_recursive(const PolyFill *__restrict pf_list, const uint pf_len, const uint pf_target, const uint pf_test, uint *__restrict target_map)
Definition scanfill.c:178
#define SF_EPSILON_SQ
Definition scanfill.c:53
static uint scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
Definition scanfill.c:462
static bool boundisect(const PolyFill *pf2, const PolyFill *pf1)
Definition scanfill.c:152
ScanFillVert * BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3])
Definition scanfill.c:95
static ScanFillVertLink * addedgetoscanlist(ScanFillVertLink *scdata, ScanFillEdge *eed, uint len)
Definition scanfill.c:314
#define SF_POLY_NEW
Definition scanfill.c:68
static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
Definition scanfill.c:263
ScanFillEdge * BLI_scanfill_edge_add(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2)
Definition scanfill.c:117
uint BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag)
Definition scanfill.c:1152
#define SF_VERT_AVAILABLE
Definition scanfill.c:57
static void testvertexnearedge(ScanFillContext *sf_ctx)
Definition scanfill.c:379
void * last
void * first
uchar f
Definition scanfill.c:42
ushort nr
Definition scanfill.c:41
uint verts
Definition scanfill.c:39
uint edges
Definition scanfill.c:39
float max_xy[2]
Definition scanfill.c:40
float min_xy[2]
Definition scanfill.c:40
struct MemArena * arena
ListBase fillvertbase
ListBase filledgebase
unsigned short poly_nr
ListBase fillfacebase
struct ScanFillEdge * prev
unsigned short poly_nr
union ScanFillEdge::@115 tmp
struct ScanFillVert * v1
struct ScanFillVert * v2
unsigned char c
unsigned int f
struct ScanFillEdge * next
unsigned int user_flag
struct ScanFillVert * v2
struct ScanFillVert * v3
struct ScanFillVert * v1
float xy[2]
unsigned short poly_nr
unsigned int f
unsigned char edge_count
struct ScanFillVert * next
float co[3]
struct ScanFillVert * v
unsigned int user_flag
unsigned int u
union ScanFillVert::@114 tmp
unsigned int keyindex
uint8_t flag
Definition wm_window.cc:138