示例#1
0
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;
}
示例#2
0
/**
 * \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]);
}
示例#3
0
/**
 * \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)]]);
}
示例#4
0
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;
}
示例#5
0
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;
}