// Starting with a valid triangulation, uses the Edge Flip algorithm to // refine the triangulation into a Constrained Delaunay Triangulation. void tessMeshRefineDelaunay( TESSmesh *mesh, TESSalloc *alloc ) { // At this point, we have a valid, but not optimal, triangulation. // We refine the triangulation using the Edge Flip algorithm // // 1) Find all internal edges // 2) Mark all dual edges // 3) insert all dual edges into a queue TESSface *f; EdgeStack stack; TESShalfEdge *e; int maxFaces = 0, maxIter = 0, iter = 0; stackInit(&stack, alloc); for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { if ( f->inside) { e = f->anEdge; do { e->mark = EdgeIsInternal(e); // Mark internal edges if (e->mark && !e->Sym->mark) stackPush(&stack, e); // Insert into queue e = e->Lnext; } while (e != f->anEdge); maxFaces++; } } // The algorithm should converge on O(n^2), since the predicate is not robust, // we'll save guard against infinite loop. maxIter = maxFaces * maxFaces; // Pop stack until we find a reversed edge // Flip the reversed edge, and insert any of the four opposite edges // which are internal and not already in the stack (!marked) while (!stackEmpty(&stack) && iter < maxIter) { e = stackPop(&stack); e->mark = e->Sym->mark = 0; if (!tesedgeIsLocallyDelaunay(e)) { TESShalfEdge *edges[4]; int i; tessMeshFlipEdge(mesh, e); // for each opposite edge edges[0] = e->Lnext; edges[1] = e->Lprev; edges[2] = e->Sym->Lnext; edges[3] = e->Sym->Lprev; for (i = 0; i < 4; i++) { if (!edges[i]->mark && EdgeIsInternal(edges[i])) { edges[i]->mark = edges[i]->Sym->mark = 1; stackPush(&stack, edges[i]); } } } iter++; } stackDelete(&stack); }
/* Starting with a valid triangulation, uses the Edge Flip algorithm to refine the triangulation into a Constrained Delaunay Triangulation. */ int tessMeshRefineDelaunay( TESSmesh *mesh, TESSalloc *alloc ) { /* At this point, we have a valid, but not optimal, triangulation. We refine the triangulation using the Edge Flip algorithm */ /* 1) Find all internal edges 2) Mark all dual edges 3) insert all dual edges into a queue */ TESSface *f; EdgeStack stack; TESShalfEdge *e; TESShalfEdge *edges[4]; stackInit(&stack, alloc); for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { if ( f->inside) { e = f->anEdge; do { e->mark = EdgeIsInternal(e); /* Mark internal edges */ if (e->mark && !e->Sym->mark) stackPush(&stack, e); /* Insert into queue */ e = e->Lnext; } while (e != f->anEdge); } } // Pop stack until we find a reversed edge // Flip the reversed edge, and insert any of the four opposite edges // which are internal and not already in the stack (!marked) while (!stackEmpty(&stack)) { e = stackPop(&stack); e->mark = e->Sym->mark = 0; if (!tesedgeIsLocallyDelaunay(e)) { int i; tessMeshFlipEdge(mesh, e); // for each opposite edge edges[0] = e->Lnext; edges[1] = e->Lprev; edges[2] = e->Sym->Lnext; edges[3] = e->Sym->Lprev; for (i=0;i<3;i++) { if (!edges[i]->mark && EdgeIsInternal(edges[i])) { edges[i]->mark = edges[i]->Sym->mark = 1; stackPush(&stack, edges[i]); } } } } stackDelete(&stack); return 1; }