void display() { int i=0; glClear(GL_COLOR_BUFFER_BIT); buret(); glPushMatrix(); glutTimerFunc(400,update,0); glTranslated(a,b,0.0); dro(); glutPostRedisplay(); glPopMatrix(); glPushMatrix(); glTranslated(c,d,0.0); conical(); scanfill1(75,25,78,22,122,22,125,25); glutPostRedisplay(); glPopMatrix(); scanfill(94,185,106,185,106,111,94,111); scanfill(95,111,107,111,103,90,99,90); scanfill(95,111,103,90,101,80,101,80); sprintf(125,100,"conical"); glColor3f(1.0,1.0,1.0); glRasterPos2i(100,120); glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,"L"); glFlush(); }
void display() { x1=200.0;y1=200.0;x2=100.0,y2=300.0;x3=200.0; y3=400.0;x4=300.0;y4=300.0; glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0,0.0,1.0); glBegin(GL_LINE_LOOP); glVertex2f(x1,y1); glVertex2f(x2,y2);\ glVertex2f(x3,y3); glVertex2f(x4,y4); glEnd(); scanfill(x1,y1,x2,y2,x3,y3,x4,y4); glFlush(); }
void display6() { xo1=200.0;yo1=200.0;x2=100.0;y2=300.0;x3=200.0;y3=400.0;x4=300.0;y4=300.0; glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0,0.0,1.0); glRasterPos2f(50.03,60.57); Write("Close"); glutMouseFunc(OnClick1); if(xo>38&&xo<69&&yo>72&&yo<91) glutHideWindow(); glColor3f(0.0,0.0,1.0); glBegin(GL_LINE_LOOP); glVertex2f(xo1,yo1); glVertex2f(x2,y2); glVertex2f(x3,y3); glVertex2f(x4,y4); glEnd(); scanfill(xo1,yo1,x2,y2,x3,y3,x4,y4); glFlush(); }
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; }
int BLI_edgefill(int mat_nr) { /* - 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 ) */ ListBase tempve, temped; EditVert *eve; EditEdge *eed,*nexted; PolyFill *pflist,*pf; float *minp, *maxp, *v1, *v2, norm[3], len; short a,c,poly=0,ok=0,toggle=0; /* reset variables */ eve= fillvertbase.first; while(eve) { eve->f= 0; eve->xs= 0; eve->h= 0; eve= eve->next; } /* first test vertices if they are in edges */ /* including resetting of flags */ eed= filledgebase.first; while(eed) { eed->f= eed->f1= eed->h= 0; eed->v1->f= 1; eed->v2->f= 1; eed= eed->next; } eve= fillvertbase.first; while(eve) { if(eve->f & 1) { ok=1; break; } eve= eve->next; } if(ok==0) return 0; /* NEW NEW! define projection: with 'best' normal */ /* just use the first three different vertices */ /* THIS PART STILL IS PRETTY WEAK! (ton) */ eve= fillvertbase.last; len= 0.0; v1= eve->co; v2= 0; eve= fillvertbase.first; while(eve) { if(v2) { if( compare_v3v3(v2, eve->co, COMPLIMIT)==0) { len= normal_tri_v3( norm,v1, v2, eve->co); if(len != 0.0) break; } } else if(compare_v3v3(v1, eve->co, COMPLIMIT)==0) { v2= eve->co; } eve= eve->next; } if(len==0.0) return 0; /* no fill possible */ norm[0]= fabs(norm[0]); norm[1]= fabs(norm[1]); norm[2]= fabs(norm[2]); if(norm[2]>=norm[0] && norm[2]>=norm[1]) { cox= 0; coy= 1; } else if(norm[1]>=norm[0] && norm[1]>=norm[2]) { cox= 0; coy= 2; } else { cox= 1; coy= 2; } /* STEP 1: COUNT POLYS */ eve= fillvertbase.first; while(eve) { /* get first vertex with no poly number */ if(eve->xs==0) { poly++; /* now a sortof select connected */ ok= 1; eve->xs= poly; while(ok) { ok= 0; toggle++; if(toggle & 1) eed= filledgebase.first; else eed= filledgebase.last; while(eed) { if(eed->v1->xs==0 && eed->v2->xs==poly) { eed->v1->xs= poly; eed->f1= poly; ok= 1; } else if(eed->v2->xs==0 && eed->v1->xs==poly) { eed->v2->xs= poly; eed->f1= poly; ok= 1; } else if(eed->f1==0) { if(eed->v1->xs==poly && eed->v2->xs==poly) { eed->f1= poly; ok= 1; } } if(toggle & 1) eed= eed->next; else eed= eed->prev; } } } eve= eve->next; } /* printf("amount of poly's: %d\n",poly); */ /* STEP 2: remove loose edges and strings of edges */ eed= filledgebase.first; while(eed) { if(eed->v1->h++ >250) break; if(eed->v2->h++ >250) break; eed= eed->next; } if(eed) { /* otherwise it's impossible to be sure you can clear vertices */ callLocalErrorCallBack("No vertices with 250 edges allowed!"); return 0; } /* does it only for vertices with ->h==1 */ testvertexnearedge(); ok= 1; while(ok) { ok= 0; toggle++; if(toggle & 1) eed= filledgebase.first; else eed= filledgebase.last; while(eed) { if(toggle & 1) nexted= eed->next; else nexted= eed->prev; if(eed->v1->h==1) { eed->v2->h--; BLI_remlink(&fillvertbase,eed->v1); BLI_remlink(&filledgebase,eed); ok= 1; } else if(eed->v2->h==1) { eed->v1->h--; BLI_remlink(&fillvertbase,eed->v2); BLI_remlink(&filledgebase,eed); ok= 1; } eed= nexted; } } if(filledgebase.first==0) { /* printf("All edges removed\n"); */ return 0; } /* CURRENT STATUS: - eve->f :1= availalble in edges - eve->xs :polynumber - eve->h :amount of edges connected to vertex - eve->tmp.v :store! original vertex number - eed->f : - eed->f1 :poly number */ /* STEP 3: MAKE POLYFILL STRUCT */ pflist= (PolyFill *)MEM_callocN(poly*sizeof(PolyFill),"edgefill"); pf= pflist; for(a=1;a<=poly;a++) { pf->nr= a; pf->min[0]=pf->min[1]=pf->min[2]= 1.0e20; pf->max[0]=pf->max[1]=pf->max[2]= -1.0e20; pf++; } eed= filledgebase.first; while(eed) { pflist[eed->f1-1].edges++; eed= eed->next; } eve= fillvertbase.first; while(eve) { pflist[eve->xs-1].verts++; minp= pflist[eve->xs-1].min; maxp= pflist[eve->xs-1].max; minp[cox]= (minp[cox])<(eve->co[cox]) ? (minp[cox]) : (eve->co[cox]); minp[coy]= (minp[coy])<(eve->co[coy]) ? (minp[coy]) : (eve->co[coy]); maxp[cox]= (maxp[cox])>(eve->co[cox]) ? (maxp[cox]) : (eve->co[cox]); maxp[coy]= (maxp[coy])>(eve->co[coy]) ? (maxp[coy]) : (eve->co[coy]); if(eve->h>2) pflist[eve->xs-1].f= 1; eve= eve->next; } /* 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(poly>1) { short *polycache, *pc; /* so, sort first */ qsort(pflist, poly, sizeof(PolyFill), vergpoly); /*pf= pflist; for(a=1;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++; }*/ polycache= pc= MEM_callocN(sizeof(short)*poly, "polycache"); pf= pflist; for(a=0; a<poly; a++, pf++) { for(c=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[cox] < (pflist+c)->min[cox]) break; */ } while(pc!=polycache) { pc--; mergepolysSimp(pf, pflist+ *pc); } } MEM_freeN(polycache); } /* printf("after merge\n"); pf= pflist; for(a=1;a<=poly;a++) { printf("poly:%d edges:%d verts:%d flag: %d\n",a,pf->edges,pf->verts,pf->f); pf++; } */ /* STEP 5: MAKE TRIANGLES */ tempve.first= fillvertbase.first; tempve.last= fillvertbase.last; temped.first= filledgebase.first; temped.last= filledgebase.last; fillvertbase.first=fillvertbase.last= 0; filledgebase.first=filledgebase.last= 0; pf= pflist; for(a=0;a<poly;a++) { if(pf->edges>1) { splitlist(&tempve,&temped,pf->nr); scanfill(pf, mat_nr); } pf++; } BLI_movelisttolist(&fillvertbase,&tempve); BLI_movelisttolist(&filledgebase,&temped); /* FREE */ MEM_freeN(pflist); return 1; }
int BLI_edgefill_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedup, 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, *nexted; PolyFill *pflist, *pf; float *min_xy_p, *max_xy_p; short a, c, poly = 0, ok = 0, toggle = 0; int totfaces = 0; /* total faces added */ int co_x, co_y; /* reset variables */ eve = sf_ctx->fillvertbase.first; a = 0; while (eve) { eve->f = 0; eve->poly_nr = 0; eve->h = 0; eve = eve->next; a += 1; } if (do_quad_tri_speedup && (a == 3)) { eve = sf_ctx->fillvertbase.first; addfillface(sf_ctx, eve, eve->next, eve->next->next); return 1; } else if (do_quad_tri_speedup && (a == 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; } /* first test vertices if they are in edges */ /* including resetting of flags */ eed = sf_ctx->filledgebase.first; while (eed) { eed->poly_nr = 0; eed->v1->f = SF_VERT_UNKNOWN; eed->v2->f = SF_VERT_UNKNOWN; eed = eed->next; } eve = sf_ctx->fillvertbase.first; while (eve) { if (eve->f & SF_VERT_UNKNOWN) { ok = 1; break; } eve = eve->next; } if (ok == 0) { 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 */ 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(&co_x, &co_y, n); } /* STEP 1: COUNT POLYS */ eve = sf_ctx->fillvertbase.first; while (eve) { eve->xy[0] = eve->co[co_x]; eve->xy[1] = eve->co[co_y]; /* get first vertex with no poly number */ if (eve->poly_nr == 0) { poly++; /* now a sort of select connected */ ok = 1; eve->poly_nr = poly; while (ok) { ok = 0; toggle++; if (toggle & 1) eed = sf_ctx->filledgebase.first; else eed = sf_ctx->filledgebase.last; while (eed) { if (eed->v1->poly_nr == 0 && eed->v2->poly_nr == poly) { eed->v1->poly_nr = poly; eed->poly_nr = poly; ok = 1; } else if (eed->v2->poly_nr == 0 && eed->v1->poly_nr == poly) { eed->v2->poly_nr = poly; eed->poly_nr = poly; ok = 1; } else if (eed->poly_nr == 0) { if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) { eed->poly_nr = poly; ok = 1; } } if (toggle & 1) eed = eed->next; else eed = eed->prev; } } } eve = eve->next; } /* printf("amount of poly's: %d\n",poly); */ /* STEP 2: remove loose edges and strings of edges */ eed = sf_ctx->filledgebase.first; while (eed) { if (eed->v1->h++ > 250) break; if (eed->v2->h++ > 250) break; eed = eed->next; } if (eed) { /* otherwise it's impossible to be sure you can clear vertices */ callLocalErrorCallBack("No vertices with 250 edges allowed!"); return 0; } /* does it only for vertices with ->h==1 */ testvertexnearedge(sf_ctx); ok = 1; while (ok) { ok = 0; toggle++; if (toggle & 1) eed = sf_ctx->filledgebase.first; else eed = sf_ctx->filledgebase.last; while (eed) { if (toggle & 1) nexted = eed->next; else nexted = eed->prev; if (eed->v1->h == 1) { eed->v2->h--; BLI_remlink(&sf_ctx->fillvertbase, eed->v1); BLI_remlink(&sf_ctx->filledgebase, eed); ok = 1; } else if (eed->v2->h == 1) { eed->v1->h--; BLI_remlink(&sf_ctx->fillvertbase, eed->v2); BLI_remlink(&sf_ctx->filledgebase, eed); ok = 1; } eed = nexted; } } if (sf_ctx->filledgebase.first == 0) { /* printf("All edges removed\n"); */ return 0; } /* CURRENT STATUS: * - eve->f :1= availalble in edges * - eve->xs :polynumber * - eve->h :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 = (PolyFill *)MEM_callocN(poly * sizeof(PolyFill), "edgefill"); pf = pflist; for (a = 1; a <= poly; a++) { pf->nr = a; pf->min_xy[0] = pf->min_xy[1] = 1.0e20; pf->max_xy[0] = pf->max_xy[1] = -1.0e20; pf++; } eed = sf_ctx->filledgebase.first; while (eed) { pflist[eed->poly_nr - 1].edges++; eed = eed->next; } eve = sf_ctx->fillvertbase.first; while (eve) { pflist[eve->poly_nr - 1].verts++; min_xy_p = pflist[eve->poly_nr - 1].min_xy; max_xy_p = pflist[eve->poly_nr - 1].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->h > 2) pflist[eve->poly_nr - 1].f = 1; eve = eve->next; } /* 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 (poly > 1) { short *polycache, *pc; /* so, sort first */ qsort(pflist, poly, sizeof(PolyFill), vergpoly); #if 0 pf = pflist; for (a = 1; 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(short) * poly, "polycache"); pf = pflist; for (a = 0; a < poly; a++, pf++) { for (c = 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 = 1; 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; sf_ctx->fillvertbase.first = sf_ctx->fillvertbase.last = NULL; sf_ctx->filledgebase.first = sf_ctx->filledgebase.last = NULL; pf = pflist; for (a = 0; a < poly; a++) { if (pf->edges > 1) { splitlist(sf_ctx, &tempve, &temped, pf->nr); totfaces += scanfill(sf_ctx, pf); } pf++; } BLI_movelisttolist(&sf_ctx->fillvertbase, &tempve); BLI_movelisttolist(&sf_ctx->filledgebase, &temped); /* FREE */ MEM_freeN(pflist); return totfaces; }