Blender V5.0
polyfill_2d.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
33
34#include "BLI_utildefines.h"
35
36#include <cstdlib>
37
38#include "MEM_guardedalloc.h"
39
40#include "BLI_alloca.h"
41#include "BLI_math_geom.h"
42#include "BLI_math_vector.h"
43#include "BLI_memarena.h"
44
45#include "BLI_polyfill_2d.h" /* own include */
46
47#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
48
49/* avoid fan-fill topology */
50#define USE_CLIP_EVEN
51#define USE_CONVEX_SKIP
52/* sweep back-and-forth about convex ears (avoids lop-sided fans) */
53#define USE_CLIP_SWEEP
54// #define USE_CONVEX_SKIP_TEST
55
56#ifdef USE_CONVEX_SKIP
57# define USE_KDTREE
58#endif
59
60/* disable in production, it can fail on near zero area ngons */
61// #define USE_STRICT_ASSERT
62
63// #define DEBUG_TIME
64#ifdef DEBUG_TIME
65# include "BLI_time_utildefines.h"
66#endif
67
68namespace {
69
70using eSign = int8_t;
71
72#ifdef USE_KDTREE
91
92using axis_t = bool;
93
94/* use for sorting */
95struct KDTreeNode2D_head {
96 uint32_t neg, pos;
97 uint32_t index;
98};
99
100struct KDTreeNode2D {
101 uint32_t neg, pos;
102 uint32_t index;
103 axis_t axis; /* range is only (0-1) */
104 uint16_t flag;
105 uint32_t parent;
106};
107
108struct KDTree2D {
109 KDTreeNode2D *nodes;
110 const float (*coords)[2];
111 uint32_t root;
112 uint32_t node_num;
113 uint32_t *nodes_map; /* index -> node lookup */
114};
115
116struct KDRange2D {
117 float min, max;
118};
119#endif /* USE_KDTREE */
120
121enum {
122 CONCAVE = -1,
123 TANGENTIAL = 0,
124 CONVEX = 1,
125};
126
128struct PolyIndex {
129 PolyIndex *next, *prev;
130 uint32_t index;
131 eSign sign;
132};
133
134struct PolyFill {
135 PolyIndex *indices; /* vertex aligned */
136
137 const float (*coords)[2];
138 uint32_t coords_num;
139#ifdef USE_CONVEX_SKIP
140 uint32_t coords_num_concave;
141#endif
142
143 /* A polygon with n vertices has a triangulation of n-2 triangles. */
144 uint32_t (*tris)[3];
145 uint32_t tris_num;
146
147#ifdef USE_KDTREE
148 KDTree2D kdtree;
149#endif
150};
151
152} // namespace
153
154/* Based on LIBGDX 2013-11-28, APACHE 2.0 licensed. */
155
156static void pf_coord_sign_calc(const PolyFill *pf, PolyIndex *pi);
157
158static PolyIndex *pf_ear_tip_find(PolyFill *pf
159#ifdef USE_CLIP_EVEN
160 ,
161 PolyIndex *pi_ear_init
162#endif
163#ifdef USE_CLIP_SWEEP
164 ,
165 bool reverse
166#endif
167);
168
169static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip, const eSign sign_accept);
170static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip);
171
173{
174 if (a > 0.0f) {
175 return CONVEX;
176 }
177 if (UNLIKELY(a == 0.0f)) {
178 return TANGENTIAL;
179 }
180 return CONCAVE;
181}
182
189BLI_INLINE float area_tri_signed_v2_alt_2x(const float v1[2], const float v2[2], const float v3[2])
190{
191 float d2[2], d3[2];
192 sub_v2_v2v2(d2, v2, v1);
193 sub_v2_v2v2(d3, v3, v1);
194 return (d2[0] * d3[1]) - (d3[0] * d2[1]);
195}
196
197static eSign span_tri_v2_sign(const float v1[2], const float v2[2], const float v3[2])
198{
200}
201
202#ifdef USE_KDTREE
203# define KDNODE_UNSET (uint32_t(-1))
204
205enum {
207};
208
209static void kdtree2d_new(KDTree2D *tree, uint32_t tot, const float (*coords)[2])
210{
211 /* set by caller */
212 // tree->nodes = nodes;
213 tree->coords = coords;
214 tree->root = KDNODE_UNSET;
215 tree->node_num = tot;
216}
217
221static void kdtree2d_init(KDTree2D *tree, const uint32_t coords_num, const PolyIndex *indices)
222{
223 KDTreeNode2D *node;
224 uint32_t i;
225
226 for (i = 0, node = tree->nodes; i < coords_num; i++) {
227 if (indices[i].sign != CONVEX) {
228 node->neg = node->pos = KDNODE_UNSET;
229 node->index = indices[i].index;
230 node->axis = 0;
231 node->flag = 0;
232 node++;
233 }
234 }
235
236 BLI_assert(tree->node_num == uint32_t(node - tree->nodes));
237}
238
239static uint32_t kdtree2d_balance_recursive(KDTreeNode2D *nodes,
240 uint32_t node_num,
241 axis_t axis,
242 const float (*coords)[2],
243 const uint32_t ofs)
244{
245 KDTreeNode2D *node;
246 uint32_t neg, pos, median, i, j;
247
248 if (node_num <= 0) {
249 return KDNODE_UNSET;
250 }
251 if (node_num == 1) {
252 return 0 + ofs;
253 }
254
255 /* Quick-sort style sorting around median. */
256 neg = 0;
257 pos = node_num - 1;
258 median = node_num / 2;
259
260 while (pos > neg) {
261 const float co = coords[nodes[pos].index][axis];
262 i = neg - 1;
263 j = pos;
264
265 while (true) {
266 while (coords[nodes[++i].index][axis] < co) { /* pass */
267 }
268 while (coords[nodes[--j].index][axis] > co && j > neg) { /* pass */
269 }
270
271 if (i >= j) {
272 break;
273 }
274 SWAP(KDTreeNode2D_head, *(KDTreeNode2D_head *)&nodes[i], *(KDTreeNode2D_head *)&nodes[j]);
275 }
276
277 SWAP(KDTreeNode2D_head, *(KDTreeNode2D_head *)&nodes[i], *(KDTreeNode2D_head *)&nodes[pos]);
278 if (i >= median) {
279 pos = i - 1;
280 }
281 if (i <= median) {
282 neg = i + 1;
283 }
284 }
285
286 /* Set node and sort sub-nodes. */
287 node = &nodes[median];
288 node->axis = axis;
289 axis = !axis;
290 node->neg = kdtree2d_balance_recursive(nodes, median, axis, coords, ofs);
291 node->pos = kdtree2d_balance_recursive(
292 &nodes[median + 1], (node_num - (median + 1)), axis, coords, (median + 1) + ofs);
293
294 return median + ofs;
295}
296
297static void kdtree2d_balance(KDTree2D *tree)
298{
299 tree->root = kdtree2d_balance_recursive(tree->nodes, tree->node_num, 0, tree->coords, 0);
300}
301
302static void kdtree2d_init_mapping(KDTree2D *tree)
303{
304 uint32_t i;
305 KDTreeNode2D *node;
306
307 for (i = 0, node = tree->nodes; i < tree->node_num; i++, node++) {
308 if (node->neg != KDNODE_UNSET) {
309 tree->nodes[node->neg].parent = i;
310 }
311 if (node->pos != KDNODE_UNSET) {
312 tree->nodes[node->pos].parent = i;
313 }
314
315 /* build map */
316 BLI_assert(tree->nodes_map[node->index] == KDNODE_UNSET);
317 tree->nodes_map[node->index] = i;
318 }
319
320 tree->nodes[tree->root].parent = KDNODE_UNSET;
321}
322
323static void kdtree2d_node_remove(KDTree2D *tree, uint32_t index)
324{
325 uint32_t node_index = tree->nodes_map[index];
326 KDTreeNode2D *node;
327
328 if (node_index == KDNODE_UNSET) {
329 return;
330 }
331
332 tree->nodes_map[index] = KDNODE_UNSET;
333
334 node = &tree->nodes[node_index];
335 tree->node_num -= 1;
336
337 BLI_assert((node->flag & KDNODE_FLAG_REMOVED) == 0);
338 node->flag |= KDNODE_FLAG_REMOVED;
339
340 while ((node->neg == KDNODE_UNSET) && (node->pos == KDNODE_UNSET) &&
341 (node->parent != KDNODE_UNSET))
342 {
343 KDTreeNode2D *node_parent = &tree->nodes[node->parent];
344
345 BLI_assert(uint32_t(node - tree->nodes) == node_index);
346 if (node_parent->neg == node_index) {
347 node_parent->neg = KDNODE_UNSET;
348 }
349 else {
350 BLI_assert(node_parent->pos == node_index);
351 node_parent->pos = KDNODE_UNSET;
352 }
353
354 if (node_parent->flag & KDNODE_FLAG_REMOVED) {
355 node_index = node->parent;
356 node = node_parent;
357 }
358 else {
359 break;
360 }
361 }
362}
363
364static bool kdtree2d_isect_tri_recursive(const KDTree2D *tree,
365 const uint32_t tri_index[3],
366 const float *tri_coords[3],
367 const float tri_center[2],
368 const KDRange2D bounds[2],
369 const KDTreeNode2D *node)
370{
371 const float *co = tree->coords[node->index];
372
373 /* bounds then triangle intersect */
374 if ((node->flag & KDNODE_FLAG_REMOVED) == 0) {
375 /* bounding box test first */
376 if ((co[0] >= bounds[0].min) && (co[0] <= bounds[0].max) && (co[1] >= bounds[1].min) &&
377 (co[1] <= bounds[1].max))
378 {
379 if ((span_tri_v2_sign(tri_coords[0], tri_coords[1], co) != CONCAVE) &&
380 (span_tri_v2_sign(tri_coords[1], tri_coords[2], co) != CONCAVE) &&
381 (span_tri_v2_sign(tri_coords[2], tri_coords[0], co) != CONCAVE))
382 {
383 if (!ELEM(node->index, tri_index[0], tri_index[1], tri_index[2])) {
384 return true;
385 }
386 }
387 }
388 }
389
390# define KDTREE2D_ISECT_TRI_RECURSE_NEG \
391 (((node->neg != KDNODE_UNSET) && (co[node->axis] >= bounds[node->axis].min)) && \
392 kdtree2d_isect_tri_recursive( \
393 tree, tri_index, tri_coords, tri_center, bounds, &tree->nodes[node->neg]))
394# define KDTREE2D_ISECT_TRI_RECURSE_POS \
395 (((node->pos != KDNODE_UNSET) && (co[node->axis] <= bounds[node->axis].max)) && \
396 kdtree2d_isect_tri_recursive( \
397 tree, tri_index, tri_coords, tri_center, bounds, &tree->nodes[node->pos]))
398
399 if (tri_center[node->axis] > co[node->axis]) {
401 return true;
402 }
404 return true;
405 }
406 }
407 else {
409 return true;
410 }
412 return true;
413 }
414 }
415
416# undef KDTREE2D_ISECT_TRI_RECURSE_NEG
417# undef KDTREE2D_ISECT_TRI_RECURSE_POS
418
419 BLI_assert(node->index != KDNODE_UNSET);
420
421 return false;
422}
423
424static bool kdtree2d_isect_tri(KDTree2D *tree, const uint32_t ind[3])
425{
426 const float *vs[3];
427 uint32_t i;
428 KDRange2D bounds[2] = {
429 {FLT_MAX, -FLT_MAX},
430 {FLT_MAX, -FLT_MAX},
431 };
432 float tri_center[2] = {0.0f, 0.0f};
433
434 for (i = 0; i < 3; i++) {
435 vs[i] = tree->coords[ind[i]];
436
437 add_v2_v2(tri_center, vs[i]);
438
439 CLAMP_MAX(bounds[0].min, vs[i][0]);
440 CLAMP_MIN(bounds[0].max, vs[i][0]);
441 CLAMP_MAX(bounds[1].min, vs[i][1]);
442 CLAMP_MIN(bounds[1].max, vs[i][1]);
443 }
444
445 mul_v2_fl(tri_center, 1.0f / 3.0f);
446
447 return kdtree2d_isect_tri_recursive(tree, ind, vs, tri_center, bounds, &tree->nodes[tree->root]);
448}
449
450#endif /* USE_KDTREE */
451
452static uint32_t *pf_tri_add(PolyFill *pf)
453{
454 return pf->tris[pf->tris_num++];
455}
456
457static void pf_coord_remove(PolyFill *pf, PolyIndex *pi)
458{
459#ifdef USE_KDTREE
460 /* avoid double lookups, since convex coords are ignored when testing intersections */
461 if (pf->kdtree.node_num) {
462 kdtree2d_node_remove(&pf->kdtree, pi->index);
463 }
464#endif /* USE_KDTREE */
465
466 pi->next->prev = pi->prev;
467 pi->prev->next = pi->next;
468
469 if (UNLIKELY(pf->indices == pi)) {
470 pf->indices = pi->next;
471 }
472#ifndef NDEBUG
473 pi->index = uint32_t(-1);
474 pi->next = pi->prev = nullptr;
475#endif /* !NDEBUG */
476
477 pf->coords_num -= 1;
478}
479
480static void pf_triangulate(PolyFill *pf)
481{
482 /* localize */
483 PolyIndex *pi_ear;
484
485#ifdef USE_CLIP_EVEN
486 PolyIndex *pi_ear_init = pf->indices;
487#endif
488#ifdef USE_CLIP_SWEEP
489 bool reverse = false;
490#endif
491
492 while (pf->coords_num > 3) {
493 PolyIndex *pi_prev, *pi_next;
494 eSign sign_orig_prev, sign_orig_next;
495
496 pi_ear = pf_ear_tip_find(pf
497#ifdef USE_CLIP_EVEN
498 ,
499 pi_ear_init
500#endif
501#ifdef USE_CLIP_SWEEP
502 ,
503 reverse
504#endif
505 );
506
507#ifdef USE_CONVEX_SKIP
508 if (pi_ear->sign != CONVEX) {
509 pf->coords_num_concave -= 1;
510 }
511#endif
512
513 pi_prev = pi_ear->prev;
514 pi_next = pi_ear->next;
515
516 pf_ear_tip_cut(pf, pi_ear);
517
518 /* The type of the two vertices adjacent to the clipped vertex may have changed. */
519 sign_orig_prev = pi_prev->sign;
520 sign_orig_next = pi_next->sign;
521
522 /* check if any verts became convex the (else if)
523 * case is highly unlikely but may happen with degenerate polygons */
524 if (sign_orig_prev != CONVEX) {
525 pf_coord_sign_calc(pf, pi_prev);
526#ifdef USE_CONVEX_SKIP
527 if (pi_prev->sign == CONVEX) {
528 pf->coords_num_concave -= 1;
529# ifdef USE_KDTREE
530 kdtree2d_node_remove(&pf->kdtree, pi_prev->index);
531# endif
532 }
533#endif
534 }
535 if (sign_orig_next != CONVEX) {
536 pf_coord_sign_calc(pf, pi_next);
537#ifdef USE_CONVEX_SKIP
538 if (pi_next->sign == CONVEX) {
539 pf->coords_num_concave -= 1;
540# ifdef USE_KDTREE
541 kdtree2d_node_remove(&pf->kdtree, pi_next->index);
542# endif
543 }
544#endif
545 }
546
547#ifdef USE_CLIP_EVEN
548# ifdef USE_CLIP_SWEEP
549 pi_ear_init = reverse ? pi_prev->prev : pi_next->next;
550# else
551 pi_ear_init = pi_next->next;
552# endif
553#endif
554
555#ifdef USE_CLIP_EVEN
556# ifdef USE_CLIP_SWEEP
557 if (pi_ear_init->sign != CONVEX) {
558 /* take the extra step since this ear isn't a good candidate */
559 pi_ear_init = reverse ? pi_ear_init->prev : pi_ear_init->next;
560 reverse = !reverse;
561 }
562# endif
563#else
564# ifdef USE_CLIP_SWEEP
565 if ((reverse ? pi_prev->prev : pi_next->next)->sign != CONVEX) {
566 reverse = !reverse;
567 }
568# endif
569#endif
570 }
571
572 if (pf->coords_num == 3) {
573 uint32_t *tri = pf_tri_add(pf);
574 pi_ear = pf->indices;
575 tri[0] = pi_ear->index;
576 pi_ear = pi_ear->next;
577 tri[1] = pi_ear->index;
578 pi_ear = pi_ear->next;
579 tri[2] = pi_ear->index;
580 }
581}
582
586static void pf_coord_sign_calc(const PolyFill *pf, PolyIndex *pi)
587{
588 /* localize */
589 const float (*coords)[2] = pf->coords;
590
591 pi->sign = span_tri_v2_sign(coords[pi->prev->index], coords[pi->index], coords[pi->next->index]);
592}
593
594static PolyIndex *pf_ear_tip_find(PolyFill *pf
595#ifdef USE_CLIP_EVEN
596 ,
597 PolyIndex *pi_ear_init
598#endif
599#ifdef USE_CLIP_SWEEP
600 ,
601 bool reverse
602#endif
603)
604{
605 /* localize */
606 const uint32_t coords_num = pf->coords_num;
607 PolyIndex *pi_ear;
608
609 uint32_t i;
610
611 /* Use two passes when looking for an ear.
612 *
613 * - The first pass only picks *good* (concave) choices.
614 * For polygons which aren't degenerate this works well
615 * since it avoids creating any zero area faces.
616 *
617 * - The second pass is only met if no concave choices are possible,
618 * so the cost of a second pass is only incurred for degenerate polygons.
619 * In this case accept zero area faces as better alternatives aren't available.
620 *
621 * See: #103913 for reference.
622 *
623 * NOTE: these passes draw a distinction between zero area faces and concave
624 * which is susceptible minor differences in float precision
625 * (since #TANGENTIAL compares with 0.0f).
626 *
627 * While it's possible to compute an error threshold and run a pass that picks
628 * ears which are more likely not to appear as zero area from a users perspective,
629 * this API prioritizes performance (for real-time updates).
630 * Higher quality tessellation can always be achieved using #BLI_polyfill_beautify.
631 */
632 for (eSign sign_accept = CONVEX; sign_accept >= TANGENTIAL; sign_accept--) {
633#ifdef USE_CLIP_EVEN
634 pi_ear = pi_ear_init;
635#else
636 pi_ear = pf->indices;
637#endif
638 i = coords_num;
639 while (i--) {
640 if (pf_ear_tip_check(pf, pi_ear, sign_accept)) {
641 return pi_ear;
642 }
643#ifdef USE_CLIP_SWEEP
644 pi_ear = reverse ? pi_ear->prev : pi_ear->next;
645#else
646 pi_ear = pi_ear->next;
647#endif
648 }
649 }
650
651 /* Desperate mode: if no vertex is an ear tip,
652 * we are dealing with a degenerate polygon (e.g. nearly collinear).
653 * Note that the input was not necessarily degenerate,
654 * but we could have made it so by clipping some valid ears.
655 *
656 * Idea taken from Martin Held, "FIST: Fast industrial-strength triangulation of polygons",
657 * Algorithmica (1998),
658 * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.115.291
659 *
660 * Return a convex or tangential vertex if one exists.
661 */
662
663#ifdef USE_CLIP_EVEN
664 pi_ear = pi_ear_init;
665#else
666 pi_ear = pf->indices;
667#endif
668
669 i = coords_num;
670 while (i--) {
671 if (pi_ear->sign != CONCAVE) {
672 return pi_ear;
673 }
674 pi_ear = pi_ear->next;
675 }
676
677 /* If all vertices are concave, just return the last one. */
678 return pi_ear;
679}
680
681static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip, const eSign sign_accept)
682{
683#ifndef USE_KDTREE
684 /* localize */
685 const float (*coords)[2] = pf->coords;
686 PolyIndex *pi_curr;
687
688 const float *v1, *v2, *v3;
689#endif
690
691#if defined(USE_CONVEX_SKIP) && !defined(USE_KDTREE)
692 uint32_t coords_num_concave_checked = 0;
693#endif
694
695#ifdef USE_CONVEX_SKIP
696
697# ifdef USE_CONVEX_SKIP_TEST
698 /* check if counting is wrong */
699 {
700 uint32_t coords_num_concave_test = 0;
701 PolyIndex *pi_iter = pi_ear_tip;
702 do {
703 if (pi_iter->sign != CONVEX) {
704 coords_num_concave_test += 1;
705 }
706 } while ((pi_iter = pi_iter->next) != pi_ear_tip);
707 BLI_assert(coords_num_concave_test == pf->coords_num_concave);
708 }
709# endif
710
711 /* fast-path for circles */
712 if (pf->coords_num_concave == 0) {
713 return true;
714 }
715#endif
716
717 if (UNLIKELY(pi_ear_tip->sign != sign_accept)) {
718 return false;
719 }
720
721#ifdef USE_KDTREE
722 {
723 const uint32_t ind[3] = {pi_ear_tip->index, pi_ear_tip->next->index, pi_ear_tip->prev->index};
724
725 if (kdtree2d_isect_tri(&pf->kdtree, ind)) {
726 return false;
727 }
728 }
729#else
730
731 v1 = coords[pi_ear_tip->prev->index];
732 v2 = coords[pi_ear_tip->index];
733 v3 = coords[pi_ear_tip->next->index];
734
735 /* Check if any point is inside the triangle formed by previous, current and next vertices.
736 * Only consider vertices that are not part of this triangle,
737 * or else we'll always find one inside. */
738
739 for (pi_curr = pi_ear_tip->next->next; pi_curr != pi_ear_tip->prev; pi_curr = pi_curr->next) {
740 /* Concave vertices can obviously be inside the candidate ear,
741 * but so can tangential vertices if they coincide with one of the triangle's vertices. */
742 if (pi_curr->sign != CONVEX) {
743 const float *v = coords[pi_curr->index];
744 /* Because the polygon has clockwise winding order,
745 * the area sign will be positive if the point is strictly inside.
746 * It will be 0 on the edge, which we want to include as well. */
747
748 /* NOTE: check (v3, v1) first since it fails _far_ more often than the other 2 checks
749 * (those fail equally).
750 * It's logical - the chance is low that points exist on the
751 * same side as the ear we're clipping off. */
752 if ((span_tri_v2_sign(v3, v1, v) != CONCAVE) && (span_tri_v2_sign(v1, v2, v) != CONCAVE) &&
753 (span_tri_v2_sign(v2, v3, v) != CONCAVE))
754 {
755 return false;
756 }
757
758# ifdef USE_CONVEX_SKIP
759 coords_num_concave_checked += 1;
760 if (coords_num_concave_checked == pf->coords_num_concave) {
761 break;
762 }
763# endif
764 }
765 }
766#endif /* USE_KDTREE */
767
768 return true;
769}
770
771static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip)
772{
773 uint32_t *tri = pf_tri_add(pf);
774
775 tri[0] = pi_ear_tip->prev->index;
776 tri[1] = pi_ear_tip->index;
777 tri[2] = pi_ear_tip->next->index;
778
779 pf_coord_remove(pf, pi_ear_tip);
780}
781
785static void polyfill_prepare(PolyFill *pf,
786 const float (*coords)[2],
787 const uint32_t coords_num,
788 int coords_sign,
789 uint32_t (*r_tris)[3],
790 PolyIndex *r_indices)
791{
792 /* localize */
793 PolyIndex *indices = r_indices;
794
795 uint32_t i;
796
797 /* assign all polyfill members here */
798 pf->indices = r_indices;
799 pf->coords = coords;
800 pf->coords_num = coords_num;
801#ifdef USE_CONVEX_SKIP
802 pf->coords_num_concave = 0;
803#endif
804 pf->tris = r_tris;
805 pf->tris_num = 0;
806
807 if (coords_sign == 0) {
808 coords_sign = (cross_poly_v2(coords, coords_num) <= 0.0f) ? 1 : -1;
809 }
810 else {
811 /* check we're passing in correct args */
812#ifdef USE_STRICT_ASSERT
813# ifndef NDEBUG
814 if (coords_sign == 1) {
815 BLI_assert(cross_poly_v2(coords, coords_num) <= 0.0f);
816 }
817 else {
818 BLI_assert(cross_poly_v2(coords, coords_num) >= 0.0f);
819 }
820# endif
821#endif
822 }
823
824 if (coords_sign == 1) {
825 for (i = 0; i < coords_num; i++) {
826 indices[i].next = &indices[i + 1];
827 indices[i].prev = &indices[i - 1];
828 indices[i].index = i;
829 }
830 }
831 else {
832 /* reversed */
833 uint32_t n = coords_num - 1;
834 for (i = 0; i < coords_num; i++) {
835 indices[i].next = &indices[i + 1];
836 indices[i].prev = &indices[i - 1];
837 indices[i].index = (n - i);
838 }
839 }
840 indices[0].prev = &indices[coords_num - 1];
841 indices[coords_num - 1].next = &indices[0];
842
843 for (i = 0; i < coords_num; i++) {
844 PolyIndex *pi = &indices[i];
846#ifdef USE_CONVEX_SKIP
847 if (pi->sign != CONVEX) {
848 pf->coords_num_concave += 1;
849 }
850#endif
851 }
852}
853
854static void polyfill_calc(PolyFill *pf)
855{
856#ifdef USE_KDTREE
857# ifdef USE_CONVEX_SKIP
858 if (pf->coords_num_concave)
859# endif
860 {
861 kdtree2d_new(&pf->kdtree, pf->coords_num_concave, pf->coords);
862 kdtree2d_init(&pf->kdtree, pf->coords_num, pf->indices);
863 kdtree2d_balance(&pf->kdtree);
864 kdtree2d_init_mapping(&pf->kdtree);
865 }
866#endif
867
869}
870
871void BLI_polyfill_calc_arena(const float (*coords)[2],
872 const uint32_t coords_num,
873 const int coords_sign,
874 uint32_t (*r_tris)[3],
875
876 MemArena *arena)
877{
878 PolyFill pf;
879 PolyIndex *indices = static_cast<PolyIndex *>(
880 BLI_memarena_alloc(arena, sizeof(*indices) * coords_num));
881
882#ifdef DEBUG_TIME
883 TIMEIT_START(polyfill2d);
884#endif
885
887 coords,
888 coords_num,
889 coords_sign,
890 r_tris,
891 /* cache */
892 indices);
893
894#ifdef USE_KDTREE
895 if (pf.coords_num_concave) {
896 pf.kdtree.nodes = static_cast<KDTreeNode2D *>(
897 BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes) * pf.coords_num_concave));
898 pf.kdtree.nodes_map = static_cast<uint32_t *>(
899 memset(BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes_map) * coords_num),
900 0xff,
901 sizeof(*pf.kdtree.nodes_map) * coords_num));
902 }
903 else {
904 pf.kdtree.node_num = 0;
905 }
906#endif
907
909
910 /* indices are no longer needed,
911 * caller can clear arena */
912
913#ifdef DEBUG_TIME
914 TIMEIT_END(polyfill2d);
915#endif
916}
917
918void BLI_polyfill_calc(const float (*coords)[2],
919 const uint32_t coords_num,
920 const int coords_sign,
921 uint32_t (*r_tris)[3])
922{
923 /* Fall back to heap memory for large allocations.
924 * Avoid running out of stack memory on systems with 512kb stack (macOS).
925 * This happens at around 13,000 points, use a much lower value to be safe. */
926 if (UNLIKELY(coords_num > 8192)) {
927 /* The buffer size only accounts for the index allocation,
928 * worst case we do two allocations when concave, while we should try to be efficient,
929 * any caller that relies on this frequently should use #BLI_polyfill_calc_arena directly. */
930 MemArena *arena = BLI_memarena_new(sizeof(PolyIndex) * coords_num, __func__);
931 BLI_polyfill_calc_arena(coords, coords_num, coords_sign, r_tris, arena);
932 BLI_memarena_free(arena);
933 return;
934 }
935
936 PolyFill pf;
937 PolyIndex *indices = static_cast<PolyIndex *>(BLI_array_alloca(indices, coords_num));
938
939#ifdef DEBUG_TIME
940 TIMEIT_START(polyfill2d);
941#endif
942
944 coords,
945 coords_num,
946 coords_sign,
947 r_tris,
948 /* cache */
949 indices);
950
951#ifdef USE_KDTREE
952 if (pf.coords_num_concave) {
953 pf.kdtree.nodes = static_cast<KDTreeNode2D *>(
954 BLI_array_alloca(pf.kdtree.nodes, pf.coords_num_concave));
955 pf.kdtree.nodes_map = static_cast<uint32_t *>(
956 memset(BLI_array_alloca(pf.kdtree.nodes_map, coords_num),
957 0xff,
958 sizeof(*pf.kdtree.nodes_map) * coords_num));
959 }
960 else {
961 pf.kdtree.node_num = 0;
962 }
963#endif
964
966
967#ifdef DEBUG_TIME
968 TIMEIT_END(polyfill2d);
969#endif
970}
#define BLI_array_alloca(arr, realsize)
Definition BLI_alloca.h:18
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_INLINE
uchar axis_t
float cross_poly_v2(const float verts[][2], unsigned int nr)
Definition math_geom.cc:149
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
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)
Utility defines for timing/benchmarks.
#define TIMEIT_START(var)
#define TIMEIT_END(var)
#define CLAMP_MAX(a, c)
#define SWAP(type, a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define CLAMP_MIN(a, b)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
nullptr float
KDTree_3d * tree
static ushort indices[]
#define pf(_x, _i)
Prefetch 64.
Definition gim_memory.h:48
uint pos
constexpr T sign(T) RET
static ulong * next
static void kdtree2d_node_remove(KDTree2D *tree, uint32_t index)
static void pf_coord_sign_calc(const PolyFill *pf, PolyIndex *pi)
static PolyIndex * pf_ear_tip_find(PolyFill *pf, PolyIndex *pi_ear_init, bool reverse)
void BLI_polyfill_calc_arena(const float(*coords)[2], const uint32_t coords_num, const int coords_sign, uint32_t(*r_tris)[3], MemArena *arena)
static uint32_t kdtree2d_balance_recursive(KDTreeNode2D *nodes, uint32_t node_num, axis_t axis, const float(*coords)[2], const uint32_t ofs)
static void kdtree2d_balance(KDTree2D *tree)
void BLI_polyfill_calc(const float(*coords)[2], const uint32_t coords_num, const int coords_sign, uint32_t(*r_tris)[3])
static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip, const eSign sign_accept)
BLI_INLINE eSign signum_enum(float a)
static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip)
#define KDTREE2D_ISECT_TRI_RECURSE_NEG
static bool kdtree2d_isect_tri(KDTree2D *tree, const uint32_t ind[3])
static bool kdtree2d_isect_tri_recursive(const KDTree2D *tree, const uint32_t tri_index[3], const float *tri_coords[3], const float tri_center[2], const KDRange2D bounds[2], const KDTreeNode2D *node)
static uint32_t * pf_tri_add(PolyFill *pf)
BLI_INLINE float area_tri_signed_v2_alt_2x(const float v1[2], const float v2[2], const float v3[2])
static void polyfill_prepare(PolyFill *pf, const float(*coords)[2], const uint32_t coords_num, int coords_sign, uint32_t(*r_tris)[3], PolyIndex *r_indices)
@ KDNODE_FLAG_REMOVED
#define USE_CLIP_EVEN
#define KDNODE_UNSET
#define USE_CLIP_SWEEP
static eSign span_tri_v2_sign(const float v1[2], const float v2[2], const float v3[2])
static void kdtree2d_init_mapping(KDTree2D *tree)
static void kdtree2d_new(KDTree2D *tree, uint32_t tot, const float(*coords)[2])
#define KDTREE2D_ISECT_TRI_RECURSE_POS
static void kdtree2d_init(KDTree2D *tree, const uint32_t coords_num, const PolyIndex *indices)
static void polyfill_calc(PolyFill *pf)
static void pf_coord_remove(PolyFill *pf, PolyIndex *pi)
static void pf_triangulate(PolyFill *pf)
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint8_t flag
Definition wm_window.cc:145