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; }
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; }