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