From 86b60318269ddf3bfd978a623b293098f1466265 Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Sat, 6 Jun 2009 07:34:48 +0000 Subject: [PATCH] *** empty log message *** --- contrib/Tetgen/constrain.cxx | 21 +-- contrib/Tetgen/refine.cxx | 243 +++++++++++++++++++++++++++++++++++ 2 files changed, 255 insertions(+), 9 deletions(-) create mode 100644 contrib/Tetgen/refine.cxx diff --git a/contrib/Tetgen/constrain.cxx b/contrib/Tetgen/constrain.cxx index b2e175540f..2bdd61a326 100644 --- a/contrib/Tetgen/constrain.cxx +++ b/contrib/Tetgen/constrain.cxx @@ -807,8 +807,12 @@ void tetgenmesh::getsegmentsplitpoint2(face* sseg, point refpt, REAL* vt) } /////////////////////////////////////////////////////////////////////////////// -// getsegmentsplitpoint3() Calculate a split point in the given segment. -// This routine does not check far origin and far dest. +// // +// getsegmentsplitpoint3() Calculate a split point in the given segment. // +// // +// This routine does not check far origin and far dest. // +// // +/////////////////////////////////////////////////////////////////////////////// void tetgenmesh::getsegmentsplitpoint3(face* sseg, point refpt, REAL* vt) { @@ -837,7 +841,8 @@ void tetgenmesh::getsegmentsplitpoint3(face* sseg, point refpt, REAL* vt) if (getpointtype(ei) == RIDGEVERTEX) { if (getpointtype(ej) == ACUTEVERTEX) { // ej is an ACUTEVERTEX. - stype = 1; sign = -1; + stype = 1; + sign = -1; // Exchange ei and ej. ek = ej; } else { if (getpointtype(ej) == RIDGEVERTEX) { @@ -857,7 +862,8 @@ void tetgenmesh::getsegmentsplitpoint3(face* sseg, point refpt, REAL* vt) } else { // ei is a STEINERVERTEX. if (getpointtype(ej) == ACUTEVERTEX) { - stype = 1; sign = -1; + stype = 1; + sign = -1; // Exchange ei and ej. ek = ej; } else { // ej is either a RIDGEVERTEX or STEINERVERTEX. @@ -996,12 +1002,9 @@ void tetgenmesh::delaunizesegments() if (dir != ACROSSVERT) { // Create the new point. makepoint(&newpt); - getsegmentsplitpoint(&sseg, refpt, newpt); + // getsegmentsplitpoint(&sseg, refpt, newpt); + getsegmentsplitpoint3(&sseg, refpt, newpt); setpointtype(newpt, STEINERVERTEX); - // DEBUG - if (pointmark(newpt) == 4157) { - printf("debug point\n"); - } // Split the segment by newpt. sinsertvertex(newpt, &splitsh, &sseg, true, false); // Insert newpt into the DT. If 'checksubfaces == 1' the current diff --git a/contrib/Tetgen/refine.cxx b/contrib/Tetgen/refine.cxx new file mode 100644 index 0000000000..fd4dc34f52 --- /dev/null +++ b/contrib/Tetgen/refine.cxx @@ -0,0 +1,243 @@ +#ifndef refineCXX +#define refineCXX + +#include "tetgen.h" + +/////////////////////////////////////////////////////////////////////////////// +// // +// checkedge4encroach() Check a subsegment to see if it is encroached. // +// // +// If 'testpt' != NULL, only test if the segment is encroached by this point.// +// Otherwise, test all apexes of faces containing this segment. // +// // +// If 'enqflag' > 0, add the segment into list (badsegpool) if it is encroa- // +// ched. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenmesh::checkedge4encroach(face& seg, point testpt, int enqflag) +{ + badface *encseg; + triface neightet, spintet; + point pa, pb, pc, encpt; + REAL midpt[3], r, d, diff; + int encroached; + int i; + + seg.shver = 0; + pa = sorg(seg); + pb = sdest(seg); + + for (i = 0; i < 3; i++) { + midpt[i] = 0.5 * (pa[i] + pb[i]); + } + r = DIST(midpt, pa); + + encroached = 0; + encpt = NULL; + + if (testpt == NULL) { + // Check all apexes of faces containing [pa, pb]. + stpivot(seg, neightet); // sstpivot(seg, neightet); + spintet = neightet; + while (1) { + pc = apex(spintet); + if (pc != dummypoint) { + d = DIST(midpt, pc); + diff = fabs(r - d); + if ((diff / r) < b->epsilon) { + // testpt is on the diametric ball of [pa, pb]. + encroached = 0; + } else { + encroached = (d < r ? 1 : 0); + } + if (encroached) { + encpt = pc; // pc is encroached [pa. pb]. + break; + } + } + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + } else { + d = DIST(midpt, testpt); + diff = fabs(r - d); + if ((diff / r) < b->epsilon) { + // testpt is on the diametric ball of [pa, pb]. + encroached = 0; + } else { + encroached = (d < r ? 1 : 0); + if (encroached) { + encpt = testpt; + } + } + } + + if (encroached && enqflag) { + if (b->verbose > 1) { + printf(" Queuing encroaching segment (%d, %d) ref (%d).\n", + pointmark(pa), pointmark(pb), pointmark(encpt)); + } + encseg = (badface *) badsegpool->alloc(); + encseg->ss = seg; + encseg->forg = pa; + encseg->fdest = pb; + encseg->foppo = encpt; // The encroaching point. + smarktest(seg); // Flag it to avoid multiple testing. + } + + return encroached > 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// repairencsegs() Repair all queued encroached subsegments. // +// // +// Encroached segments are repaired by inserting a vertex inside them. Each // +// newly inserted vertex may encroach other segments, or makeing them non- // +// Delaunay, these segments are also repaired. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::repairencsegs() +{ + badface *encloop; + triface searchtet; + face splitsh; + point newpt, refpt; + point pa, pb; + + while ((badsegpool->items > 0) && (b->steinerleft != 0)) { + + badsegpool->traversalinit(); + encloop = badfacetraverse(badsegpool); + while ((encloop != NULL) && (b->steinerleft != 0)) { + // assert(smarktested(encloop->ss)); + sunmarktest(encloop->ss); + + // Check if it is still the same segment when it is tested. + pa = sorg(encloop->ss); + pb = sdest(encloop->ss); + if ((encloop->forg == pa) && (encloop->fdest == pb)) { + + refpt = encloop->foppo; + if ((refpt == NULL) || getpointtype(refpt) == DEADVERTEX) { + // Check if this segment can be split. + assert(0); // Not handled yet. + } + // Create a new point in the segment. + makepoint(&newpt); + // getsegmentsplitpoint2(&(encloop->ss), refpt, newpt); + getsegmentsplitpoint3(&(encloop->ss), refpt, newpt); + setpointtype(newpt, STEINERVERTEX); + + // Decrease the number of allocated Steiner points (-S option). + if (b->steinerleft != -1) { + b->steinerleft--; + } + + // Get an adjacent tet for point location. + stpivot(encloop->ss, searchtet); + + // Split the segment by newpt. Two new subsegments and new subfaces + // are queued in subsegstack and subfacstack for recovery. + spivot(encloop->ss, splitsh); + sinsertvertex(newpt, &splitsh, &(encloop->ss), true, false); + + // Insert newpt into the DT. Since the mesh may be a CDT, always + // set visflag be true. Some existing egments and subfaces may be + // non-Delaunay due to this new vertex, they will be removed from + // the mesh, and are queued in subsegstack and subfacstack for + // recovery. + // Newly encroached segments, subfaces, and badly-shaped tets are + // queued in badsegpool, badsubpool, and badtetpool, resp. + insertvertex(newpt, &searchtet, true, true, false, false); + + // Recover missing subsegments. + assert(subsegstack->objects > 0); + delaunizesegments(); + // Recover missing subfaces. + assert(subfacstack->objects > 0); + constrainedfacets(); + } + + // Deallocate the badface. + badfacedealloc(badsegpool, encloop); + // Get the next badface. + encloop = badfacetraverse(badsegpool); + } // while (encloop != NULL) + + } // while (badsegpool->items > 0) +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// enforcequality() Create quality conforming Delaunay mesh. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::enforcequality() +{ + face shloop; + long bakptcount; + + if (!b->quiet) { + printf("Conforming Delaunay meshing.\n"); + } + + // Initialize the pool for storing encroched segments. + badsegpool = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0); + + // Initialize arrays. + tg_crosstets = new arraypool(sizeof(triface), 10); + tg_topnewtets = new arraypool(sizeof(triface), 10); + tg_botnewtets = new arraypool(sizeof(triface), 10); + tg_topfaces = new arraypool(sizeof(triface), 10); + tg_botfaces = new arraypool(sizeof(triface), 10); + tg_midfaces = new arraypool(sizeof(triface), 10); + tg_toppoints = new arraypool(sizeof(point), 8); + tg_botpoints = new arraypool(sizeof(point), 8); + tg_facpoints = new arraypool(sizeof(point), 8); + tg_facfaces = new arraypool(sizeof(face), 10); + tg_topshells = new arraypool(sizeof(face), 10); + tg_botshells = new arraypool(sizeof(face), 10); + + // Find all encroached segments. + subsegpool->traversalinit(); + shloop.sh = shellfacetraverse(subsegpool); + while (shloop.sh != NULL) { + checkedge4encroach(shloop, NULL, 1); + shloop.sh = shellfacetraverse(subsegpool); + } + + if (b->verbose && (badsegpool->items > 0)) { + printf(" Splitting encroached segments.\n"); + } + bakptcount = pointpool->items; + + // Fix encroached segments. + repairencsegs(); + // At this point, no segments should be encroached. + + if (b->verbose && ((pointpool->items - bakptcount) > 0)) { + printf(" %ld Steiner points.\n", pointpool->items - bakptcount); + } + + // Delete arrays. + delete tg_crosstets; + delete tg_topnewtets; + delete tg_botnewtets; + delete tg_topfaces; + delete tg_botfaces; + delete tg_midfaces; + delete tg_toppoints; + delete tg_botpoints; + delete tg_facpoints; + delete tg_facfaces; + delete tg_topshells; + delete tg_botshells; + + delete badsegpool; +} + +#endif // #ifndef refineCXX -- GitLab