SliverChecker.h

Go to the documentation of this file.
00001 #ifndef SliverChecker_HEADER
00002 #define SliverChecker_HEADER
00003 
00004 #ifdef HAVE_CONFIG_H
00005 # include <config.h>
00006 #endif
00007 
00008 #include "MeshTypes.h"
00009 #include "ProtectedBall.h"
00010 #include "RefineVertex.h"
00011 #include <boost/static_assert.hpp>
00012 #include <geometry/Circles.h>
00013 #include <geometry/predicates.h>
00014 #include <limits>
00015 #include <refine-common/RefineConstants.h>
00016 #include <utilities/SmallList.h>
00017 
00024 template <unsigned ambient> struct SliverChecker;
00025 
00026 template <>
00027 struct SliverChecker<3> {
00028   static const unsigned ambient = 3;
00029 
00030   typedef MeshTypes<ambient>::Vertex Vertex;
00031   typedef MeshTypes<ambient>::Point Point;
00032   typedef MeshTypes<ambient>::Ball Ball;
00033 
00034   struct Triangle {
00035     Vertex *const a_, *const b_, *const c_;
00036 
00037     /* The goal is to return 'sigma', which is volume / e^3, where e is the
00038      * shortest edge.  We compute the edge length in the ctor, and orient3d
00039      * returns six times the volume, so I store one-sixth the edge cubed. */
00040     double sixth_e3_;
00041 
00042     Triangle(Vertex *a, Vertex *b, Vertex *c): a_(a), b_(b), c_(c) {
00043       double ab2 = a->toPoint().dist2(b->toPoint());
00044       double ac2 = a->toPoint().dist2(c->toPoint());
00045       double bc2 = b->toPoint().dist2(c->toPoint());
00046       double min2 = std::min(ab2, std::min(ac2, bc2));
00047       double min = sqrt(min2);
00048       sixth_e3_ = min * min * min / 6.0;
00049     }
00050 
00051     double sigma(const Point& p) const {
00052       /* Return sigma = volume / e^3, a dimensionless quantity.  Larger is better. */
00053       double six_volume = - orient3d(a_->x(), b_->x(), c_->x(), p.data());
00054       if (six_volume < 0.0) {
00055         // this tet won't be created, so just return that it's perfect quality
00056         return std::numeric_limits<double>::max();
00057       } else {
00058         return six_volume / sixth_e3_;
00059       }
00060     }
00061 
00062     /* Circumradius of the new sliver.  Only called if it is, in fact, a sliver;
00063        therefore, we really shouldn't need to recompute it since it should be
00064        constant. */
00065     double radius2(const Point& p) const {
00066       return Geometry::circumcenter_tetrahedron<ambient>(
00067           a_->toPoint(), b_->toPoint(), c_->toPoint(), p).radius2;
00068     }
00069   };
00070 
00071   template <class ball_iterator>
00072   SliverChecker(const ball_iterator& begin, const ball_iterator& end, const
00073       RefineConstants & consts, double radius2):
00074   consts_(consts), radius2_(radius2) {
00075     BOUNDED_FOREACH(Ball *b, begin, end) {
00076       // ignore uppers that aren't up enough to form slivers at all
00077       if (b->topological() < 3) { continue; }
00078 
00079       // since we're in ambient dimension 3... TODO
00080       assert(b->topological() == 3);
00081 
00082       // Copy all triangles that this protected simplex can make.
00083       typename Vertex::VertexUniqueList verts;
00084       b->gatherVertices(verts);
00085       assert(verts.size() == 4);
00086       boost::array<Vertex*,4> varray;
00087       std::copy(verts.begin(), verts.end(), varray.begin());
00088       for(int i = 0; i < 4; ++i) {
00089         for(int j = i+1; j < 4; ++j) {
00090           for(int k = j+1; k < 4; ++k) {
00091             Triangle t(varray[i], varray[j], varray[k]);
00092             triangles_.push_front(t);
00093           }
00094         }
00095       }
00096     }
00097   }
00098 
00099   bool formsSliver(const Point& p) const {
00100     double b2 = consts_.sliverGrowth * consts_.sliverGrowth;
00101     BOOST_FOREACH(const Triangle& t, triangles_) {
00102       if (t.sigma(p) < consts_.sigma) {
00103         // this forms a sliver.  Is it a small sliver?
00104         if (t.radius2(p) < b2 * radius2_) {
00105           // it's too small => report!
00106           return true;
00107         }
00108       }
00109     }
00110     // Nothing got reported?  Then this is a good point.
00111     return false;
00112   }
00113 
00114   private:
00115   const RefineConstants consts_;
00116   hudson::SmallList<Triangle> triangles_;
00117   double radius2_;
00118 };
00119 
00120 template <>
00121 struct SliverChecker<2> {
00122   template <class ball_iterator>
00123   SliverChecker(const ball_iterator&, const ball_iterator&,
00124       const RefineConstants &, double) { }
00125 
00126   /* We never form slivers. */
00127   bool formsSliver(const Geometry::Point<2>&) const {
00128     return false;
00129   }
00130 };
00131 
00132 template <>
00133 struct SliverChecker<1> {
00134   template <class ball_iterator>
00135   SliverChecker(const ball_iterator&, const ball_iterator&, 
00136       const RefineConstants &, double) { }
00137 
00138   /* We never form slivers. */
00139   bool formsSliver(const Geometry::Point<1>&) const {
00140     return false;
00141   }
00142 };
00143 
00144 #endif

Generated on Thu Mar 27 19:04:14 2008 by  doxygen 1.4.6