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