Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgPointSet.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgPointSet.h
00003     Sets of points on the board. */
00004 //----------------------------------------------------------------------------
00005 
00006 #ifndef SG_POINTSET_H
00007 #define SG_POINTSET_H
00008 
00009 #include <algorithm>
00010 #include <bitset>
00011 #include <cstring>
00012 #include <iosfwd>
00013 #include <memory>
00014 #include "SgArray.h"
00015 #include "SgPoint.h"
00016 #include "SgRect.h"
00017 #include "SgVector.h"
00018 
00019 //----------------------------------------------------------------------------
00020 
00021 /** Set of points.
00022     Represents a set of points on the Go board. This class is efficient for
00023     bit-level operations on the board as a whole. */
00024 class SgPointSet
00025 {
00026 public:
00027     SgPointSet();
00028 
00029     ~SgPointSet();
00030 
00031     explicit SgPointSet(const SgVector<SgPoint>& vector);
00032 
00033     SgPointSet& operator-=(const SgPointSet& other);
00034 
00035     SgPointSet& operator&=(const SgPointSet& other);
00036 
00037     SgPointSet& operator|=(const SgPointSet& other);
00038 
00039     SgPointSet& operator^=(const SgPointSet& other);
00040 
00041     bool operator==(const SgPointSet& other) const;
00042 
00043     bool operator!=(const SgPointSet& other) const;
00044 
00045     /** Return whether point 'p' is set. */
00046     bool operator[](SgPoint p) const;
00047     
00048     bool Disjoint(const SgPointSet& s) const;
00049     
00050     /** Test if this contains a Point adjacent to a Point in s */
00051     bool Adjacent(const SgPointSet& s) const;
00052 
00053     bool Adjacent8To(SgPoint p) const;
00054     
00055     /** Test if all points adjacent to this are contained in s */
00056     bool AdjacentOnlyTo(const SgPointSet& s, int boardSize) const;
00057 
00058     bool AdjacentTo(SgPoint p) const;
00059     
00060     /** Test if all Points in this are adjacent to some Point in s */
00061     bool AllAdjacentTo(const SgPointSet& s) const;
00062 
00063     static const SgPointSet& AllPoints(int boardSize);
00064 
00065     int Size() const;
00066 
00067     bool IsSize(int size) const;
00068 
00069     bool MinSetSize(int size) const;
00070 
00071     bool MaxSetSize(int size) const;
00072 
00073     bool IsEmpty() const;
00074 
00075     bool NonEmpty() const;
00076 
00077     /** 4-Neighbor points of set */
00078     SgPointSet Border(int boardSize) const;
00079 
00080     /** 8-Neighbor points of set */
00081     SgPointSet Border8(int boardSize) const;
00082 
00083     /** Compute border without clipping to board size. */
00084     SgPointSet BorderNoClip() const;
00085 
00086     /** SgPoint as close to the center of set as possible */
00087     SgPoint Center() const;
00088 
00089     /** Return whether point 'p' is set. */
00090     bool CheckedContains(SgPoint p, bool doRangeCheck = true,
00091                          bool onBoardCheck = false) const;
00092     
00093     SgPointSet& Clear();
00094 
00095     /** Compute connected component by iterative Border calculation.
00096         @note Slow for large diameter sets. */
00097     SgPointSet Component(SgPoint p) const;
00098 
00099     /** Good for small diameter sets */
00100     SgPointSet Component8(SgPoint p) const;
00101 
00102     /** Good for large diameter sets */
00103     SgPointSet ConnComp(SgPoint p) const;
00104 
00105     /** 8-neighbors */
00106     SgPointSet ConnComp8(SgPoint p) const;
00107 
00108     /** Check if contains point.
00109      Can be called with out-of-board points, otherwise use
00110      ContainsPoints(). */
00111     bool Contains(SgPoint p) const;
00112     
00113     /** Check if contains point.
00114      Can only be called with on-board points, otherwise use Contains(). */
00115     bool ContainsPoint(SgPoint p) const;
00116     
00117     SgRect EnclosingRect() const;
00118     
00119     SgPointSet& Exclude(SgPoint p);
00120 
00121     SgPointSet& Exclude(const SgVector<SgPoint>& vector);
00122 
00123     /** Include 4-neighbor points in set */
00124     void Grow(int boardSize);
00125     
00126     /** Returns newly added points */
00127     void Grow(SgPointSet* newArea, int boardSize);
00128     
00129     /** Include 8-neighbor points in set */
00130     void Grow8(int boardSize);
00131 
00132     SgPointSet& Include(SgPoint p);
00133 
00134     /** Whether set is connected or not.
00135         @return True if connected or set is empty.
00136         @note Slow for large diameters. */
00137     bool IsConnected() const;
00138 
00139     /** Whether set is connected or not. */
00140     bool Is8Connected() const;
00141 
00142     /** Points of set surrounded by set */
00143     SgPointSet Kernel(int boardSize) const;
00144 
00145     /** At most 'max' common points. */
00146     bool MaxOverlap(const SgPointSet& other, int max) const;
00147     
00148     /** At least 'min' common points. */
00149     bool MinOverlap(const SgPointSet& s, int min) const;
00150     
00151     bool NewMark(SgPoint p);
00152     
00153     bool Overlaps(const SgPointSet& other) const;
00154     
00155     /** First point of set.
00156         @return First (smallest) point of set or SG_NULLPOINT for empty set. */
00157     SgPoint PointOf() const;
00158 
00159     /** Is this set a subset of s? */
00160     bool SubsetOf(const SgPointSet& other) const;
00161     
00162     /** Is this set a superset of s? */
00163     bool SupersetOf(const SgPointSet& other) const;
00164     
00165     void Swap(SgPointSet& other) throw();
00166     
00167     SgPointSet& Toggle(SgPoint p);
00168 
00169     void ToVector(SgVector<SgPoint>* vector) const;
00170 
00171     void Write(std::ostream& out, int boardSize) const;
00172     
00173     /** Return whether point 'p' is close to a point in set.
00174         in implementation: const int MAX_CLOSE_DISTANCE = 3; */
00175     bool IsCloseTo(SgPoint p) const;
00176     
00177 private:
00178     /** Precomputed point sets with all points depending on board size. */
00179     class PrecompAllPoints
00180     {
00181     public:
00182         PrecompAllPoints();
00183 
00184         const SgPointSet& Get(int boardSize)
00185         {
00186             SG_ASSERT(boardSize >= SG_MIN_SIZE);
00187             SG_ASSERT(boardSize <= SG_MAX_SIZE);
00188             return *m_allPoints[boardSize];
00189         }
00190 
00191     private:
00192         SgArray<std::auto_ptr<SgPointSet>,SG_MAX_SIZE + 1> m_allPoints;
00193     };
00194 
00195     friend class SgSetIterator;
00196 
00197     std::bitset<SG_MAXPOINT> m_a;
00198 
00199     static PrecompAllPoints s_allPoints;
00200 
00201     SgPointSet operator>>(int n) const;
00202 
00203     SgPointSet operator<<(int n) const;
00204 
00205 };
00206 
00207 
00208 /** Compute difference between point sets.
00209     @relatesalso SgPointSet */
00210 inline SgPointSet operator-(const SgPointSet& L, const SgPointSet& R)
00211 {
00212     return (SgPointSet(L) -= R);
00213 }
00214 
00215 /** Compute intersection between point sets.
00216     @relatesalso SgPointSet */
00217 inline SgPointSet operator&(const SgPointSet& L, const SgPointSet& R)
00218 {
00219     return (SgPointSet(L) &= R);
00220 }
00221 
00222 /** Compute union between point sets.
00223     @relatesalso SgPointSet */
00224 inline SgPointSet operator|(const SgPointSet& L, const SgPointSet& R)
00225 {
00226     return (SgPointSet(L) |= R);
00227 }
00228 
00229 /** Compute XOR between point sets.
00230     @relatesalso SgPointSet */
00231 inline SgPointSet operator^(const SgPointSet& L, const SgPointSet& R)
00232 {
00233     return (SgPointSet(L) ^= R);
00234 }
00235 
00236 inline SgPointSet::SgPointSet()
00237 {
00238 }
00239 
00240 inline SgPointSet::~SgPointSet()
00241 {
00242 }
00243 
00244 inline void SgPointSet::Swap(SgPointSet& other) throw()
00245 {
00246     std::swap(m_a, other.m_a);
00247 }
00248 
00249 inline SgPointSet& SgPointSet::operator-=(const SgPointSet& other)
00250 {
00251     m_a &= ~other.m_a;
00252     return (*this);
00253 }
00254 
00255 inline SgPointSet& SgPointSet::operator&=(const SgPointSet& other)
00256 {
00257     m_a &= other.m_a;
00258     return (*this);
00259 }
00260 
00261 inline SgPointSet& SgPointSet::operator|=(const SgPointSet& other)
00262 {
00263     m_a |= other.m_a;
00264     return (*this);
00265 }
00266 
00267 inline SgPointSet& SgPointSet::operator^=(const SgPointSet& other)
00268 {
00269     m_a ^= other.m_a;
00270     return (*this);
00271 }
00272 
00273 inline bool SgPointSet::operator==(const SgPointSet& other) const
00274 {
00275     return m_a == other.m_a;
00276 }
00277 
00278 inline bool SgPointSet::operator!=(const SgPointSet& other) const
00279 {
00280     return m_a != other.m_a;
00281 }
00282 
00283 inline const SgPointSet& SgPointSet::AllPoints(int boardSize)
00284 {
00285     return s_allPoints.Get(boardSize);
00286 }
00287 
00288 inline bool SgPointSet::Overlaps(const SgPointSet& other) const
00289 {
00290     return (m_a & other.m_a).any();
00291 }
00292 
00293 inline bool SgPointSet::MaxOverlap(const SgPointSet& other, int max) const
00294 {
00295     SgPointSet s(*this);
00296     s &= other;
00297     return s.Size() <= max;
00298 }
00299 
00300 inline bool SgPointSet::MinOverlap(const SgPointSet& s, int min) const
00301 {
00302     return ! MaxOverlap(s, min - 1);
00303 }
00304 
00305 inline bool SgPointSet::Disjoint(const SgPointSet& s) const
00306 {
00307     return ! Overlaps(s);
00308 }
00309 
00310 inline bool SgPointSet::AdjacentTo(SgPoint p) const
00311 {
00312     SG_ASSERT_BOARDRANGE(p);
00313     return Contains(p + SG_NS)
00314         || Contains(p - SG_NS)
00315         || Contains(p + SG_WE)
00316         || Contains(p - SG_WE);
00317 }
00318 
00319 inline bool SgPointSet::Adjacent8To(SgPoint p) const
00320 {
00321     SG_ASSERT_BOARDRANGE(p);
00322     return Contains(p + SG_NS) || Contains(p - SG_NS) || Contains(p + SG_WE)
00323         || Contains(p - SG_WE) || Contains(p + SG_NS + SG_WE)
00324         || Contains(p + SG_NS - SG_WE) || Contains(p - SG_NS + SG_WE)
00325         || Contains(p - SG_NS - SG_WE);
00326 }
00327 
00328 inline bool SgPointSet::SubsetOf(const SgPointSet& other) const
00329 {
00330     return (m_a & ~other.m_a).none();
00331 }
00332 
00333 inline bool SgPointSet::SupersetOf(const SgPointSet& other) const
00334 {
00335     return (other.m_a & ~m_a).none();
00336 }
00337 
00338 inline int SgPointSet::Size() const
00339 {
00340     return static_cast<int>(m_a.count());
00341 }
00342 
00343 inline bool SgPointSet::IsEmpty() const
00344 {
00345     return m_a.none();
00346 }
00347 
00348 inline bool SgPointSet::NonEmpty() const
00349 {
00350     return ! IsEmpty();
00351 }
00352 
00353 inline SgPointSet& SgPointSet::Exclude(SgPoint p)
00354 {
00355     SG_ASSERT_BOARDRANGE(p);
00356     m_a.reset(p); 
00357     return (*this);
00358 }
00359 
00360 inline SgPointSet& SgPointSet::Include(SgPoint p)
00361 {
00362     SG_ASSERT_BOARDRANGE(p);
00363     m_a.set(p);
00364     return (*this);
00365 }
00366 
00367 inline SgPointSet& SgPointSet::Clear()
00368 {
00369     m_a.reset();
00370     return *this;
00371 }
00372 
00373 inline SgPointSet& SgPointSet::Toggle(SgPoint p)
00374 {
00375     SG_ASSERT(p < static_cast<int>(m_a.size()));
00376     m_a.flip(p);
00377     return (*this);
00378 }
00379 
00380 inline bool SgPointSet::Contains(SgPoint p) const
00381 {
00382     return m_a.test(p);
00383 }
00384 
00385 inline bool SgPointSet::CheckedContains(SgPoint p, bool doRangeCheck,
00386                                         bool onBoardCheck) const
00387 {
00388     if (doRangeCheck)
00389     {   
00390         if (onBoardCheck)
00391             SG_ASSERT_BOARDRANGE(p);
00392         else
00393             // 1 larger for nbiterators
00394             SG_ASSERTRANGE(p, SgPointUtil::Pt(0, 0),
00395                            SgPointUtil::Pt(SG_MAX_SIZE + 1, SG_MAX_SIZE + 1));
00396     }
00397     return m_a.test(p);
00398 }
00399 
00400 inline bool SgPointSet::ContainsPoint(SgPoint p) const
00401 {
00402     return CheckedContains(p, true, true);
00403 }
00404 
00405 inline bool SgPointSet::operator[](SgPoint p) const
00406 {
00407     return Contains(p);
00408 }
00409 
00410 inline bool SgPointSet::NewMark(SgPoint p)
00411 {
00412     if (Contains(p))
00413         return false;
00414     else
00415     {
00416         Include(p);
00417         return true;
00418     }
00419 }
00420 
00421 inline SgPointSet SgPointSet::operator>>(int n) const
00422 {
00423     SgPointSet result(*this);
00424     result.m_a >>= n;
00425     return result;
00426 }
00427 
00428 inline SgPointSet SgPointSet::operator<<(int n) const
00429 {
00430     SgPointSet result(*this);
00431     result.m_a <<= n;
00432     return result;
00433 }
00434 
00435 //----------------------------------------------------------------------------
00436 
00437 /** Iterator to iterate through 'set'.
00438     Set may contain only board
00439     points, no 'Border' points. */
00440 class SgSetIterator
00441 {
00442 public:
00443     /** Set may contain only board points, no 'Border' points. */
00444     SgSetIterator(const SgPointSet& set);
00445     
00446     /** Advance the state of the iteration to the next element. */
00447     void operator++();
00448 
00449     /** Return the value of the current element. */
00450     SgPoint operator*() const;
00451 
00452     /** Return true if iteration is valid, otherwise false. */
00453     operator bool() const;
00454 
00455 private:
00456     const SgPointSet& m_set;
00457 
00458     int m_index;
00459 
00460     void FindNext();
00461 
00462     int Size() const;
00463 };
00464 
00465 inline SgSetIterator::SgSetIterator(const SgPointSet& set)
00466     : m_set(set),
00467       m_index(0)
00468 {
00469     FindNext();
00470 }
00471 
00472 inline void SgSetIterator::operator++()
00473 {
00474     SG_ASSERT(m_index < Size());
00475     FindNext();
00476 }
00477 
00478 inline SgPoint SgSetIterator::operator*() const
00479 {
00480     SG_ASSERT(m_index <= Size());
00481     SG_ASSERT_BOARDRANGE(m_index);
00482     SG_ASSERT(m_set.m_a.test(m_index));
00483     return m_index;
00484 }
00485 
00486 inline SgSetIterator::operator bool() const
00487 {
00488     return m_index < Size();
00489 }
00490 
00491 inline void SgSetIterator::FindNext()
00492 {
00493     int size = Size();
00494     do
00495     {
00496         ++m_index;
00497     }
00498     while (m_index < size && ! m_set.m_a.test(m_index));
00499 }
00500 
00501 inline int SgSetIterator::Size() const
00502 {
00503     return static_cast<int>(m_set.m_a.size());
00504 }
00505 
00506 //----------------------------------------------------------------------------
00507 
00508 /** Point set efficient for marking and testing.
00509     A SgSimpleSet is like a SgPointSet, except that it's more efficient at
00510     marking points and testing for marked points, while taking more time to
00511     clear, and not providing bit operations on the whole set. */
00512 class SgSimpleSet
00513 {
00514 public:
00515     SgSimpleSet();
00516 
00517     void Include(SgPoint p);
00518 
00519     void Exclude(SgPoint p);
00520 
00521     bool Contains(SgPoint p) const;
00522 
00523     void Clear();
00524 
00525     bool IsEmpty() const;
00526 
00527     bool NonEmpty() const;
00528 
00529     void GetPoints(SgPointSet* points) const;
00530 
00531     bool NewMark(SgPoint p);
00532 
00533 private:
00534     /** Marked points. */
00535     bool m_mark[SG_MAXPOINT];
00536 };
00537 
00538 inline SgSimpleSet::SgSimpleSet()
00539 {
00540     Clear();
00541 }
00542 
00543 
00544 inline void SgSimpleSet::Include(SgPoint p)
00545 {
00546     SG_ASSERT_BOARDRANGE(p);
00547     m_mark[p] = true;
00548 }
00549 
00550 inline void SgSimpleSet::Exclude(SgPoint p)
00551 {
00552     SG_ASSERT_BOARDRANGE(p);
00553     m_mark[p] = false;
00554 }
00555 
00556 inline bool SgSimpleSet::Contains(SgPoint p) const
00557 {
00558     return m_mark[p];
00559 }
00560 
00561 inline void SgSimpleSet::Clear()
00562 {
00563     std::memset(m_mark, 0, SG_MAXPOINT * sizeof(bool));
00564 }
00565 
00566 inline bool SgSimpleSet::IsEmpty() const
00567 {
00568     for (SgPoint p = 0; p < SG_MAXPOINT; ++p)
00569         if (Contains(p))
00570             return false;
00571     return true;
00572 }
00573 
00574 inline bool SgSimpleSet::NonEmpty() const
00575 {
00576     return ! IsEmpty();
00577 }
00578 
00579 inline void SgSimpleSet::GetPoints(SgPointSet* points) const
00580 {
00581     points->Clear();
00582     for (SgPoint p = 0; p < SG_MAXPOINT; ++p)
00583         if (Contains(p))
00584             points->Include(p);
00585 }
00586 
00587 inline bool SgSimpleSet::NewMark(SgPoint p)
00588 {
00589     if (Contains(p))
00590         return false;
00591     else
00592     {
00593         Include(p);
00594         return true;
00595     }
00596 }
00597 
00598 //----------------------------------------------------------------------------
00599 
00600 #endif // SG_POINTSET_H


Sun Mar 13 2011 Doxygen 1.7.1