Example #1
0
/**
 * Measure the 'area' of each channel and combine to use as a cost for this samples removal.
 */
static float color_sample_remove_cost(const struct ColorResampleElem *c)
{
	if (c->next == NULL || c->prev == NULL) {
		return -1.0f;
	}
	float area = 0.0f;
#if 0
	float xy_prev[2], xy_curr[2], xy_next[2];
	xy_prev[0] = c->prev->pos;
	xy_curr[0] = c->pos;
	xy_next[0] = c->next->pos;
	for (int i = 0; i < 4; i++) {
		xy_prev[1] = c->prev->rgba[i];
		xy_curr[1] = c->rgba[i];
		xy_next[1] = c->next->rgba[i];
		area += fabsf(cross_tri_v2(xy_prev, xy_curr, xy_next));
	}
#else
	/* Above logic, optimized (p: previous, c: current, n: next). */
	const float xpc = c->prev->pos - c->pos;
	const float xnc = c->next->pos - c->pos;
	for (int i = 0; i < 4; i++) {
		const float ycn = c->rgba[i] - c->next->rgba[i];
		const float ypc = c->prev->rgba[i] - c->rgba[i];
		area += fabsf((xpc * ycn) + (ypc * xnc));
	}
#endif
	return area;
}
/**
 * Assuming we have 2 triangles sharing an edge (2 - 4),
 * check if the edge running from (1 - 3) gives better results.
 *
 * \return (negative number means the edge can be rotated, lager == better).
 */
float BLI_polyfill_beautify_quad_rotate_calc(
    const float v1[2], const float v2[2], const float v3[2], const float v4[2])
{
    /* not a loop (only to be able to break out) */
    do {
        bool is_zero_a, is_zero_b;

        const float area_2x_234 = cross_tri_v2(v2, v3, v4);
        const float area_2x_241 = cross_tri_v2(v2, v4, v1);

        const float area_2x_123 = cross_tri_v2(v1, v2, v3);
        const float area_2x_134 = cross_tri_v2(v1, v3, v4);

        {
            BLI_assert((ELEM(v1, v2, v3, v4) == false) &&
                       (ELEM(v2, v1, v3, v4) == false) &&
                       (ELEM(v3, v1, v2, v4) == false) &&
                       (ELEM(v4, v1, v2, v3) == false));

            is_zero_a = (fabsf(area_2x_234) <= FLT_EPSILON);
            is_zero_b = (fabsf(area_2x_241) <= FLT_EPSILON);

            if (is_zero_a && is_zero_b) {
                break;
            }
        }

        /* one of the tri's was degenerate, check we're not rotating
         * into a different degenerate shape or flipping the face */
        if ((fabsf(area_2x_123) <= FLT_EPSILON) || (fabsf(area_2x_134) <= FLT_EPSILON)) {
            /* one of the new rotations is degenerate */
            break;
        }

        if ((area_2x_123 >= 0.0f) != (area_2x_134 >= 0.0f)) {
            /* rotation would cause flipping */
            break;
        }

        {
            /* testing rule: the area divided by the perimeter,
             * check if (1-3) beats the existing (2-4) edge rotation */
            float area_a, area_b;
            float prim_a, prim_b;
            float fac_24, fac_13;

            float len_12, len_23, len_34, len_41, len_24, len_13;

            /* edges around the quad */
            len_12 = len_v2v2(v1, v2);
            len_23 = len_v2v2(v2, v3);
            len_34 = len_v2v2(v3, v4);
            len_41 = len_v2v2(v4, v1);
            /* edges crossing the quad interior */
            len_13 = len_v2v2(v1, v3);
            len_24 = len_v2v2(v2, v4);

            /* note, area is in fact (area * 2),
             * but in this case its OK, since we're comparing ratios */

            /* edge (2-4), current state */
            area_a = fabsf(area_2x_234);
            area_b = fabsf(area_2x_241);
            prim_a = len_23 + len_34 + len_24;
            prim_b = len_41 + len_12 + len_24;
            fac_24 = (area_a / prim_a) + (area_b / prim_b);

            /* edge (1-3), new state */
            area_a = fabsf(area_2x_123);
            area_b = fabsf(area_2x_134);
            prim_a = len_12 + len_23 + len_13;
            prim_b = len_34 + len_41 + len_13;
            fac_13 = (area_a / prim_a) + (area_b / prim_b);

            /* negative number if (1-3) is an improved state */
            return fac_24 - fac_13;
        }
    } while (false);

    return FLT_MAX;
}
Example #3
0
static float bm_edge_calc_rotate_beauty__area(
        const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
	/* not a loop (only to be able to break out) */
	do {
		float v1_xy[2], v2_xy[2], v3_xy[2], v4_xy[2];

		/* first get the 2d values */
		{
			const float eps = 1e-5;
			float no_a[3], no_b[3];
			float no[3];
			float axis_mat[3][3];
			float no_scale;
			cross_tri_v3(no_a, v2, v3, v4);
			cross_tri_v3(no_b, v2, v4, v1);

			// printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
			BLI_assert((ELEM(v1, v2, v3, v4) == false) &&
			           (ELEM(v2, v1, v3, v4) == false) &&
			           (ELEM(v3, v1, v2, v4) == false) &&
			           (ELEM(v4, v1, v2, v3) == false));

			add_v3_v3v3(no, no_a, no_b);
			if (UNLIKELY((no_scale = normalize_v3(no)) == 0.0f)) {
				break;
			}

			axis_dominant_v3_to_m3(axis_mat, no);
			mul_v2_m3v3(v1_xy, axis_mat, v1);
			mul_v2_m3v3(v2_xy, axis_mat, v2);
			mul_v2_m3v3(v3_xy, axis_mat, v3);
			mul_v2_m3v3(v4_xy, axis_mat, v4);

			/**
			 * Check if input faces are already flipped.
			 * Logic for 'signum_i' addition is:
			 *
			 * Accept:
			 * - (1, 1) or (-1, -1): same side (common case).
			 * - (-1/1, 0): one degenerate, OK since we may rotate into a valid state.
			 *
			 * Ignore:
			 * - (-1, 1): opposite winding, ignore.
			 * - ( 0, 0): both degenerate, ignore.
			 *
			 * \note The cross product is divided by 'no_scale'
			 * so the rotation calculation is scale independent.
			 */
			if (!(signum_i_ex(cross_tri_v2(v2_xy, v3_xy, v4_xy) / no_scale, eps) +
			      signum_i_ex(cross_tri_v2(v2_xy, v4_xy, v1_xy) / no_scale, eps)))
			{
				break;
			}
		}

		/**
		 * Important to lock degenerate here,
		 * since the triangle pars will be projected into different 2D spaces.
		 * Allowing to rotate out of a degenerate state can flip the faces (when performed iteratively).
		 */
		return BLI_polyfill_beautify_quad_rotate_calc_ex(v1_xy, v2_xy, v3_xy, v4_xy, true);
	} while (false);

	return FLT_MAX;
}