Ejemplo n.º 1
0
unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3])
{
	/*
	 * - fill works with its own lists, so create that first (no faces!)
	 * - for vertices, put in ->tmp.v the old pointer
	 * - struct elements xs en ys are not used here: don't hide stuff in it
	 * - edge flag ->f becomes 2 when it's a new edge
	 * - mode: & 1 is check for crossings, then create edges (TO DO )
	 * - returns number of triangle faces added.
	 */
	ListBase tempve, temped;
	ScanFillVert *eve;
	ScanFillEdge *eed, *eed_next;
	PolyFill *pflist, *pf;
	float *min_xy_p, *max_xy_p;
	unsigned int totfaces = 0;  /* total faces added */
	unsigned short a, c, poly = 0;
	bool ok;
	float mat_2d[3][3];

	BLI_assert(!nor_proj || len_squared_v3(nor_proj) > FLT_EPSILON);

#ifdef DEBUG
	for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
		/* these values used to be set,
		 * however they should always be zero'd so check instead */
		BLI_assert(eve->f == 0);
		BLI_assert(sf_ctx->poly_nr || eve->poly_nr == 0);
		BLI_assert(eve->edge_tot == 0);
	}
#endif

#if 0
	if (flag & BLI_SCANFILL_CALC_QUADTRI_FASTPATH) {
		const int totverts = BLI_countlist(&sf_ctx->fillvertbase);

		if (totverts == 3) {
			eve = sf_ctx->fillvertbase.first;

			addfillface(sf_ctx, eve, eve->next, eve->next->next);
			return 1;
		}
		else if (totverts == 4) {
			float vec1[3], vec2[3];

			eve = sf_ctx->fillvertbase.first;
			/* no need to check 'eve->next->next->next' is valid, already counted */
			/* use shortest diagonal for quad */
			sub_v3_v3v3(vec1, eve->co, eve->next->next->co);
			sub_v3_v3v3(vec2, eve->next->co, eve->next->next->next->co);

			if (dot_v3v3(vec1, vec1) < dot_v3v3(vec2, vec2)) {
				addfillface(sf_ctx, eve, eve->next, eve->next->next);
				addfillface(sf_ctx, eve->next->next, eve->next->next->next, eve);
			}
			else {
				addfillface(sf_ctx, eve->next, eve->next->next, eve->next->next->next);
				addfillface(sf_ctx, eve->next->next->next, eve, eve->next);
			}
			return 2;
		}
	}
#endif

	/* first test vertices if they are in edges */
	/* including resetting of flags */
	for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
		BLI_assert(sf_ctx->poly_nr != SF_POLY_UNSET || eed->poly_nr == SF_POLY_UNSET);
		eed->v1->f = SF_VERT_AVAILABLE;
		eed->v2->f = SF_VERT_AVAILABLE;
	}

	for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
		if (eve->f == SF_VERT_AVAILABLE) {
			break;
		}
	}

	if (UNLIKELY(eve == NULL)) {
		return 0;
	}
	else {
		float n[3];

		if (nor_proj) {
			copy_v3_v3(n, nor_proj);
		}
		else {
			/* define projection: with 'best' normal */
			/* Newell's Method */
			/* Similar code used elsewhere, but this checks for double ups
			 * which historically this function supports so better not change */

			/* warning: this only gives stable direction with single polygons,
			 * ideally we'd calcualte connectivity and calculate each polys normal, see T41047 */
			const float *v_prev;

			zero_v3(n);
			eve = sf_ctx->fillvertbase.last;
			v_prev = eve->co;

			for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
				if (LIKELY(!compare_v3v3(v_prev, eve->co, SF_EPSILON))) {
					add_newell_cross_v3_v3v3(n, v_prev, eve->co);
					v_prev = eve->co;
				}
			}
		}

		if (UNLIKELY(normalize_v3(n) == 0.0f)) {
			return 0;
		}

		axis_dominant_v3_to_m3(mat_2d, n);
	}


	/* STEP 1: COUNT POLYS */
	if (sf_ctx->poly_nr != SF_POLY_UNSET) {
		poly = (unsigned short)(sf_ctx->poly_nr + 1);
		sf_ctx->poly_nr = SF_POLY_UNSET;
	}

	if (flag & BLI_SCANFILL_CALC_POLYS && (poly == 0)) {
		for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
			mul_v2_m3v3(eve->xy, mat_2d, eve->co);

			/* get first vertex with no poly number */
			if (eve->poly_nr == SF_POLY_UNSET) {
				unsigned int toggle = 0;
				/* now a sort of select connected */
				ok = true;
				eve->poly_nr = poly;

				while (ok) {

					ok = false;

					toggle++;
					for (eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last;
					     eed;
					     eed = (toggle & 1) ? eed->next : eed->prev)
					{
						if (eed->v1->poly_nr == SF_POLY_UNSET && eed->v2->poly_nr == poly) {
							eed->v1->poly_nr = poly;
							eed->poly_nr = poly;
							ok = true;
						}
						else if (eed->v2->poly_nr == SF_POLY_UNSET && eed->v1->poly_nr == poly) {
							eed->v2->poly_nr = poly;
							eed->poly_nr = poly;
							ok = true;
						}
						else if (eed->poly_nr == SF_POLY_UNSET) {
							if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) {
								eed->poly_nr = poly;
								ok = true;
							}
						}
					}
				}

				poly++;
			}
		}
		/* printf("amount of poly's: %d\n", poly); */
	}
	else if (poly) {
		/* we pre-calculated poly_nr */
		for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
			mul_v2_m3v3(eve->xy, mat_2d, eve->co);
		}
	}
	else {
		poly = 1;

		for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
			mul_v2_m3v3(eve->xy, mat_2d, eve->co);
			eve->poly_nr = 0;
		}

		for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
			eed->poly_nr = 0;
		}
	}

	/* STEP 2: remove loose edges and strings of edges */
	if (flag & BLI_SCANFILL_CALC_LOOSE) {
		unsigned int toggle = 0;
		for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
			if (eed->v1->edge_tot++ > 250) break;
			if (eed->v2->edge_tot++ > 250) break;
		}
		if (eed) {
			/* otherwise it's impossible to be sure you can clear vertices */
#ifdef DEBUG
			printf("No vertices with 250 edges allowed!\n");
#endif
			return 0;
		}

		/* does it only for vertices with (->edge_tot == 1) */
		testvertexnearedge(sf_ctx);

		ok = true;
		while (ok) {
			ok = false;

			toggle++;
			for (eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last;
			     eed;
			     eed = eed_next)
			{
				eed_next = (toggle & 1) ? eed->next : eed->prev;
				if (eed->v1->edge_tot == 1) {
					eed->v2->edge_tot--;
					BLI_remlink(&sf_ctx->fillvertbase, eed->v1);
					BLI_remlink(&sf_ctx->filledgebase, eed);
					ok = true;
				}
				else if (eed->v2->edge_tot == 1) {
					eed->v1->edge_tot--;
					BLI_remlink(&sf_ctx->fillvertbase, eed->v2);
					BLI_remlink(&sf_ctx->filledgebase, eed);
					ok = true;
				}
			}
		}
		if (BLI_listbase_is_empty(&sf_ctx->filledgebase)) {
			/* printf("All edges removed\n"); */
			return 0;
		}
	}
	else {
		/* skip checks for loose edges */
		for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
			eed->v1->edge_tot++;
			eed->v2->edge_tot++;
		}
#ifdef DEBUG
		/* ensure we're right! */
		for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
			BLI_assert(eed->v1->edge_tot != 1);
			BLI_assert(eed->v2->edge_tot != 1);
		}
#endif
	}


	/* CURRENT STATUS:
	 * - eve->f        :1 = available in edges
	 * - eve->poly_nr  :polynumber
	 * - eve->edge_tot :amount of edges connected to vertex
	 * - eve->tmp.v    :store! original vertex number
	 * 
	 * - eed->f        :1 = boundary edge (optionally set by caller)
	 * - eed->poly_nr  :poly number
	 */


	/* STEP 3: MAKE POLYFILL STRUCT */
	pflist = MEM_mallocN(sizeof(*pflist) * (size_t)poly, "edgefill");
	pf = pflist;
	for (a = 0; a < poly; a++) {
		pf->edges = pf->verts = 0;
		pf->min_xy[0] = pf->min_xy[1] =  1.0e20f;
		pf->max_xy[0] = pf->max_xy[1] = -1.0e20f;
		pf->f = SF_POLY_NEW;
		pf->nr = a;
		pf++;
	}
	for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
		pflist[eed->poly_nr].edges++;
	}

	for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
		pflist[eve->poly_nr].verts++;
		min_xy_p = pflist[eve->poly_nr].min_xy;
		max_xy_p = pflist[eve->poly_nr].max_xy;

		min_xy_p[0] = (min_xy_p[0]) < (eve->xy[0]) ? (min_xy_p[0]) : (eve->xy[0]);
		min_xy_p[1] = (min_xy_p[1]) < (eve->xy[1]) ? (min_xy_p[1]) : (eve->xy[1]);
		max_xy_p[0] = (max_xy_p[0]) > (eve->xy[0]) ? (max_xy_p[0]) : (eve->xy[0]);
		max_xy_p[1] = (max_xy_p[1]) > (eve->xy[1]) ? (max_xy_p[1]) : (eve->xy[1]);
		if (eve->edge_tot > 2) {
			pflist[eve->poly_nr].f = SF_POLY_VALID;
		}
	}

	/* STEP 4: FIND HOLES OR BOUNDS, JOIN THEM
	 *  ( bounds just to divide it in pieces for optimization, 
	 *    the edgefill itself has good auto-hole detection)
	 * WATCH IT: ONLY WORKS WITH SORTED POLYS!!! */
	
	if ((flag & BLI_SCANFILL_CALC_HOLES) && (poly > 1)) {
		unsigned short *polycache, *pc;

		/* so, sort first */
		qsort(pflist, (size_t)poly, sizeof(PolyFill), vergpoly);

#if 0
		pf = pflist;
		for (a = 0; a < poly; a++) {
			printf("poly:%d edges:%d verts:%d flag: %d\n", a, pf->edges, pf->verts, pf->f);
			PRINT2(f, f, pf->min[0], pf->min[1]);
			pf++;
		}
#endif

		polycache = pc = MEM_callocN(sizeof(*polycache) * (size_t)poly, "polycache");
		pf = pflist;
		for (a = 0; a < poly; a++, pf++) {
			for (c = (unsigned short)(a + 1); c < poly; c++) {
				
				/* if 'a' inside 'c': join (bbox too)
				 * Careful: 'a' can also be inside another poly.
				 */
				if (boundisect(pf, pflist + c)) {
					*pc = c;
					pc++;
				}
				/* only for optimize! */
				/* else if (pf->max_xy[0] < (pflist+c)->min[cox]) break; */
				
			}
			while (pc != polycache) {
				pc--;
				mergepolysSimp(sf_ctx, pf, pflist + *pc);
			}
		}
		MEM_freeN(polycache);
	}

#if 0
	printf("after merge\n");
	pf = pflist;
	for (a = 0; a < poly; a++) {
		printf("poly:%d edges:%d verts:%d flag: %d\n", a, pf->edges, pf->verts, pf->f);
		pf++;
	}
#endif

	/* STEP 5: MAKE TRIANGLES */

	tempve.first = sf_ctx->fillvertbase.first;
	tempve.last = sf_ctx->fillvertbase.last;
	temped.first = sf_ctx->filledgebase.first;
	temped.last = sf_ctx->filledgebase.last;
	BLI_listbase_clear(&sf_ctx->fillvertbase);
	BLI_listbase_clear(&sf_ctx->filledgebase);

	pf = pflist;
	for (a = 0; a < poly; a++) {
		if (pf->edges > 1) {
			splitlist(sf_ctx, &tempve, &temped, pf->nr);
			totfaces += scanfill(sf_ctx, pf, flag);
		}
		pf++;
	}
	BLI_movelisttolist(&sf_ctx->fillvertbase, &tempve);
	BLI_movelisttolist(&sf_ctx->filledgebase, &temped);

	/* FREE */

	MEM_freeN(pflist);

	return totfaces;
}
Ejemplo n.º 2
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;
}