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; }
/** * \return CONCAVE, TANGENTIAL or CONVEX */ static void pf_coord_sign_calc(PolyFill *pf, PolyIndex *pi) { /* localize */ const float(*coords)[2] = pf->coords; pi->sign = span_tri_v2_sign(coords[pi->prev->index], coords[pi->index], coords[pi->next->index]); }
/** * \return CONCAVE, TANGENTIAL or CONVEX */ static eSign pf_coord_sign_calc(PolyFill *pf, unsigned int index) { /* localize */ unsigned int *indices = pf->indices; const float (*coords)[2] = pf->coords; return span_tri_v2_sign( coords[indices[pf_index_prev(pf, index)]], coords[indices[index]], coords[indices[pf_index_next(pf, index)]]); }
static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip) { /* localize */ PolyIndex *pi_curr; const float (*coords)[2] = pf->coords; #ifndef USE_KDTREE const float *v1, *v2, *v3; #endif #if defined(USE_CONVEX_SKIP) && !defined(USE_KDTREE) unsigned int coords_tot_concave_checked = 0; #endif #ifdef USE_CONVEX_SKIP #ifdef USE_CONVEX_SKIP_TEST /* check if counting is wrong */ { unsigned int coords_tot_concave_test = 0; unsigned int i = pf->coords_tot; while (i--) { if (coords_sign[indices[i]] != CONVEX) { coords_tot_concave_test += 1; } } 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 unsigned int 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; } } (void)pi_curr; (void)coords; #else 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 bool pf_ear_tip_check(PolyFill *pf, const unsigned int index_ear_tip) { /* localize */ const unsigned int *indices = pf->indices; const float (*coords)[2] = pf->coords; const eSign *coords_sign = pf->coords_sign; unsigned int i_prev, i_curr, i_next; const float *v1, *v2, *v3; #ifdef USE_CONVEX_SKIP unsigned int coords_tot_concave_checked = 0; #endif #ifdef USE_CONVEX_SKIP #ifdef USE_CONVEX_SKIP_TEST /* check if counting is wrong */ { unsigned int coords_tot_concave_test = 0; unsigned int i = pf->coords_tot; while (i--) { if (coords_sign[i] != CONVEX) { coords_tot_concave_test += 1; } } 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(coords_sign[index_ear_tip] == CONCAVE)) { return false; } i_prev = pf_index_prev(pf, index_ear_tip); i_next = pf_index_next(pf, index_ear_tip); v1 = coords[indices[i_prev]]; v2 = coords[indices[index_ear_tip]]; v3 = coords[indices[i_next]]; /* 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 (i_curr = pf_index_next(pf, i_next); i_curr != i_prev; i_curr = pf_index_next(pf, i_curr)) { /* 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 (coords_sign[i_curr] != CONVEX) { const float *v = coords[indices[i_curr]]; /* 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. */ if ((span_tri_v2_sign(v1, v2, v) != CONCAVE) && (span_tri_v2_sign(v2, v3, v) != CONCAVE) && (span_tri_v2_sign(v3, v1, v) != CONCAVE)) { return false; } #ifdef USE_CONVEX_SKIP coords_tot_concave_checked += 1; if (coords_tot_concave_checked == pf->coords_tot_concave) { break; } #endif } } return true; }