Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/intern/polyfill_2d.c')
-rw-r--r--source/blender/blenlib/intern/polyfill_2d.c1203
1 files changed, 586 insertions, 617 deletions
diff --git a/source/blender/blenlib/intern/polyfill_2d.c b/source/blender/blenlib/intern/polyfill_2d.c
index 4044ebad56b..1538b5922b1 100644
--- a/source/blender/blenlib/intern/polyfill_2d.c
+++ b/source/blender/blenlib/intern/polyfill_2d.c
@@ -49,7 +49,7 @@
#include "BLI_memarena.h"
#include "BLI_alloca.h"
-#include "BLI_polyfill_2d.h" /* own include */
+#include "BLI_polyfill_2d.h" /* own include */
#include "BLI_strict_flags.h"
@@ -72,7 +72,6 @@
# include "PIL_time_utildefines.h"
#endif
-
typedef signed char eSign;
#ifdef USE_KDTREE
@@ -99,93 +98,91 @@ typedef bool axis_t;
/* use for sorting */
typedef struct KDTreeNode2D_head {
- uint neg, pos;
- uint index;
+ uint neg, pos;
+ uint index;
} KDTreeNode2D_head;
typedef struct KDTreeNode2D {
- uint neg, pos;
- uint index;
- axis_t axis; /* range is only (0-1) */
- ushort flag;
- uint parent;
+ uint neg, pos;
+ uint index;
+ axis_t axis; /* range is only (0-1) */
+ ushort flag;
+ uint parent;
} KDTreeNode2D;
struct KDTree2D {
- KDTreeNode2D *nodes;
- const float (*coords)[2];
- uint root;
- uint totnode;
- uint *nodes_map; /* index -> node lookup */
+ KDTreeNode2D *nodes;
+ const float (*coords)[2];
+ uint root;
+ uint totnode;
+ uint *nodes_map; /* index -> node lookup */
};
struct KDRange2D {
- float min, max;
+ float min, max;
};
-#endif /* USE_KDTREE */
+#endif /* USE_KDTREE */
enum {
- CONCAVE = -1,
- TANGENTIAL = 0,
- CONVEX = 1,
+ CONCAVE = -1,
+ TANGENTIAL = 0,
+ CONVEX = 1,
};
typedef struct PolyFill {
- struct PolyIndex *indices; /* vertex aligned */
+ struct PolyIndex *indices; /* vertex aligned */
- const float (*coords)[2];
- uint coords_tot;
+ const float (*coords)[2];
+ uint coords_tot;
#ifdef USE_CONVEX_SKIP
- uint coords_tot_concave;
+ uint coords_tot_concave;
#endif
- /* A polygon with n vertices has a triangulation of n-2 triangles. */
- uint (*tris)[3];
- uint tris_tot;
+ /* A polygon with n vertices has a triangulation of n-2 triangles. */
+ uint (*tris)[3];
+ uint tris_tot;
#ifdef USE_KDTREE
- struct KDTree2D kdtree;
+ struct KDTree2D kdtree;
#endif
} PolyFill;
-
/* circular linklist */
typedef struct PolyIndex {
- struct PolyIndex *next, *prev;
- uint index;
- eSign sign;
+ struct PolyIndex *next, *prev;
+ uint index;
+ eSign sign;
} PolyIndex;
-
/* based on libgdx 2013-11-28, apache 2.0 licensed */
static void pf_coord_sign_calc(PolyFill *pf, PolyIndex *pi);
-static PolyIndex *pf_ear_tip_find(
- PolyFill *pf
+static PolyIndex *pf_ear_tip_find(PolyFill *pf
#ifdef USE_CLIP_EVEN
- , PolyIndex *pi_ear_init
+ ,
+ PolyIndex *pi_ear_init
#endif
#ifdef USE_CLIP_SWEEP
- , bool reverse
+ ,
+ bool reverse
#endif
- );
-
-static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip);
-static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip);
+);
+static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip);
+static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip);
BLI_INLINE eSign signum_enum(float a)
{
- if (UNLIKELY(a == 0.0f)) {
- return 0;
- }
- else if (a > 0.0f) {
- return 1;
- }
- else {
- return -1;
- }
+ if (UNLIKELY(a == 0.0f)) {
+ return 0;
+ }
+ else if (a > 0.0f) {
+ return 1;
+ }
+ else {
+ return -1;
+ }
}
/**
@@ -196,407 +193,386 @@ BLI_INLINE eSign signum_enum(float a)
*/
BLI_INLINE float area_tri_signed_v2_alt_2x(const float v1[2], const float v2[2], const float v3[2])
{
- return ((v1[0] * (v2[1] - v3[1])) +
- (v2[0] * (v3[1] - v1[1])) +
- (v3[0] * (v1[1] - v2[1])));
+ return ((v1[0] * (v2[1] - v3[1])) + (v2[0] * (v3[1] - v1[1])) + (v3[0] * (v1[1] - v2[1])));
}
-
static eSign span_tri_v2_sign(const float v1[2], const float v2[2], const float v3[2])
{
- return signum_enum(area_tri_signed_v2_alt_2x(v3, v2, v1));
+ return signum_enum(area_tri_signed_v2_alt_2x(v3, v2, v1));
}
-
#ifdef USE_KDTREE
-#define KDNODE_UNSET ((uint)-1)
+# define KDNODE_UNSET ((uint)-1)
enum {
- KDNODE_FLAG_REMOVED = (1 << 0),
+ KDNODE_FLAG_REMOVED = (1 << 0),
};
-static void kdtree2d_new(
- struct KDTree2D *tree,
- uint tot,
- const float (*coords)[2])
+static void kdtree2d_new(struct KDTree2D *tree, uint tot, const float (*coords)[2])
{
- /* set by caller */
- // tree->nodes = nodes;
- tree->coords = coords;
- tree->root = KDNODE_UNSET;
- tree->totnode = tot;
+ /* set by caller */
+ // tree->nodes = nodes;
+ tree->coords = coords;
+ tree->root = KDNODE_UNSET;
+ tree->totnode = tot;
}
/**
* no need for kdtree2d_insert, since we know the coords array.
*/
-static void kdtree2d_init(
- struct KDTree2D *tree,
- const uint coords_tot,
- const PolyIndex *indices)
+static void kdtree2d_init(struct KDTree2D *tree, const uint coords_tot, const PolyIndex *indices)
{
- KDTreeNode2D *node;
- uint i;
-
- for (i = 0, node = tree->nodes; i < coords_tot; i++) {
- if (indices[i].sign != CONVEX) {
- node->neg = node->pos = KDNODE_UNSET;
- node->index = indices[i].index;
- node->axis = 0;
- node->flag = 0;
- node++;
- }
- }
-
- BLI_assert(tree->totnode == (uint)(node - tree->nodes));
+ KDTreeNode2D *node;
+ uint i;
+
+ for (i = 0, node = tree->nodes; i < coords_tot; i++) {
+ if (indices[i].sign != CONVEX) {
+ node->neg = node->pos = KDNODE_UNSET;
+ node->index = indices[i].index;
+ node->axis = 0;
+ node->flag = 0;
+ node++;
+ }
+ }
+
+ BLI_assert(tree->totnode == (uint)(node - tree->nodes));
}
static uint kdtree2d_balance_recursive(
- KDTreeNode2D *nodes, uint totnode, axis_t axis,
- const float (*coords)[2], const uint ofs)
+ KDTreeNode2D *nodes, uint totnode, axis_t axis, const float (*coords)[2], const uint ofs)
{
- KDTreeNode2D *node;
- uint neg, pos, median, i, j;
-
- if (totnode <= 0) {
- return KDNODE_UNSET;
- }
- else if (totnode == 1) {
- return 0 + ofs;
- }
-
- /* quicksort style sorting around median */
- neg = 0;
- pos = totnode - 1;
- median = totnode / 2;
-
- while (pos > neg) {
- const float co = coords[nodes[pos].index][axis];
- i = neg - 1;
- j = pos;
-
- while (1) {
- while (coords[nodes[++i].index][axis] < co) { /* pass */ }
- while (coords[nodes[--j].index][axis] > co && j > neg) { /* pass */ }
-
- if (i >= j) {
- break;
- }
- SWAP(KDTreeNode2D_head, *(KDTreeNode2D_head *)&nodes[i], *(KDTreeNode2D_head *)&nodes[j]);
- }
-
- SWAP(KDTreeNode2D_head, *(KDTreeNode2D_head *)&nodes[i], *(KDTreeNode2D_head *)&nodes[pos]);
- if (i >= median) {
- pos = i - 1;
- }
- if (i <= median) {
- neg = i + 1;
- }
- }
-
- /* set node and sort subnodes */
- node = &nodes[median];
- node->axis = axis;
- axis = !axis;
- node->neg = kdtree2d_balance_recursive(nodes, median, axis, coords, ofs);
- node->pos = kdtree2d_balance_recursive(&nodes[median + 1], (totnode - (median + 1)), axis, coords, (median + 1) + ofs);
-
- return median + ofs;
+ KDTreeNode2D *node;
+ uint neg, pos, median, i, j;
+
+ if (totnode <= 0) {
+ return KDNODE_UNSET;
+ }
+ else if (totnode == 1) {
+ return 0 + ofs;
+ }
+
+ /* quicksort style sorting around median */
+ neg = 0;
+ pos = totnode - 1;
+ median = totnode / 2;
+
+ while (pos > neg) {
+ const float co = coords[nodes[pos].index][axis];
+ i = neg - 1;
+ j = pos;
+
+ while (1) {
+ while (coords[nodes[++i].index][axis] < co) { /* pass */
+ }
+ while (coords[nodes[--j].index][axis] > co && j > neg) { /* pass */
+ }
+
+ if (i >= j) {
+ break;
+ }
+ SWAP(KDTreeNode2D_head, *(KDTreeNode2D_head *)&nodes[i], *(KDTreeNode2D_head *)&nodes[j]);
+ }
+
+ SWAP(KDTreeNode2D_head, *(KDTreeNode2D_head *)&nodes[i], *(KDTreeNode2D_head *)&nodes[pos]);
+ if (i >= median) {
+ pos = i - 1;
+ }
+ if (i <= median) {
+ neg = i + 1;
+ }
+ }
+
+ /* set node and sort subnodes */
+ node = &nodes[median];
+ node->axis = axis;
+ axis = !axis;
+ node->neg = kdtree2d_balance_recursive(nodes, median, axis, coords, ofs);
+ node->pos = kdtree2d_balance_recursive(
+ &nodes[median + 1], (totnode - (median + 1)), axis, coords, (median + 1) + ofs);
+
+ return median + ofs;
}
-static void kdtree2d_balance(
- struct KDTree2D *tree)
+static void kdtree2d_balance(struct KDTree2D *tree)
{
- tree->root = kdtree2d_balance_recursive(tree->nodes, tree->totnode, 0, tree->coords, 0);
+ tree->root = kdtree2d_balance_recursive(tree->nodes, tree->totnode, 0, tree->coords, 0);
}
-
-static void kdtree2d_init_mapping(
- struct KDTree2D *tree)
+static void kdtree2d_init_mapping(struct KDTree2D *tree)
{
- uint i;
- KDTreeNode2D *node;
-
- for (i = 0, node = tree->nodes; i < tree->totnode; i++, node++) {
- if (node->neg != KDNODE_UNSET) {
- tree->nodes[node->neg].parent = i;
- }
- if (node->pos != KDNODE_UNSET) {
- tree->nodes[node->pos].parent = i;
- }
-
- /* build map */
- BLI_assert(tree->nodes_map[node->index] == KDNODE_UNSET);
- tree->nodes_map[node->index] = i;
- }
-
- tree->nodes[tree->root].parent = KDNODE_UNSET;
+ uint i;
+ KDTreeNode2D *node;
+
+ for (i = 0, node = tree->nodes; i < tree->totnode; i++, node++) {
+ if (node->neg != KDNODE_UNSET) {
+ tree->nodes[node->neg].parent = i;
+ }
+ if (node->pos != KDNODE_UNSET) {
+ tree->nodes[node->pos].parent = i;
+ }
+
+ /* build map */
+ BLI_assert(tree->nodes_map[node->index] == KDNODE_UNSET);
+ tree->nodes_map[node->index] = i;
+ }
+
+ tree->nodes[tree->root].parent = KDNODE_UNSET;
}
-static void kdtree2d_node_remove(
- struct KDTree2D *tree,
- uint index)
+static void kdtree2d_node_remove(struct KDTree2D *tree, uint index)
{
- uint node_index = tree->nodes_map[index];
- KDTreeNode2D *node;
-
- if (node_index == KDNODE_UNSET) {
- return;
- }
- else {
- tree->nodes_map[index] = KDNODE_UNSET;
- }
-
- node = &tree->nodes[node_index];
- tree->totnode -= 1;
-
- BLI_assert((node->flag & KDNODE_FLAG_REMOVED) == 0);
- node->flag |= KDNODE_FLAG_REMOVED;
-
- while ((node->neg == KDNODE_UNSET) &&
- (node->pos == KDNODE_UNSET) &&
- (node->parent != KDNODE_UNSET))
- {
- KDTreeNode2D *node_parent = &tree->nodes[node->parent];
-
- BLI_assert((uint)(node - tree->nodes) == node_index);
- if (node_parent->neg == node_index) {
- node_parent->neg = KDNODE_UNSET;
- }
- else {
- BLI_assert(node_parent->pos == node_index);
- node_parent->pos = KDNODE_UNSET;
- }
-
- if (node_parent->flag & KDNODE_FLAG_REMOVED) {
- node_index = node->parent;
- node = node_parent;
- }
- else {
- break;
- }
- }
+ uint node_index = tree->nodes_map[index];
+ KDTreeNode2D *node;
+
+ if (node_index == KDNODE_UNSET) {
+ return;
+ }
+ else {
+ tree->nodes_map[index] = KDNODE_UNSET;
+ }
+
+ node = &tree->nodes[node_index];
+ tree->totnode -= 1;
+
+ BLI_assert((node->flag & KDNODE_FLAG_REMOVED) == 0);
+ node->flag |= KDNODE_FLAG_REMOVED;
+
+ while ((node->neg == KDNODE_UNSET) && (node->pos == KDNODE_UNSET) &&
+ (node->parent != KDNODE_UNSET)) {
+ KDTreeNode2D *node_parent = &tree->nodes[node->parent];
+
+ BLI_assert((uint)(node - tree->nodes) == node_index);
+ if (node_parent->neg == node_index) {
+ node_parent->neg = KDNODE_UNSET;
+ }
+ else {
+ BLI_assert(node_parent->pos == node_index);
+ node_parent->pos = KDNODE_UNSET;
+ }
+
+ if (node_parent->flag & KDNODE_FLAG_REMOVED) {
+ node_index = node->parent;
+ node = node_parent;
+ }
+ else {
+ break;
+ }
+ }
}
-static bool kdtree2d_isect_tri_recursive(
- const struct KDTree2D *tree,
- const uint tri_index[3],
- const float *tri_coords[3],
- const float tri_center[2],
- const struct KDRange2D bounds[2],
- const KDTreeNode2D *node)
+static bool kdtree2d_isect_tri_recursive(const struct KDTree2D *tree,
+ const uint tri_index[3],
+ const float *tri_coords[3],
+ const float tri_center[2],
+ const struct KDRange2D bounds[2],
+ const KDTreeNode2D *node)
{
- const float *co = tree->coords[node->index];
-
- /* bounds then triangle intersect */
- if ((node->flag & KDNODE_FLAG_REMOVED) == 0) {
- /* bounding box test first */
- if ((co[0] >= bounds[0].min) &&
- (co[0] <= bounds[0].max) &&
- (co[1] >= bounds[1].min) &&
- (co[1] <= bounds[1].max))
- {
- if ((span_tri_v2_sign(tri_coords[0], tri_coords[1], co) != CONCAVE) &&
- (span_tri_v2_sign(tri_coords[1], tri_coords[2], co) != CONCAVE) &&
- (span_tri_v2_sign(tri_coords[2], tri_coords[0], co) != CONCAVE))
- {
- if (!ELEM(node->index, tri_index[0], tri_index[1], tri_index[2])) {
- return true;
- }
- }
- }
- }
-
-#define KDTREE2D_ISECT_TRI_RECURSE_NEG \
- (((node->neg != KDNODE_UNSET) && (co[node->axis] >= bounds[node->axis].min)) && \
- (kdtree2d_isect_tri_recursive(tree, tri_index, tri_coords, tri_center, bounds, \
- &tree->nodes[node->neg])))
-#define KDTREE2D_ISECT_TRI_RECURSE_POS \
- (((node->pos != KDNODE_UNSET) && (co[node->axis] <= bounds[node->axis].max)) && \
- (kdtree2d_isect_tri_recursive(tree, tri_index, tri_coords, tri_center, bounds, \
- &tree->nodes[node->pos])))
-
- if (tri_center[node->axis] > co[node->axis]) {
- if (KDTREE2D_ISECT_TRI_RECURSE_POS) {
- return true;
- }
- if (KDTREE2D_ISECT_TRI_RECURSE_NEG) {
- return true;
- }
- }
- else {
- if (KDTREE2D_ISECT_TRI_RECURSE_NEG) {
- return true;
- }
- if (KDTREE2D_ISECT_TRI_RECURSE_POS) {
- return true;
- }
- }
-
-#undef KDTREE2D_ISECT_TRI_RECURSE_NEG
-#undef KDTREE2D_ISECT_TRI_RECURSE_POS
-
- BLI_assert(node->index != KDNODE_UNSET);
-
- return false;
+ const float *co = tree->coords[node->index];
+
+ /* bounds then triangle intersect */
+ if ((node->flag & KDNODE_FLAG_REMOVED) == 0) {
+ /* bounding box test first */
+ if ((co[0] >= bounds[0].min) && (co[0] <= bounds[0].max) && (co[1] >= bounds[1].min) &&
+ (co[1] <= bounds[1].max)) {
+ if ((span_tri_v2_sign(tri_coords[0], tri_coords[1], co) != CONCAVE) &&
+ (span_tri_v2_sign(tri_coords[1], tri_coords[2], co) != CONCAVE) &&
+ (span_tri_v2_sign(tri_coords[2], tri_coords[0], co) != CONCAVE)) {
+ if (!ELEM(node->index, tri_index[0], tri_index[1], tri_index[2])) {
+ return true;
+ }
+ }
+ }
+ }
+
+# define KDTREE2D_ISECT_TRI_RECURSE_NEG \
+ (((node->neg != KDNODE_UNSET) && (co[node->axis] >= bounds[node->axis].min)) && \
+ (kdtree2d_isect_tri_recursive( \
+ tree, tri_index, tri_coords, tri_center, bounds, &tree->nodes[node->neg])))
+# define KDTREE2D_ISECT_TRI_RECURSE_POS \
+ (((node->pos != KDNODE_UNSET) && (co[node->axis] <= bounds[node->axis].max)) && \
+ (kdtree2d_isect_tri_recursive( \
+ tree, tri_index, tri_coords, tri_center, bounds, &tree->nodes[node->pos])))
+
+ if (tri_center[node->axis] > co[node->axis]) {
+ if (KDTREE2D_ISECT_TRI_RECURSE_POS) {
+ return true;
+ }
+ if (KDTREE2D_ISECT_TRI_RECURSE_NEG) {
+ return true;
+ }
+ }
+ else {
+ if (KDTREE2D_ISECT_TRI_RECURSE_NEG) {
+ return true;
+ }
+ if (KDTREE2D_ISECT_TRI_RECURSE_POS) {
+ return true;
+ }
+ }
+
+# undef KDTREE2D_ISECT_TRI_RECURSE_NEG
+# undef KDTREE2D_ISECT_TRI_RECURSE_POS
+
+ BLI_assert(node->index != KDNODE_UNSET);
+
+ return false;
}
-static bool kdtree2d_isect_tri(
- struct KDTree2D *tree,
- const uint ind[3])
+static bool kdtree2d_isect_tri(struct KDTree2D *tree, const uint ind[3])
{
- const float *vs[3];
- uint i;
- struct KDRange2D bounds[2] = {
- {FLT_MAX, -FLT_MAX},
- {FLT_MAX, -FLT_MAX},
- };
- float tri_center[2] = {0.0f, 0.0f};
+ const float *vs[3];
+ uint i;
+ struct KDRange2D bounds[2] = {
+ {FLT_MAX, -FLT_MAX},
+ {FLT_MAX, -FLT_MAX},
+ };
+ float tri_center[2] = {0.0f, 0.0f};
- for (i = 0; i < 3; i++) {
- vs[i] = tree->coords[ind[i]];
+ for (i = 0; i < 3; i++) {
+ vs[i] = tree->coords[ind[i]];
- add_v2_v2(tri_center, vs[i]);
+ add_v2_v2(tri_center, vs[i]);
- CLAMP_MAX(bounds[0].min, vs[i][0]);
- CLAMP_MIN(bounds[0].max, vs[i][0]);
- CLAMP_MAX(bounds[1].min, vs[i][1]);
- CLAMP_MIN(bounds[1].max, vs[i][1]);
- }
+ CLAMP_MAX(bounds[0].min, vs[i][0]);
+ CLAMP_MIN(bounds[0].max, vs[i][0]);
+ CLAMP_MAX(bounds[1].min, vs[i][1]);
+ CLAMP_MIN(bounds[1].max, vs[i][1]);
+ }
- mul_v2_fl(tri_center, 1.0f / 3.0f);
+ mul_v2_fl(tri_center, 1.0f / 3.0f);
- return kdtree2d_isect_tri_recursive(tree, ind, vs, tri_center, bounds, &tree->nodes[tree->root]);
+ return kdtree2d_isect_tri_recursive(tree, ind, vs, tri_center, bounds, &tree->nodes[tree->root]);
}
-#endif /* USE_KDTREE */
-
+#endif /* USE_KDTREE */
static uint *pf_tri_add(PolyFill *pf)
{
- return pf->tris[pf->tris_tot++];
+ return pf->tris[pf->tris_tot++];
}
static void pf_coord_remove(PolyFill *pf, PolyIndex *pi)
{
#ifdef USE_KDTREE
- /* avoid double lookups, since convex coords are ignored when testing intersections */
- if (pf->kdtree.totnode) {
- kdtree2d_node_remove(&pf->kdtree, pi->index);
- }
+ /* avoid double lookups, since convex coords are ignored when testing intersections */
+ if (pf->kdtree.totnode) {
+ kdtree2d_node_remove(&pf->kdtree, pi->index);
+ }
#endif
- pi->next->prev = pi->prev;
- pi->prev->next = pi->next;
+ pi->next->prev = pi->prev;
+ pi->prev->next = pi->next;
- if (UNLIKELY(pf->indices == pi)) {
- pf->indices = pi->next;
- }
+ if (UNLIKELY(pf->indices == pi)) {
+ pf->indices = pi->next;
+ }
#ifdef DEBUG
- pi->index = (uint)-1;
- pi->next = pi->prev = NULL;
+ pi->index = (uint)-1;
+ pi->next = pi->prev = NULL;
#endif
- pf->coords_tot -= 1;
+ pf->coords_tot -= 1;
}
static void pf_triangulate(PolyFill *pf)
{
- /* localize */
- PolyIndex *pi_ear;
+ /* localize */
+ PolyIndex *pi_ear;
#ifdef USE_CLIP_EVEN
- PolyIndex *pi_ear_init = pf->indices;
+ PolyIndex *pi_ear_init = pf->indices;
#endif
#ifdef USE_CLIP_SWEEP
- bool reverse = false;
+ bool reverse = false;
#endif
- while (pf->coords_tot > 3) {
- PolyIndex *pi_prev, *pi_next;
- eSign sign_orig_prev, sign_orig_next;
+ while (pf->coords_tot > 3) {
+ PolyIndex *pi_prev, *pi_next;
+ eSign sign_orig_prev, sign_orig_next;
- pi_ear = pf_ear_tip_find(
- pf
+ pi_ear = pf_ear_tip_find(pf
#ifdef USE_CLIP_EVEN
- , pi_ear_init
+ ,
+ pi_ear_init
#endif
#ifdef USE_CLIP_SWEEP
- , reverse
+ ,
+ reverse
#endif
- );
+ );
#ifdef USE_CONVEX_SKIP
- if (pi_ear->sign != CONVEX) {
- pf->coords_tot_concave -= 1;
- }
+ if (pi_ear->sign != CONVEX) {
+ pf->coords_tot_concave -= 1;
+ }
#endif
- pi_prev = pi_ear->prev;
- pi_next = pi_ear->next;
+ pi_prev = pi_ear->prev;
+ pi_next = pi_ear->next;
- pf_ear_tip_cut(pf, pi_ear);
+ pf_ear_tip_cut(pf, pi_ear);
- /* The type of the two vertices adjacent to the clipped vertex may have changed. */
- sign_orig_prev = pi_prev->sign;
- sign_orig_next = pi_next->sign;
+ /* The type of the two vertices adjacent to the clipped vertex may have changed. */
+ sign_orig_prev = pi_prev->sign;
+ sign_orig_next = pi_next->sign;
- /* check if any verts became convex the (else if)
- * case is highly unlikely but may happen with degenerate polygons */
- if (sign_orig_prev != CONVEX) {
- pf_coord_sign_calc(pf, pi_prev);
+ /* check if any verts became convex the (else if)
+ * case is highly unlikely but may happen with degenerate polygons */
+ if (sign_orig_prev != CONVEX) {
+ pf_coord_sign_calc(pf, pi_prev);
#ifdef USE_CONVEX_SKIP
- if (pi_prev->sign == CONVEX) {
- pf->coords_tot_concave -= 1;
-#ifdef USE_KDTREE
- kdtree2d_node_remove(&pf->kdtree, pi_prev->index);
-#endif
- }
-#endif
- }
- if (sign_orig_next != CONVEX) {
- pf_coord_sign_calc(pf, pi_next);
+ if (pi_prev->sign == CONVEX) {
+ pf->coords_tot_concave -= 1;
+# ifdef USE_KDTREE
+ kdtree2d_node_remove(&pf->kdtree, pi_prev->index);
+# endif
+ }
+#endif
+ }
+ if (sign_orig_next != CONVEX) {
+ pf_coord_sign_calc(pf, pi_next);
#ifdef USE_CONVEX_SKIP
- if (pi_next->sign == CONVEX) {
- pf->coords_tot_concave -= 1;
-#ifdef USE_KDTREE
- kdtree2d_node_remove(&pf->kdtree, pi_next->index);
+ if (pi_next->sign == CONVEX) {
+ pf->coords_tot_concave -= 1;
+# ifdef USE_KDTREE
+ kdtree2d_node_remove(&pf->kdtree, pi_next->index);
+# endif
+ }
#endif
- }
-#endif
- }
+ }
#ifdef USE_CLIP_EVEN
-#ifdef USE_CLIP_SWEEP
- pi_ear_init = reverse ? pi_prev->prev : pi_next->next;
-#else
- pi_ear_init = pi_next->next;
-#endif
+# ifdef USE_CLIP_SWEEP
+ pi_ear_init = reverse ? pi_prev->prev : pi_next->next;
+# else
+ pi_ear_init = pi_next->next;
+# endif
#endif
#ifdef USE_CLIP_EVEN
-#ifdef USE_CLIP_SWEEP
- if (pi_ear_init->sign != CONVEX) {
- /* take the extra step since this ear isn't a good candidate */
- pi_ear_init = reverse ? pi_ear_init->prev : pi_ear_init->next;
- reverse = !reverse;
- }
-#endif
+# ifdef USE_CLIP_SWEEP
+ if (pi_ear_init->sign != CONVEX) {
+ /* take the extra step since this ear isn't a good candidate */
+ pi_ear_init = reverse ? pi_ear_init->prev : pi_ear_init->next;
+ reverse = !reverse;
+ }
+# endif
#else
- if ((reverse ? pi_prev->prev : pi_next->next)->sign != CONVEX) {
- reverse = !reverse;
- }
-#endif
-
- }
-
- if (pf->coords_tot == 3) {
- uint *tri = pf_tri_add(pf);
- pi_ear = pf->indices;
- tri[0] = pi_ear->index; pi_ear = pi_ear->next;
- tri[1] = pi_ear->index; pi_ear = pi_ear->next;
- tri[2] = pi_ear->index;
- }
+ if ((reverse ? pi_prev->prev : pi_next->next)->sign != CONVEX) {
+ reverse = !reverse;
+ }
+#endif
+ }
+
+ if (pf->coords_tot == 3) {
+ uint *tri = pf_tri_add(pf);
+ pi_ear = pf->indices;
+ tri[0] = pi_ear->index;
+ pi_ear = pi_ear->next;
+ tri[1] = pi_ear->index;
+ pi_ear = pi_ear->next;
+ tri[2] = pi_ear->index;
+ }
}
/**
@@ -604,319 +580,311 @@ static void pf_triangulate(PolyFill *pf)
*/
static void pf_coord_sign_calc(PolyFill *pf, PolyIndex *pi)
{
- /* localize */
- const float (*coords)[2] = pf->coords;
+ /* localize */
+ const float(*coords)[2] = pf->coords;
- pi->sign = span_tri_v2_sign(
- coords[pi->prev->index],
- coords[pi->index],
- coords[pi->next->index]);
+ pi->sign = span_tri_v2_sign(coords[pi->prev->index], coords[pi->index], coords[pi->next->index]);
}
-static PolyIndex *pf_ear_tip_find(
- PolyFill *pf
+static PolyIndex *pf_ear_tip_find(PolyFill *pf
#ifdef USE_CLIP_EVEN
- , PolyIndex *pi_ear_init
+ ,
+ PolyIndex *pi_ear_init
#endif
#ifdef USE_CLIP_SWEEP
- , bool reverse
+ ,
+ bool reverse
#endif
- )
+)
{
- /* localize */
- const uint coords_tot = pf->coords_tot;
- PolyIndex *pi_ear;
+ /* localize */
+ const uint coords_tot = pf->coords_tot;
+ PolyIndex *pi_ear;
- uint i;
+ uint i;
#ifdef USE_CLIP_EVEN
- pi_ear = pi_ear_init;
+ pi_ear = pi_ear_init;
#else
- pi_ear = pf->indices;
+ pi_ear = pf->indices;
#endif
- i = coords_tot;
- while (i--) {
- if (pf_ear_tip_check(pf, pi_ear)) {
- return pi_ear;
- }
+ i = coords_tot;
+ while (i--) {
+ if (pf_ear_tip_check(pf, pi_ear)) {
+ return pi_ear;
+ }
#ifdef USE_CLIP_SWEEP
- pi_ear = reverse ? pi_ear->prev : pi_ear->next;
+ pi_ear = reverse ? pi_ear->prev : pi_ear->next;
#else
- pi_ear = pi_ear->next;
-#endif
- }
-
- /* Desperate mode: if no vertex is an ear tip,
- * we are dealing with a degenerate polygon (e.g. nearly collinear).
- * Note that the input was not necessarily degenerate,
- * but we could have made it so by clipping some valid ears.
- *
- * Idea taken from Martin Held, "FIST: Fast industrial-strength triangulation of polygons",
- * Algorithmica (1998),
- * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.115.291
- *
- * Return a convex or tangential vertex if one exists.
- */
+ pi_ear = pi_ear->next;
+#endif
+ }
+
+ /* Desperate mode: if no vertex is an ear tip,
+ * we are dealing with a degenerate polygon (e.g. nearly collinear).
+ * Note that the input was not necessarily degenerate,
+ * but we could have made it so by clipping some valid ears.
+ *
+ * Idea taken from Martin Held, "FIST: Fast industrial-strength triangulation of polygons",
+ * Algorithmica (1998),
+ * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.115.291
+ *
+ * Return a convex or tangential vertex if one exists.
+ */
#ifdef USE_CLIP_EVEN
- pi_ear = pi_ear_init;
+ pi_ear = pi_ear_init;
#else
- pi_ear = pf->indices;
+ pi_ear = pf->indices;
#endif
- i = coords_tot;
- while (i--) {
- if (pi_ear->sign != CONCAVE) {
- return pi_ear;
- }
- pi_ear = pi_ear->next;
- }
+ i = coords_tot;
+ while (i--) {
+ if (pi_ear->sign != CONCAVE) {
+ return pi_ear;
+ }
+ pi_ear = pi_ear->next;
+ }
- /* If all vertices are concave, just return the last one. */
- return pi_ear;
+ /* If all vertices are concave, just return the last one. */
+ return pi_ear;
}
static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
{
#ifndef USE_KDTREE
- /* localize */
- const float (*coords)[2] = pf->coords;
- PolyIndex *pi_curr;
+ /* localize */
+ const float(*coords)[2] = pf->coords;
+ PolyIndex *pi_curr;
- const float *v1, *v2, *v3;
+ const float *v1, *v2, *v3;
#endif
#if defined(USE_CONVEX_SKIP) && !defined(USE_KDTREE)
- uint coords_tot_concave_checked = 0;
+ uint coords_tot_concave_checked = 0;
#endif
-
#ifdef USE_CONVEX_SKIP
-#ifdef USE_CONVEX_SKIP_TEST
- /* check if counting is wrong */
- {
- uint coords_tot_concave_test = 0;
- PolyIndex *pi_iter = pi_ear_tip;
- do {
- if (pi_iter->sign != CONVEX) {
- coords_tot_concave_test += 1;
- }
- } while ((pi_iter = pi_iter->next) != pi_ear_tip);
- BLI_assert(coords_tot_concave_test == pf->coords_tot_concave);
- }
-#endif
-
- /* fast-path for circles */
- if (pf->coords_tot_concave == 0) {
- return true;
- }
-#endif
-
- if (UNLIKELY(pi_ear_tip->sign == CONCAVE)) {
- return false;
- }
+# ifdef USE_CONVEX_SKIP_TEST
+ /* check if counting is wrong */
+ {
+ uint coords_tot_concave_test = 0;
+ PolyIndex *pi_iter = pi_ear_tip;
+ do {
+ if (pi_iter->sign != CONVEX) {
+ coords_tot_concave_test += 1;
+ }
+ } while ((pi_iter = pi_iter->next) != pi_ear_tip);
+ BLI_assert(coords_tot_concave_test == pf->coords_tot_concave);
+ }
+# endif
+
+ /* fast-path for circles */
+ if (pf->coords_tot_concave == 0) {
+ return true;
+ }
+#endif
+
+ if (UNLIKELY(pi_ear_tip->sign == CONCAVE)) {
+ return false;
+ }
#ifdef USE_KDTREE
- {
- const uint ind[3] = {
- pi_ear_tip->index,
- pi_ear_tip->next->index,
- pi_ear_tip->prev->index};
-
- if (kdtree2d_isect_tri(&pf->kdtree, ind)) {
- return false;
- }
- }
-#else
+ {
+ const uint ind[3] = {pi_ear_tip->index, pi_ear_tip->next->index, pi_ear_tip->prev->index};
- v1 = coords[pi_ear_tip->prev->index];
- v2 = coords[pi_ear_tip->index];
- v3 = coords[pi_ear_tip->next->index];
-
- /* Check if any point is inside the triangle formed by previous, current and next vertices.
- * Only consider vertices that are not part of this triangle,
- * or else we'll always find one inside. */
-
- for (pi_curr = pi_ear_tip->next->next; pi_curr != pi_ear_tip->prev; pi_curr = pi_curr->next) {
- /* Concave vertices can obviously be inside the candidate ear,
- * but so can tangential vertices if they coincide with one of the triangle's vertices. */
- if (pi_curr->sign != CONVEX) {
- const float *v = coords[pi_curr->index];
- /* Because the polygon has clockwise winding order,
- * the area sign will be positive if the point is strictly inside.
- * It will be 0 on the edge, which we want to include as well. */
-
- /* note: check (v3, v1) first since it fails _far_ more often then the other 2 checks
- * (those fail equally).
- * It's logical - the chance is low that points exist on the
- * same side as the ear we're clipping off. */
- if ((span_tri_v2_sign(v3, v1, v) != CONCAVE) &&
- (span_tri_v2_sign(v1, v2, v) != CONCAVE) &&
- (span_tri_v2_sign(v2, v3, v) != CONCAVE))
- {
- return false;
- }
-
-#ifdef USE_CONVEX_SKIP
- coords_tot_concave_checked += 1;
- if (coords_tot_concave_checked == pf->coords_tot_concave) {
- break;
- }
-#endif
- }
- }
-#endif /* USE_KDTREE */
+ if (kdtree2d_isect_tri(&pf->kdtree, ind)) {
+ return false;
+ }
+ }
+#else
- return true;
+ v1 = coords[pi_ear_tip->prev->index];
+ v2 = coords[pi_ear_tip->index];
+ v3 = coords[pi_ear_tip->next->index];
+
+ /* Check if any point is inside the triangle formed by previous, current and next vertices.
+ * Only consider vertices that are not part of this triangle,
+ * or else we'll always find one inside. */
+
+ for (pi_curr = pi_ear_tip->next->next; pi_curr != pi_ear_tip->prev; pi_curr = pi_curr->next) {
+ /* Concave vertices can obviously be inside the candidate ear,
+ * but so can tangential vertices if they coincide with one of the triangle's vertices. */
+ if (pi_curr->sign != CONVEX) {
+ const float *v = coords[pi_curr->index];
+ /* Because the polygon has clockwise winding order,
+ * the area sign will be positive if the point is strictly inside.
+ * It will be 0 on the edge, which we want to include as well. */
+
+ /* note: check (v3, v1) first since it fails _far_ more often then the other 2 checks
+ * (those fail equally).
+ * It's logical - the chance is low that points exist on the
+ * same side as the ear we're clipping off. */
+ if ((span_tri_v2_sign(v3, v1, v) != CONCAVE) && (span_tri_v2_sign(v1, v2, v) != CONCAVE) &&
+ (span_tri_v2_sign(v2, v3, v) != CONCAVE)) {
+ return false;
+ }
+
+# ifdef USE_CONVEX_SKIP
+ coords_tot_concave_checked += 1;
+ if (coords_tot_concave_checked == pf->coords_tot_concave) {
+ break;
+ }
+# endif
+ }
+ }
+#endif /* USE_KDTREE */
+
+ return true;
}
static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip)
{
- uint *tri = pf_tri_add(pf);
+ uint *tri = pf_tri_add(pf);
- tri[0] = pi_ear_tip->prev->index;
- tri[1] = pi_ear_tip->index;
- tri[2] = pi_ear_tip->next->index;
+ tri[0] = pi_ear_tip->prev->index;
+ tri[1] = pi_ear_tip->index;
+ tri[2] = pi_ear_tip->next->index;
- pf_coord_remove(pf, pi_ear_tip);
+ pf_coord_remove(pf, pi_ear_tip);
}
/**
* Initializes the #PolyFill structure before tessellating with #polyfill_calc.
*/
-static void polyfill_prepare(
- PolyFill *pf,
- const float (*coords)[2],
- const uint coords_tot,
- int coords_sign,
- uint (*r_tris)[3],
- PolyIndex *r_indices)
+static void polyfill_prepare(PolyFill *pf,
+ const float (*coords)[2],
+ const uint coords_tot,
+ int coords_sign,
+ uint (*r_tris)[3],
+ PolyIndex *r_indices)
{
- /* localize */
- PolyIndex *indices = r_indices;
+ /* localize */
+ PolyIndex *indices = r_indices;
- uint i;
+ uint i;
- /* assign all polyfill members here */
- pf->indices = r_indices;
- pf->coords = coords;
- pf->coords_tot = coords_tot;
+ /* assign all polyfill members here */
+ pf->indices = r_indices;
+ pf->coords = coords;
+ pf->coords_tot = coords_tot;
#ifdef USE_CONVEX_SKIP
- pf->coords_tot_concave = 0;
+ pf->coords_tot_concave = 0;
#endif
- pf->tris = r_tris;
- pf->tris_tot = 0;
+ pf->tris = r_tris;
+ pf->tris_tot = 0;
- if (coords_sign == 0) {
- coords_sign = (cross_poly_v2(coords, coords_tot) >= 0.0f) ? 1 : -1;
- }
- else {
- /* check we're passing in correcty args */
+ if (coords_sign == 0) {
+ coords_sign = (cross_poly_v2(coords, coords_tot) >= 0.0f) ? 1 : -1;
+ }
+ else {
+ /* check we're passing in correcty args */
#ifdef USE_STRICT_ASSERT
-#ifndef NDEBUG
- if (coords_sign == 1) {
- BLI_assert(cross_poly_v2(coords, coords_tot) >= 0.0f);
- }
- else {
- BLI_assert(cross_poly_v2(coords, coords_tot) <= 0.0f);
- }
-#endif
-#endif
- }
-
- if (coords_sign == 1) {
- for (i = 0; i < coords_tot; i++) {
- indices[i].next = &indices[i + 1];
- indices[i].prev = &indices[i - 1];
- indices[i].index = i;
- }
- }
- else {
- /* reversed */
- uint n = coords_tot - 1;
- for (i = 0; i < coords_tot; i++) {
- indices[i].next = &indices[i + 1];
- indices[i].prev = &indices[i - 1];
- indices[i].index = (n - i);
- }
- }
- indices[0].prev = &indices[coords_tot - 1];
- indices[coords_tot - 1].next = &indices[0];
-
- for (i = 0; i < coords_tot; i++) {
- PolyIndex *pi = &indices[i];
- pf_coord_sign_calc(pf, pi);
+# ifndef NDEBUG
+ if (coords_sign == 1) {
+ BLI_assert(cross_poly_v2(coords, coords_tot) >= 0.0f);
+ }
+ else {
+ BLI_assert(cross_poly_v2(coords, coords_tot) <= 0.0f);
+ }
+# endif
+#endif
+ }
+
+ if (coords_sign == 1) {
+ for (i = 0; i < coords_tot; i++) {
+ indices[i].next = &indices[i + 1];
+ indices[i].prev = &indices[i - 1];
+ indices[i].index = i;
+ }
+ }
+ else {
+ /* reversed */
+ uint n = coords_tot - 1;
+ for (i = 0; i < coords_tot; i++) {
+ indices[i].next = &indices[i + 1];
+ indices[i].prev = &indices[i - 1];
+ indices[i].index = (n - i);
+ }
+ }
+ indices[0].prev = &indices[coords_tot - 1];
+ indices[coords_tot - 1].next = &indices[0];
+
+ for (i = 0; i < coords_tot; i++) {
+ PolyIndex *pi = &indices[i];
+ pf_coord_sign_calc(pf, pi);
#ifdef USE_CONVEX_SKIP
- if (pi->sign != CONVEX) {
- pf->coords_tot_concave += 1;
- }
+ if (pi->sign != CONVEX) {
+ pf->coords_tot_concave += 1;
+ }
#endif
- }
+ }
}
-static void polyfill_calc(
- PolyFill *pf)
+static void polyfill_calc(PolyFill *pf)
{
#ifdef USE_KDTREE
-#ifdef USE_CONVEX_SKIP
- if (pf->coords_tot_concave)
-#endif
- {
- kdtree2d_new(&pf->kdtree, pf->coords_tot_concave, pf->coords);
- kdtree2d_init(&pf->kdtree, pf->coords_tot, pf->indices);
- kdtree2d_balance(&pf->kdtree);
- kdtree2d_init_mapping(&pf->kdtree);
- }
-#endif
-
- pf_triangulate(pf);
+# ifdef USE_CONVEX_SKIP
+ if (pf->coords_tot_concave)
+# endif
+ {
+ kdtree2d_new(&pf->kdtree, pf->coords_tot_concave, pf->coords);
+ kdtree2d_init(&pf->kdtree, pf->coords_tot, pf->indices);
+ kdtree2d_balance(&pf->kdtree);
+ kdtree2d_init_mapping(&pf->kdtree);
+ }
+#endif
+
+ pf_triangulate(pf);
}
/**
* A version of #BLI_polyfill_calc that uses a memory arena to avoid re-allocations.
*/
-void BLI_polyfill_calc_arena(
- const float (*coords)[2],
- const uint coords_tot,
- const int coords_sign,
- uint (*r_tris)[3],
+void BLI_polyfill_calc_arena(const float (*coords)[2],
+ const uint coords_tot,
+ const int coords_sign,
+ uint (*r_tris)[3],
- struct MemArena *arena)
+ struct MemArena *arena)
{
- PolyFill pf;
- PolyIndex *indices = BLI_memarena_alloc(arena, sizeof(*indices) * coords_tot);
+ PolyFill pf;
+ PolyIndex *indices = BLI_memarena_alloc(arena, sizeof(*indices) * coords_tot);
#ifdef DEBUG_TIME
- TIMEIT_START(polyfill2d);
+ TIMEIT_START(polyfill2d);
#endif
- polyfill_prepare(
- &pf,
- coords, coords_tot, coords_sign,
- r_tris,
- /* cache */
- indices);
+ polyfill_prepare(&pf,
+ coords,
+ coords_tot,
+ coords_sign,
+ r_tris,
+ /* cache */
+ indices);
#ifdef USE_KDTREE
- if (pf.coords_tot_concave) {
- pf.kdtree.nodes = BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes) * pf.coords_tot_concave);
- pf.kdtree.nodes_map = memset(BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes_map) * coords_tot),
- 0xff, sizeof(*pf.kdtree.nodes_map) * coords_tot);
- }
- else {
- pf.kdtree.totnode = 0;
- }
+ if (pf.coords_tot_concave) {
+ pf.kdtree.nodes = BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes) * pf.coords_tot_concave);
+ pf.kdtree.nodes_map = memset(
+ BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes_map) * coords_tot),
+ 0xff,
+ sizeof(*pf.kdtree.nodes_map) * coords_tot);
+ }
+ else {
+ pf.kdtree.totnode = 0;
+ }
#endif
- polyfill_calc(&pf);
+ polyfill_calc(&pf);
- /* indices are no longer needed,
- * caller can clear arena */
+ /* indices are no longer needed,
+ * caller can clear arena */
#ifdef DEBUG_TIME
- TIMEIT_END(polyfill2d);
+ TIMEIT_END(polyfill2d);
#endif
}
@@ -933,40 +901,41 @@ void BLI_polyfill_calc_arena(
* Indices are guaranteed to be assigned to unique triangles, with valid indices,
* even in the case of degenerate input (self intersecting polygons, zero area ears... etc).
*/
-void BLI_polyfill_calc(
- const float (*coords)[2],
- const uint coords_tot,
- const int coords_sign,
- uint (*r_tris)[3])
+void BLI_polyfill_calc(const float (*coords)[2],
+ const uint coords_tot,
+ const int coords_sign,
+ uint (*r_tris)[3])
{
- PolyFill pf;
- PolyIndex *indices = BLI_array_alloca(indices, coords_tot);
+ PolyFill pf;
+ PolyIndex *indices = BLI_array_alloca(indices, coords_tot);
#ifdef DEBUG_TIME
- TIMEIT_START(polyfill2d);
+ TIMEIT_START(polyfill2d);
#endif
- polyfill_prepare(
- &pf,
- coords, coords_tot, coords_sign,
- r_tris,
- /* cache */
- indices);
+ polyfill_prepare(&pf,
+ coords,
+ coords_tot,
+ coords_sign,
+ r_tris,
+ /* cache */
+ indices);
#ifdef USE_KDTREE
- if (pf.coords_tot_concave) {
- pf.kdtree.nodes = BLI_array_alloca(pf.kdtree.nodes, pf.coords_tot_concave);
- pf.kdtree.nodes_map = memset(BLI_array_alloca(pf.kdtree.nodes_map, coords_tot),
- 0xff, sizeof(*pf.kdtree.nodes_map) * coords_tot);
- }
- else {
- pf.kdtree.totnode = 0;
- }
+ if (pf.coords_tot_concave) {
+ pf.kdtree.nodes = BLI_array_alloca(pf.kdtree.nodes, pf.coords_tot_concave);
+ pf.kdtree.nodes_map = memset(BLI_array_alloca(pf.kdtree.nodes_map, coords_tot),
+ 0xff,
+ sizeof(*pf.kdtree.nodes_map) * coords_tot);
+ }
+ else {
+ pf.kdtree.totnode = 0;
+ }
#endif
- polyfill_calc(&pf);
+ polyfill_calc(&pf);
#ifdef DEBUG_TIME
- TIMEIT_END(polyfill2d);
+ TIMEIT_END(polyfill2d);
#endif
}