PointRefineVertex.h

Go to the documentation of this file.
00001 #ifndef PointRefineVertex_HEADER
00002 #define PointRefineVertex_HEADER
00003 
00004 #ifdef HAVE_CONFIG_H
00005 # include <config.h>
00006 #endif
00007 
00008 #include <geometry/Point.h>
00009 #include <delaunay/PointVertex.h>
00010 #include <utilities/IntrusiveList.h>
00011 #include <utilities/SmallList.h>
00012 #include <refine-common/ConcentricShells.h>
00013 
00016 // #undef MAINTAIN_NN
00017 
00018 #if 0
00019 #define dprintf(...) printf(__VA_ARGS__);
00020 #define dputs(str) puts(str);
00021 #else
00022 #define dprintf(...)
00023 #define dputs(str)
00024 #endif
00025 
00026 
00027 
00028 /***************************************************************************
00029  * The vertex class used by the refinement.
00030  *
00031  * I use the vertices to store the uninserted points (namely, those that lie
00032  * in their Voronoi cells), hence the need to specialize the Vertex class.
00033  *
00034  * Theoretically, there is an infinite set of annuli around each vertex,
00035  * with radii in geometric progression.  We store all the annuli that are
00036  * non-empty, along with their outradius and the points they contain.  This
00037  * means we look much (constant factors) less frequently at input points than
00038  * if we stored all the points in a single bucket.
00039  *
00040  * There are some facts we do not use: first, note that Steiner points have all
00041  * their points in O(1) annuli (since there are no points allowed close to a
00042  * Steiner point).  Second, annuli don't distinguish in which direction points
00043  * lie: a search from the left will investigate points that are very far to the
00044  * right.
00045  *
00046  * The uninserted points are stored in a number of lists.  Rather than
00047  * allocating and freeing list buckets as we reassign points, we use an
00048  * IntrusiveList: the list buckets are the vertices themselves.  This saves
00049  * a bit of memory allocation.
00050  ***************************************************************************/
00051 template <unsigned d, class Simplex>
00052 class PointRefineVertex : public PointVertex<d> {
00053 
00054   typedef Geometry::Point<d> Point;
00055   typedef PointRefineVertex Uninserted;
00056 
00057   public:
00058   PointRefineVertex(const Point& p, size_t ID = size_t(-1)) : PointVertex<d>(p) {
00059     visited_ = 0;
00060     inMesh_ = false;
00061     ID_ = ID;
00062     isSteiner_ = (ID == size_t(-1));
00063 #ifdef MAINTAIN_NN
00064     NN2_ = std::numeric_limits<double>::infinity();
00065 #endif
00066   }
00067 
00068   ~PointRefineVertex() {
00069     if (inMesh()) {
00070       get().~Simplex();
00071     }
00072   }
00073 
00074 #ifdef NDEBUG
00075 # define unused(sym)
00076 #else
00077 # define unused(sym) sym
00078 #endif
00079 
00081   void *operator new(size_t unused(sz)) {
00082     assert(sz == sizeof(PointRefineVertex));
00083     return hudson::SmallMemoryPool::allocate<sizeof(PointRefineVertex)>();
00084   }
00085 
00086   void *operator new(size_t unused(sz), void *ptr) {
00087     assert(sz == sizeof(PointRefineVertex));
00088     return ptr;
00089   }
00090 
00092   void operator delete(void *v, size_t unused(sz)) {
00093     assert(sz == sizeof(PointRefineVertex));
00094     hudson::SmallMemoryPool::deallocate<sizeof(PointRefineVertex)>(v);
00095   }
00096 #undef unused
00097 
00098 
00099   /************************************************************
00100    * \name Name.
00101    ************************************************************/
00102   size_t id() const { return ID_; }
00103   bool isSteiner() const { return isSteiner_; }
00104   void setID(size_t i) { ID_ = i; }
00105 
00106   /************************************************************
00107    * \name Distance.
00108    ************************************************************/
00109   double dist2(const PointRefineVertex *other) const {
00110     return this->toPoint().dist2(other->toPoint());
00111   }
00112   double dist2(const Point& other) const {
00113     return this->toPoint().dist2(other);
00114   }
00115 
00117 #ifdef MAINTAIN_NN
00118   double getNN2() const {
00119     return NN2_;
00120   }
00121 #endif
00122 
00123   /************************************************************
00124    * \name Queries and relocation
00125    * Foreach annulus, from outermost to innermost:
00126    *   if R(a) < |pq| - r then quit
00127    *   else iterate through the points.
00128    * r is |pq|/2 in the reassign case; it's the best point in
00129    * the query case.
00130    *
00131    * The newv is presumed to be a vertex which may be the new nearest
00132    * neighbour.
00133    ************************************************************/
00134   void reassign(PointRefineVertex *newv) {
00135 #ifdef MAINTAIN_NN
00136     double pq2 = dist2(newv);
00137     if (pq2 < NN2_) { NN2_ = pq2; }
00138 #endif
00139 
00140     annuli_.reassignTo(this->toPoint(), newv->annuli_, newv->toPoint());
00141   }
00142 
00143   pair<Uninserted*, double> findClosest(const Point& q, double r2) const {
00144     return annuli_.findClosest(this->toPoint(), q, r2);
00145   }
00146 
00147   pair<Uninserted*, double> findPoint(const Point& q, double r2) const {
00148     return annuli_.findPoint(this->toPoint(), q, r2);
00149   }
00150 
00151   void assign(Uninserted *u) {
00152     // If we were uninserted and just got inserted, we shall be assigned
00153     // ourselves.  Simply ignore the request.
00154     if (u == this) return;
00155     annuli_.add(this->toPoint(), u);
00156   }
00157 
00158   /************************************************************
00159    * Get a far-away point to insert.
00160    ************************************************************/
00161   bool isCrowded() const {
00162     return !annuli_.empty();
00163   }
00164   Uninserted *getFarPoint() const {
00165     return annuli_.getFarItem();
00166   }
00167 
00168   /************************************************************
00169    * \name Back-pointer
00170    * We need a handle from the vertex back to the mesh.
00171    ************************************************************/
00172   const Simplex& getHandle() const { return get(); }
00173   void setHandle(const Simplex& s) { get() = s; }
00174   void initHandle(const Simplex& s) {
00175     assert(!inMesh());
00176     new (&getUnchecked()) Simplex(s);
00177     inMesh_ = true;
00178   }
00179 
00180   /************************************************************
00181    * \name Visited flags
00182    *
00183    * We often want to visit vertices.  We only ever have one search
00184    * at a time.  Therefore, we simply store a flag in the vertex.
00185    * The flag is simply cleared every 2^32 searches (which typically
00186    * means we never bother cleaning the flag).
00187    ************************************************************/
00188   typedef unsigned FlagType;
00189   FlagType visitedFlag() const { return visited_; }
00190   void setVisited(FlagType i) { visited_ = i; }
00191   void clearVisited() { visited_ = 0; }
00192 
00193 
00194   private:
00195 
00196   /************************************************************
00197    * \name Management of the simplex handle
00198    *
00199    * Since we don't have a no-arg ctor for Simplex, and since
00200    * we don't get a simplex at Vertex ctor time, we have to
00201    * hack around it.  Paying for a scoped_ptr is too expensive.
00202    * Implications:
00203    * 1. we use placement new to initialize the simplex, in initData
00204    * 2. we have to explicitely destroy the simplex in ~Vertex
00205    * 3. use get() to access the simplex.
00206    ************************************************************/
00207   bool inMesh() const { return inMesh_; }
00208   Simplex& getUnchecked() { return *(Simplex*)&handle_[0]; }
00209   Simplex& get() {
00210     assert(inMesh());
00211     return getUnchecked();
00212   }
00213   const Simplex& get() const {
00214     assert(inMesh());
00215     return *(Simplex*)&handle_[0];
00216   }
00217 
00218 
00219   /************************************************************
00220    * Data members.  Descriptions are above.
00221    ************************************************************/
00222 #ifdef MAINTAIN_NN
00223   double NN2_; // nearest-neighbour
00224 #endif
00225 
00226   char handle_[sizeof(Simplex)];
00227   // bool inMesh_; // packed with a later field
00228 
00229   ConcentricShells<Uninserted, Point> annuli_;
00230 
00231   size_t ID_:(sizeof(size_t)*8 - 2); // 30 or 62 bits
00232   bool isSteiner_:1;
00233   bool inMesh_:1;
00234   FlagType visited_;
00235 };
00236 #undef dprintf
00237 #undef dputs
00238 #undef MAINTAIN_NN
00239 
00240 #endif

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