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
00038
00039
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
00053 double six_volume = - orient3d(a_->x(), b_->x(), c_->x(), p.data());
00054 if (six_volume < 0.0) {
00055
00056 return std::numeric_limits<double>::max();
00057 } else {
00058 return six_volume / sixth_e3_;
00059 }
00060 }
00061
00062
00063
00064
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
00077 if (b->topological() < 3) { continue; }
00078
00079
00080 assert(b->topological() == 3);
00081
00082
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
00104 if (t.radius2(p) < b2 * radius2_) {
00105
00106 return true;
00107 }
00108 }
00109 }
00110
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
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
00139 bool formsSliver(const Geometry::Point<1>&) const {
00140 return false;
00141 }
00142 };
00143
00144 #endif