00001
00002
00003
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
00023
00024
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
00048 bool operator[](SgPoint p) const;
00049
00050 bool Disjoint(const SgPointSet& s) const;
00051
00052
00053 bool Adjacent(const SgPointSet& s) const;
00054
00055 bool Adjacent8To(SgPoint p) const;
00056
00057
00058 bool AdjacentOnlyTo(const SgPointSet& s, int boardSize) const;
00059
00060 bool AdjacentTo(SgPoint p) const;
00061
00062
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
00080 SgPointSet Border(int boardSize) const;
00081
00082
00083 SgPointSet Border8(int boardSize) const;
00084
00085
00086 SgPointSet BorderNoClip() const;
00087
00088
00089 SgPoint Center() const;
00090
00091
00092 bool CheckedContains(SgPoint p, bool doRangeCheck = true,
00093 bool onBoardCheck = false) const;
00094
00095 SgPointSet& Clear();
00096
00097
00098
00099
00100 SgPointSet Component(SgPoint p) const;
00101
00102
00103 SgPointSet Component8(SgPoint p) const;
00104
00105
00106 SgPointSet ConnComp(SgPoint p) const;
00107
00108
00109 SgPointSet ConnComp8(SgPoint p) const;
00110
00111
00112
00113
00114
00115 bool Contains(SgPoint p) const;
00116
00117
00118
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
00129 void Grow(int boardSize);
00130
00131
00132 void Grow(SgPointSet* newArea, int boardSize);
00133
00134
00135 void Grow8(int boardSize);
00136
00137 SgPointSet& Include(SgPoint p);
00138
00139
00140
00141
00142
00143 bool IsConnected() const;
00144
00145
00146 bool Is8Connected() const;
00147
00148
00149 SgPointSet Kernel(int boardSize) const;
00150
00151
00152 bool MaxOverlap(const SgPointSet& other, int max) const;
00153
00154
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
00162
00163
00164 SgPoint PointOf() const;
00165
00166
00167 bool SubsetOf(const SgPointSet& other) const;
00168
00169
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
00181
00182
00183 bool IsCloseTo(SgPoint p) const;
00184
00185 private:
00186
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
00217
00218
00219 inline SgPointSet operator-(const SgPointSet& L, const SgPointSet& R)
00220 {
00221 return (SgPointSet(L) -= R);
00222 }
00223
00224
00225
00226
00227 inline SgPointSet operator&(const SgPointSet& L, const SgPointSet& R)
00228 {
00229 return (SgPointSet(L) &= R);
00230 }
00231
00232
00233
00234
00235 inline SgPointSet operator|(const SgPointSet& L, const SgPointSet& R)
00236 {
00237 return (SgPointSet(L) |= R);
00238 }
00239
00240
00241
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
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
00450
00451
00452
00453 class SgSetIterator
00454 {
00455 public:
00456
00457 SgSetIterator(const SgPointSet& set);
00458
00459
00460 void operator++();
00461
00462
00463 SgPoint operator*() const;
00464
00465
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
00522
00523
00524
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
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