00001 #ifndef PLC_REFINER_HEADER
00002 #define PLC_REFINER_HEADER
00003
00004
00005
00006
00007
00008
00009 #include "MeshConstructor.h"
00010 #include "MeshSet.h"
00011 #include "MeshTypes.h"
00012 #include "SplitData.h"
00013 #include "WorkItem.h"
00014 #include "WorkQueue.h"
00015 #include <boost/function_output_iterator.hpp>
00016 #include <delaunay/DelaunayHelpers.h>
00017 #include <io/PLC.h>
00018 #include <iterator>
00019 #include <refine-common/RefineConstants.h>
00020 #include <refine-common/Refiner.h>
00021 #include <topology/SimplicialHelpers.h>
00022 #include <utilities/OrderedHash.h>
00023
00024 #if 0
00025 #define dprintf(...) printf(__VA_ARGS__);
00026 #else
00027 #define dprintf(...)
00028 #endif
00029
00030 namespace SVR {
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 template <size_t ambient>
00051 class PLCRefiner : public MeshRefiner {
00052
00053 typedef Geometry::CenterRadius<ambient> CenterRadius;
00054 typedef Geometry::Point<ambient> Point;
00055 typedef ::MeshSet<ambient> MeshSet;
00056 typedef ::SplitData<ambient> SplitData;
00057 typedef ::WorkItem<ambient> WorkItem;
00058 typedef ::WorkQueue<ambient> WorkQueue;
00059 typedef typename MeshTypes<ambient>::Ball Ball;
00060 typedef typename MeshTypes<ambient>::Vertex Vertex;
00061 typedef typename MeshTypes<ambient>::GenericMesh GenericMesh;
00062 typedef typename Ball::BallSet BallSet;
00063 typedef typename Mesh<ambient, ambient>::Complex Complex;
00064 typedef typename Complex::Simplex Simplex;
00065 typedef typename Complex::OSimplex OSimplex;
00066 typedef typename Vertex::VertexUniqueList VertexUniqueList;
00067
00068 const RefineConstants consts_;
00069
00070 MeshSet meshes_;
00071 WorkQueue queue_;
00072 size_t nextID_;
00073 unsigned nsimplices_;
00074 std::vector<Vertex*> bbox_corners_;
00075
00076 hudson::SmallList<Simplex> simplices_out_;
00077
00078 unsigned niterations_;
00079 unsigned message_niterations_;
00080
00081 private:
00082 Mesh<ambient,ambient> *getTopMesh() {
00083 return meshes_.getTopMesh();
00084 }
00085 const Mesh<ambient,ambient> *getTopMesh() const {
00086 return meshes_.getTopMesh();
00087 }
00088
00089 public:
00091 size_t getID(const Vertex *v) const {
00092 return v->getID();
00093 }
00094 void setID(Vertex *v) {
00095 v->setID(nextID_++);
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105 public:
00106 static PLCRefiner *initialize(const SVR_IO::PLC *plc,
00107 RefineConstants consts) {
00108 consts.regularize(ambient, false);
00109 return new PLCRefiner(plc, consts);
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 private:
00122 PLCRefiner(const SVR_IO::PLC *plc, const RefineConstants& consts)
00123 : consts_(consts)
00124 {
00125
00126 dprintf("Init from PLC\n");
00127 MeshConstructor<ambient>::construct(plc, consts_.rho, meshes_);
00128
00129
00130
00131 dprintf("Filling queues\n");
00132 meshes_.outputAllBalls(
00133 boost::make_function_output_iterator (
00134 std::bind1st(
00135 std::mem_fun( &PLCRefiner::checkBall )
00136 , this)
00137 )
00138 );
00139 Simplicial::collectVertices(
00140 getTopMesh()->getSimplicialComplex(),
00141 boost::make_function_output_iterator (
00142 std::bind1st(
00143 std::mem_fun( &PLCRefiner::checkVertex )
00144 , this)
00145 )
00146 );
00147 vector<Vertex*> verts;
00148 Simplicial::collectVertices(getTopMesh()->getSimplicialComplex(), verts);
00149 bbox_corners_.reserve(verts.size() - 1);
00150 BOOST_FOREACH(Vertex *v, verts) {
00151 if (v->getCD() == ambient) {
00152 bbox_corners_.push_back(v);
00153 }
00154 }
00155
00156
00157 dprintf("Counting top-dimensional balls\n");
00158 nsimplices_ = meshes_.template outputSomeBalls<ambient>(hudson::count_iterator<Ball*>(0));
00159 dprintf(" %u\n", nsimplices_);
00160
00161
00162 dprintf("Counting vertices\n");
00163 nextID_ = meshes_.getVertices().size() + plc->getFirstID(0);
00164
00165
00166 niterations_ = 0;
00167 message_niterations_ = 1;
00168 }
00169
00172 private:
00173 struct EncroachmentChecker {
00174 WorkQueue *queue_;
00175 EncroachmentChecker(WorkQueue *q): queue_(q) {}
00176 void operator() (Ball *b) {
00177 BallSet uppers;
00178 b->gatherUppers(uppers);
00179 BOOST_FOREACH(Ball *up, uppers) {
00180 VertexUniqueList verts;
00181 up->gatherVertices(verts);
00182 BOOST_FOREACH(Vertex *v, verts) {
00183 if (b->encroachedBy(v)) {
00184 queue_->push( new typename WorkItem::Encroached(b) );
00185 }
00186 }
00187 }
00188 }
00189 };
00190
00191 void fixInitialEncroachment() {
00192 WorkItem *item;
00193 EncroachmentChecker echeck(&queue_);
00194 meshes_.outputAllBalls(boost::make_function_output_iterator(echeck));
00195 dprintf("Start fixing initial encroachments.\n");
00196 while( (item = queue_.pop()) ) {
00197 if (item->getReason() > WorkItem::ENCROACHED) {
00198
00199 queue_.push(item);
00200 break;
00201 } else {
00202 SplitData sdata(consts_);
00203 split(item, sdata);
00204 BOUNDED_FOREACH(Ball *b, sdata.begin_born(), sdata.end_born()) {
00205 echeck(b);
00206 }
00207 }
00208 }
00209 dprintf("Done fixing initial encroachments.\n");
00210 }
00211
00212 friend class CheckFinal;
00213 struct CheckFinal {
00214 PLCRefiner *svr_;
00215 bool isGood;
00216 CheckFinal(PLCRefiner *svr): svr_(svr), isGood(true) { }
00217 void operator() (Ball *b) {
00218 WorkItem *w = svr_->classify(b);
00219 if (w) {
00220 fprintf(stderr, "Checking: bad simplex causes %s\n", w->toString().c_str());
00221 isGood = false;
00222 }
00223 }
00224 };
00225
00226 void finalCheck() {
00227 CheckFinal final_mesh(this);
00228 meshes_.outputAllBalls(boost::make_function_output_iterator(final_mesh));
00229 assert(final_mesh.isGood);
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 public:
00250 virtual void refine() {
00251 dprintf("Refining\n");
00252
00253 fixInitialEncroachment();
00254
00255 WorkItem *w;
00256 while( (w = queue_.pop()) ) {
00257 SplitData sdata(consts_);
00258 split(w, sdata);
00259 }
00260
00261 if (consts_.cleanup) {
00262 cleanup();
00263 }
00264
00265 #ifndef NDEBUG
00266 finalCheck();
00267 #endif
00268
00269 printStats();
00270 }
00271
00272
00273
00274
00275 public:
00276 void printStats() {
00277 printf("Output size %u simplices\n", nsimplices_);
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 public:
00294 void split(WorkItem *w, SplitData& sdata) {
00295 niterations_++;
00296 if (niterations_ >= message_niterations_) {
00297 printf("Iteration %u, we have %u simplices so far\n", niterations_,
00298 nsimplices_);
00299 message_niterations_ *= 2;;
00300 }
00301 dprintf("Iteration %u: %s (%s)\n", niterations_,
00302 w->isActive() ? "*splitting*" : "moot",
00303 w->toString().c_str());
00304
00305
00306 if (!w->isActive()) {
00307 delete w;
00308 return;
00309 }
00310
00311 size_t topo = w->topological();
00312 bool didsplit = w->split(sdata);
00313
00314
00315 BOUNDED_FOREACH(Ball *encroached, sdata.begin_encroached(), sdata.end_encroached()) {
00316 queue_.push( new typename WorkItem::Encroached(encroached) );
00317 }
00318
00319
00320 if (didsplit) {
00321
00322
00323 Vertex *inserted = sdata.getVertex();
00324 bool isnew = inserted->getCD() == topo;
00325 if (isnew) {
00326 meshes_.add(inserted);
00327 setID(inserted);
00328 dprintf(" %s is a new vertex in dimension %u at %s\n",
00329 inserted->toString().c_str(), unsigned(inserted->getCD()),
00330 inserted->toPoint().toString().c_str());
00331 }
00332
00333
00334 if (topo == ambient) {
00335 checkVertex(inserted);
00336 }
00337
00338
00339
00340
00341 if (topo < ambient && isnew) {
00342 BallSet uppers;
00343 VertexUniqueList vset;
00344 BOUNDED_FOREACH(Ball *killed, sdata.begin_killed(), sdata.end_killed()) {
00345 killed->gatherUppers(uppers);
00346 }
00347 BOOST_FOREACH(Ball *upper, uppers) {
00348 if (upper->topological() != ambient) { continue; }
00349 upper->gatherVertices(vset);
00350 }
00351 BOOST_FOREACH(Vertex *upv, vset) {
00352 checkVertex(upv);
00353 }
00354 }
00355
00356
00357
00358
00359
00360 if (topo < ambient && isnew) {
00361 Ball *s = *sdata.begin_killed();
00362
00363 BallSet alluppers;
00364 hudson::OrderedHashSet<const GenericMesh*, hudson::HashPointer<GenericMesh> > meshes;
00365 hudson::FastHashMap<const GenericMesh*, BallSet, hudson::HashPointer<GenericMesh> > uppers;
00366 s->gatherUppers(alluppers);
00367 BOOST_FOREACH(Ball *upper, alluppers) {
00368 const GenericMesh *m = upper->getMesh();
00369 if (m->topological() == ambient) { continue; }
00370 uppers[m].insert(upper);
00371 meshes.insert(m);
00372 }
00373 VertexUniqueList verts;
00374 s->gatherVertices(verts);
00375 BOOST_FOREACH(const GenericMesh *m, meshes) {
00376 dprintf(" checking for immediate inclusion in %u-mesh[%p]...",
00377 m->topological(), m);
00378 VertexUniqueList mverts;
00379 BOOST_FOREACH(Ball *upper, uppers[m]) {
00380 upper->gatherVertices(mverts);
00381 }
00382
00383 bool allresolved = true;
00384 BOOST_FOREACH(Vertex *v, verts) {
00385 if (!mverts.has(v)) {
00386 dprintf("no\n");
00387 allresolved = false;
00388 break;
00389 }
00390 }
00391 if (allresolved) {
00392
00393
00394 Ball *topush = NULL;
00395 BOOST_FOREACH(Ball *upper, uppers[m]) {
00396 if (upper->inSphereExact(inserted)) {
00397 topush = upper;
00398 break;
00399 }
00400 }
00401 dprintf("split at %s\n", topush->toString().c_str());
00402 assert(topush);
00403 queue_.push( new typename WorkItem::NewBoundaryVertex(topush, inserted) );
00404 }
00405 }
00406 }
00407
00408
00409
00410 BOUNDED_FOREACH(Ball *newborn, sdata.begin_born(), sdata.end_born()) {
00411 checkBall(newborn);
00412 }
00413
00414
00415 if (topo == ambient) {
00416 nsimplices_ += sdata.nborn();
00417 nsimplices_ -= sdata.nkilled();
00418 dprintf("There are now %u simplices\n", unsigned(nsimplices_));
00419 }
00420
00421
00422 #if 0
00423
00424 if (topo == ambient && inserted->getCD() < ambient) {
00425 animation_print();
00426 }
00427 #endif
00428 }
00429
00430
00431
00432 if (w->isActive()) {
00433 queue_.push(w);
00434 } else {
00435 delete w;
00436 }
00437 }
00438
00439
00440
00441
00442
00443 typedef std::pair<boost::array<unsigned, ambient>, unsigned> face_type;
00444 struct animator {
00445 hashers::hash_map<Vertex*, unsigned, hudson::hash_by_cast<Vertex*> > ids;
00446 hashers::hash_map<const GenericMesh*, unsigned, hudson::hash_by_cast<const GenericMesh*> > colours;
00447
00448 std::vector<Vertex*> verts;
00449 std::vector<face_type> faces;
00450 const Complex& c;
00451
00452 animator(const Complex& c) : c(c) { }
00453
00454 static bool canEnter(const Simplex&) { return true; }
00455
00456 bool choose(const Simplex& s) {
00457 OSimplex os = c.orientSimplex(s);
00458 for(unsigned i = 0; i <= ambient; ++i) {
00459 processFace(c.getFace(i, os));
00460 }
00461 return false;
00462 }
00463
00464 void processFace(const OSimplex& fi) {
00465
00466
00467 std::vector<const GenericMesh*> meshes;
00468 std::copy(fi[0]->begin_uppers(ambient-1), fi[0]->end_uppers(ambient-1),
00469 std::back_inserter(meshes));
00470 for(unsigned j = 1; j < ambient; ++j) {
00471 std::vector<const GenericMesh*> tmp;
00472 std::set_intersection(meshes.begin(), meshes.end(),
00473 fi[j]->begin_uppers(ambient - 1), fi[j]->end_uppers(ambient - 1),
00474 std::back_inserter(tmp));
00475 meshes.swap(tmp);
00476 }
00477 assert(meshes.size() == 0 || meshes.size() == 1);
00478 if (!meshes.empty()) {
00479 face_type face;
00480 for(unsigned j = 0; j < ambient; ++j) {
00481 face.first[j] = getVertexID(fi[j]);
00482 }
00483 face.second = getMeshColour(meshes[0]);
00484 faces.push_back(face);
00485 }
00486 }
00487 unsigned getVertexID(Vertex *v) {
00488 if(ids.find(v) == ids.end()) {
00489 unsigned id = ids.size();
00490 ids[v] = id;
00491 verts.push_back(v);
00492 }
00493 return ids[v];
00494 }
00495
00496 unsigned getMeshColour(const GenericMesh *m) {
00497 if (colours.find(m) == colours.end()) {
00498 unsigned col = colours.size();
00499 colours[m] = col;
00500 }
00501 return colours[m];
00502 }
00503 };
00504
00505
00506 void animation_print() {
00507
00508 const Complex& c = getTopMesh()->getSimplicialComplex();
00509 animator anim(c);
00510 c.dfsBySimplex(anim, c.getHandle());
00511 assert(ambient == 3);
00512
00513 unsigned nvertices = anim.verts.size();
00514 unsigned nfaces = anim.faces.size();
00515 FILE *out;
00516
00517 {
00518 char buffer[4096];
00519 snprintf(buffer, sizeof(buffer), "faces-%u.off", nvertices);
00520 out = fopen(buffer, "w");
00521 }
00522 assert(out);
00523
00524
00525 fprintf(out, "%u %u 0\n", nvertices, nfaces);
00526
00527 BOOST_FOREACH(const Vertex *v, anim.verts) {
00528 Point p = v->toPoint();
00529 fprintf(out, "%g %g %g\n", p[0], p[1], p[2]);
00530 }
00531 BOOST_FOREACH(face_type face, anim.faces) {
00532
00533 fprintf(out, "3 %u %u %u %u\n", face.first[0], face.first[1], face.first[2], face.second);
00534 }
00535 fclose(out);
00536 }
00537
00538
00539
00540
00541 void cleanup() {
00542 bool watertight = MeshCleaner<ambient,ambient>::clean(
00543 getTopMesh()->getDelaunayDangerously(),
00544 bbox_corners_.begin(), bbox_corners_.end(),
00545 &simplices_out_);
00546
00547 if (!watertight) {
00548 nsimplices_ = 0;
00549 } else {
00550 nsimplices_ = std::distance(simplices_out_.begin(), simplices_out_.end());
00551 }
00552
00553
00554
00555 }
00556
00557
00558
00559
00560
00561 private:
00562 friend struct DoPrintSimplex;
00564 struct DoPrintSimplex {
00565 size_t n_;
00566 FILE *out_;
00567 const PLCRefiner *svr_;
00568 typedef typename Mesh<ambient, ambient>::Simplex Simplex;
00569
00570 DoPrintSimplex(const PLCRefiner *svr, FILE *out): n_(0), out_(out), svr_(svr) { }
00571 static bool canEnter(const Simplex&) { return true; }
00572 bool choose(const Simplex& s) {
00573 boost::array<size_t, ambient + 1> arr;
00574 for (size_t i = 0; i <= ambient; ++i) {
00575 arr[i] = svr_->getID(s[i]);
00576 }
00577 Delaunay::printEle(n_++, arr, out_);
00578 return false;
00579 }
00580 };
00581
00584 template <class v_iterator> void printVerts(FILE *node, v_iterator begin, v_iterator end) const {
00585 while (begin != end) {
00586 Vertex *v = *begin;
00587 ++begin;
00588 Delaunay::printPoint(getID(v), v->toPoint(), node);
00589 }
00590 }
00591
00592 public:
00597 virtual void printToNodeEle(FILE *node, FILE *ele) const {
00598
00599 fprintf(node, "%u %u 0 0\n", (unsigned)meshes_.getVertices().size(), unsigned(ambient));
00600 printVerts(node, meshes_.getVertices().begin(), meshes_.getVertices().end());
00601
00602
00603 fprintf(ele, "%u %u 0\n", unsigned(nsimplices_), unsigned(ambient + 1));
00604 DoPrintSimplex dps(this, ele);
00605 if (consts_.cleanup) {
00606 BOOST_FOREACH(const Simplex& s, simplices_out_) {
00607 dps.choose(s);
00608 }
00609 } else {
00610 const Complex& c = getTopMesh()->getSimplicialComplex();
00611 c.dfsBySimplex(dps, c.getHandle());
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620 private:
00621 WorkItem *classify(Ball *b) const {
00622
00623
00624 double re2 = b->radiusEdge2();
00625 if (re2 > consts_.rhoprime * consts_.rhoprime) {
00626 return new typename WorkItem::VerySkinny(b);
00627 }
00628
00629 if (consts_.sigma != 0.0 && b->topological() >= 3) {
00630 double sigma = b->computeSigma();
00631 if (sigma < consts_.sigma) {
00632 return new typename WorkItem::Sliver(b);
00633 }
00634 }
00635
00636 if (re2 > consts_.rho * consts_.rho) {
00637 return new typename WorkItem::MediumSkinny(b);
00638 }
00639
00640
00641
00642 if (!b->isResolved()) {
00643 return new typename WorkItem::Unresolved(b);
00644 }
00645
00646 return NULL;
00647 }
00648
00649
00650
00651
00652 void checkBall (Ball *b) {
00653 WorkItem *w = classify(b);
00654 if (w) {
00655 queue_.push(w);
00656 }
00657 }
00658
00660 void checkVertex (Vertex *v) {
00661 if (v->isCrowded(getTopMesh())) {
00662 if (v->getCD() == ambient) {
00663 queue_.push( new typename WorkItem::CrowdedSteiner(v, getTopMesh()) );
00664 } else {
00665 queue_.push( new typename WorkItem::CrowdedInput(v, getTopMesh()) );
00666 }
00667 }
00668 }
00669
00670 bool isActive(const WorkItem *item) const {
00671 if (!item->isBall()) {
00672 return item->getVertex()->isCrowded(getTopMesh());
00673 } else {
00674 Ball *b = item.getBall();
00675 if (!b->isLive()) { return false; }
00676 if (item.getReason() == WorkQueue::UNRESOLVED) {
00677 return !isResolved(b);
00678 }
00679 return true;
00680 }
00681 }
00682
00683 };
00684 }
00685
00686 #undef dprintf
00687
00688
00689 #endif