00001 #ifndef Cleaner_HEADER
00002 #define Cleaner_HEADER
00003
00004 #ifdef HAVE_CONFIG_H
00005 # include <config.h>
00006 #endif
00007
00008 #include "Mesh.h"
00009 #include <utilities/hash.h>
00010 #include <vector>
00011
00012 #if 0
00013 #define dprintf(...) printf(__VA_ARGS__);
00014 #else
00015 #define dprintf(...)
00016 #endif
00017
00024 template <unsigned ambient, unsigned topological>
00025 class MeshCleaner {
00026 BOOST_STATIC_ASSERT(ambient >= topological);
00027 BOOST_STATIC_ASSERT(topological >= 2);
00028
00029 typedef typename Mesh<ambient, topological>::Delaunay Delaunay;
00030 typedef typename Delaunay::Simplex Simplex;
00031 typedef typename Delaunay::Vertex Vertex;
00032 typedef typename Delaunay::Complex Complex;
00033 typedef typename Complex::OSimplex OSimplex;
00034 typedef ::GenericMesh<ambient> GenericMesh;
00035
00038 struct FindCorners {
00039 hudson::FastHashSet<Vertex*, hudson::HashPointer<Vertex>, false > corners_;
00040 std::vector<Simplex> corner_seeds_;
00041 template <class v_iterator>
00042 FindCorners(v_iterator begin, v_iterator end) {
00043 corners_.insert(begin, end);
00044 }
00045 static bool canEnter(const Simplex&) { return true; }
00046 bool choose(const Simplex& s) {
00047 BOOST_FOREACH(Vertex *v, s) {
00048 if (corners_.has(v)) {
00049 corner_seeds_.push_back(s);
00050 break;
00051 }
00052 }
00053 return false;
00054 }
00055 };
00056
00057
00059 typedef hudson::OrderedHashSet<Simplex, hudson::hash_by_call<Simplex> >
00060 SimplexSet;
00061
00063 struct FindAllDead {
00064 const SimplexSet& live;
00065 SimplexSet& dead;
00066 FindAllDead(const SimplexSet& live, SimplexSet& dead) : live(live), dead(dead) { }
00067 static bool canEnter(const Simplex&) { return true; }
00068 bool choose(const Simplex& s) {
00069 if (!live.has(s)) {
00070 dead.insert(s);
00071 }
00072 return false;
00073 }
00074 };
00075
00076 public:
00084 static void traverseComponent(Delaunay *del, const Simplex& seed,
00085 SimplexSet& component,
00086 hudson::SmallList<Simplex>& next_seeds)
00087 {
00088 const Complex& c = del->getComplex();
00089 hudson::FrontStack<Simplex> fringe;
00090
00091 fringe.push(seed);
00092 dprintf("traversing component from seed %s\n", seed.toString().c_str());
00093
00094
00095 while (!fringe.empty()) {
00096 Simplex s = fringe.top();
00097 fringe.pop();
00098
00099 if (component.has(s)) { continue; }
00100 component.insert(s);
00101 dprintf(" reachable: %s\n", s.toString().c_str());
00102
00103
00104 OSimplex os = c.orientSimplex(s);
00105 for (size_t faceID = 0; faceID <= topological; ++faceID) {
00106
00107 OSimplex neigh = c.getNeighbour(faceID, os);
00108
00109
00110 if (!neigh.isInternal()) {
00111 continue;
00112 }
00113
00114
00115 OSimplex fi = c.getFace(faceID, os);
00116
00117
00118
00119
00120
00121
00122
00123 std::vector<const GenericMesh*> meshes;
00124 std::copy(fi[0]->begin_uppers(topological-1), fi[0]->end_uppers(topological-1),
00125 std::back_inserter(meshes));
00126
00127 for(size_t i = 1 ; i <= topological - 1; ++i) {
00128
00129 std::vector<const GenericMesh*> tmp;
00130 std::set_intersection(meshes.begin(), meshes.end(),
00131 fi[i]->begin_uppers(topological - 1), fi[i]->end_uppers(topological - 1),
00132 std::back_inserter(tmp));
00133 meshes.swap(tmp);
00134 }
00135
00136
00137 assert(meshes.size() == 0 || meshes.size() == 1);
00138
00139 if (meshes.empty()) {
00140
00141 fringe.push(neigh);
00142 } else {
00143
00144 next_seeds.push_front(neigh);
00145 }
00146 }
00147 }
00148 }
00149
00162 template <class v_iterator>
00163 static bool clean(Delaunay *del, v_iterator begin_corners, v_iterator end_corners,
00164 hudson::SmallList<Simplex> *optional_output = 0) {
00165 const Complex& c = del->getComplex();
00166
00167 dprintf("Performing cleanup on a %u-mesh\n", topological);
00168
00169
00170 FindCorners fc(begin_corners, end_corners);
00171 c.dfsBySimplex(fc, c.getHandle());
00172
00173 dprintf("Computing exterior simplices\n");
00174 SimplexSet exterior;
00175 hudson::SmallList<Simplex> interior_seeds;
00176 BOOST_FOREACH(const Simplex& seed, fc.corner_seeds_) {
00177 traverseComponent(del, seed, exterior, interior_seeds);
00178 }
00179
00180 dprintf("Computing interior simplices\n");
00181 SimplexSet interior;
00182 hudson::SmallList<Simplex> ignored_seeds;
00183 BOOST_FOREACH(const Simplex& seed, interior_seeds) {
00184 if (exterior.has(seed)) { continue; }
00185 traverseComponent(del, seed, interior, ignored_seeds);
00186 }
00187
00188 if (interior.empty()) {
00189
00190
00191 dprintf("Non-watertight!\n");
00192 return false;
00193 }
00194
00195
00196 FindAllDead fd(interior, exterior);
00197 c.dfsBySimplex(fd, c.getHandle());
00198
00199
00200 Complex& c_writable = del->getComplexRW();
00201 assert(!exterior.has(interior.front()));
00202 c_writable.setHandle(interior.front());
00203 BOOST_FOREACH(const Simplex& toslough, exterior) {
00204 c_writable.checkedRemoveSimplex(toslough);
00205 }
00206
00207 if (optional_output) {
00208 BOOST_FOREACH(const Simplex& s, interior) {
00209 optional_output->push_front(s);
00210 }
00211 }
00212
00213
00214 return true;
00215 }
00216 };
00217
00218 #undef dprintf
00219
00220 #endif