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


17 Jun 2010 Doxygen 1.4.7