Go to the documentation of this file.00001
00002
00003
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
00022
00023
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
00046 bool operator[](SgPoint p) const;
00047
00048 bool Disjoint(const SgPointSet& s) const;
00049
00050
00051 bool Adjacent(const SgPointSet& s) const;
00052
00053 bool Adjacent8To(SgPoint p) const;
00054
00055
00056 bool AdjacentOnlyTo(const SgPointSet& s, int boardSize) const;
00057
00058 bool AdjacentTo(SgPoint p) const;
00059
00060
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
00078 SgPointSet Border(int boardSize) const;
00079
00080
00081 SgPointSet Border8(int boardSize) const;
00082
00083
00084 SgPointSet BorderNoClip() const;
00085
00086
00087 SgPoint Center() const;
00088
00089
00090 bool CheckedContains(SgPoint p, bool doRangeCheck = true,
00091 bool onBoardCheck = false) const;
00092
00093 SgPointSet& Clear();
00094
00095
00096
00097 SgPointSet Component(SgPoint p) const;
00098
00099
00100 SgPointSet Component8(SgPoint p) const;
00101
00102
00103 SgPointSet ConnComp(SgPoint p) const;
00104
00105
00106 SgPointSet ConnComp8(SgPoint p) const;
00107
00108
00109
00110
00111 bool Contains(SgPoint p) const;
00112
00113
00114
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
00124 void Grow(int boardSize);
00125
00126
00127 void Grow(SgPointSet* newArea, int boardSize);
00128
00129
00130 void Grow8(int boardSize);
00131
00132 SgPointSet& Include(SgPoint p);
00133
00134
00135
00136
00137 bool IsConnected() const;
00138
00139
00140 bool Is8Connected() const;
00141
00142
00143 SgPointSet Kernel(int boardSize) const;
00144
00145
00146 bool MaxOverlap(const SgPointSet& other, int max) const;
00147
00148
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
00156
00157 SgPoint PointOf() const;
00158
00159
00160 bool SubsetOf(const SgPointSet& other) const;
00161
00162
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
00174
00175 bool IsCloseTo(SgPoint p) const;
00176
00177 private:
00178
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
00209
00210 inline SgPointSet operator-(const SgPointSet& L, const SgPointSet& R)
00211 {
00212 return (SgPointSet(L) -= R);
00213 }
00214
00215
00216
00217 inline SgPointSet operator&(const SgPointSet& L, const SgPointSet& R)
00218 {
00219 return (SgPointSet(L) &= R);
00220 }
00221
00222
00223
00224 inline SgPointSet operator|(const SgPointSet& L, const SgPointSet& R)
00225 {
00226 return (SgPointSet(L) |= R);
00227 }
00228
00229
00230
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
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
00438
00439
00440 class SgSetIterator
00441 {
00442 public:
00443
00444 SgSetIterator(const SgPointSet& set);
00445
00446
00447 void operator++();
00448
00449
00450 SgPoint operator*() const;
00451
00452
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
00509
00510
00511
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
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