Go to the documentation of this file.00001
00002
00003
00004
00005 #include "SgSystem.h"
00006 #include "SgPointSet.h"
00007
00008 #include <algorithm>
00009 #include <iostream>
00010 #include "SgNbIterator.h"
00011
00012 using namespace std;
00013
00014
00015
00016 namespace {
00017
00018 int MaxDistance(SgPoint p1, SgPoint p2)
00019 {
00020 return max(abs(SgPointUtil::Row(p1) - SgPointUtil::Row(p2)),
00021 abs(SgPointUtil::Col(p1) - SgPointUtil::Col(p2)));
00022 }
00023
00024 }
00025
00026
00027
00028 SgPointSet::PrecompAllPoints::PrecompAllPoints()
00029 {
00030 for (int size = SG_MIN_SIZE; size <= SG_MAX_SIZE; ++size)
00031 {
00032 m_allPoints[size].reset(new SgPointSet());
00033 for (int col = 1; col <= size; ++col)
00034 for (int row = 1; row <= size; ++row)
00035 m_allPoints[size]->Include(SgPointUtil::Pt(col, row));
00036 }
00037 }
00038
00039
00040
00041 SgPointSet::PrecompAllPoints SgPointSet::s_allPoints;
00042
00043 SgPointSet SgPointSet::Border(int boardSize) const
00044 {
00045 return (BorderNoClip() & AllPoints(boardSize));
00046 }
00047
00048 SgPointSet SgPointSet::BorderNoClip() const
00049 {
00050 SgPointSet bd = (*this >> SG_NS);
00051 bd |= (*this << SG_NS);
00052 bd |= (*this >> SG_WE);
00053 bd |= (*this << SG_WE);
00054 bd -= (*this);
00055 return bd;
00056 }
00057
00058 SgPointSet SgPointSet::Component(SgPoint p) const
00059 {
00060 SgPointSet set1, set2;
00061 set1.Include(p);
00062 SgPointSet* a = &set1, *b = &set2;
00063 do
00064 {
00065 *b = *a | (a->BorderNoClip() & (*this));
00066 swap(a, b);
00067 } while (set1 != set2);
00068 return set1;
00069 }
00070
00071 SgPointSet SgPointSet::ConnComp(SgPoint p) const
00072 {
00073
00074 SgPointSet out, in = (*this);
00075 SgPoint stack[SG_MAXPOINT];
00076 out.Include(p);
00077 in.Exclude(p);
00078 int current = 0;
00079 stack[current] = p;
00080 while (current >= 0)
00081 {
00082 SgPoint q = stack[current--];
00083 for (SgNb4Iterator it(q); it; ++it)
00084 {
00085 SgPoint nb = *it;
00086 if (in.Contains(nb))
00087 {
00088 out.Include(nb);
00089 in.Exclude(nb);
00090 stack[++current] = nb;
00091 }
00092 }
00093 }
00094 return out;
00095 }
00096
00097 SgPointSet SgPointSet::ConnComp8(SgPoint p) const
00098 {
00099 SG_ASSERT(Contains(p));
00100 SgPointSet out, in = (*this);
00101 SgPoint stack[SG_MAXPOINT];
00102 out.Include(p);
00103 in.Exclude(p);
00104 int current = 0;
00105 stack[current] = p;
00106 while (current >= 0)
00107 {
00108 SgPoint q = stack[current--];
00109 for (SgNb8Iterator it(q); it; ++it)
00110 {
00111 SgPoint nb = *it;
00112 if (in.Contains(nb))
00113 {
00114 out.Include(nb);
00115 in.Exclude(nb);
00116 stack[++current] = nb;
00117 }
00118 }
00119 }
00120 SG_ASSERT(SupersetOf(out));
00121 return out;
00122 }
00123
00124 SgPointSet& SgPointSet::Exclude(const SgVector<SgPoint>& vector)
00125 {
00126 for (SgVectorIterator<SgPoint> it(vector); it; ++it)
00127 Exclude(*it);
00128 return (*this);
00129 }
00130
00131 SgPointSet::SgPointSet(const SgVector<SgPoint>& vector)
00132 {
00133 Clear();
00134 for (SgVectorIterator<SgPoint> it(vector); it; ++it)
00135 Include(*it);
00136 }
00137
00138 void SgPointSet::ToVector(SgVector<SgPoint>* list) const
00139 {
00140 list->Clear();
00141 for (SgSetIterator si(*this); si; ++si)
00142 list->PushBack(*si);
00143 }
00144
00145 void SgPointSet::Write(ostream& out, int boardSize) const
00146 {
00147 for (int row = boardSize; row >= 1; --row)
00148 {
00149 for (int col = 1; col <= boardSize; ++col)
00150 out << (Contains(SgPointUtil::Pt(col, row)) ? '@' : '-');
00151 out << '\n';
00152 }
00153 }
00154
00155 void SgPointSet::Grow(int boardSize)
00156 {
00157 SgPointSet bd = (*this >> SG_NS);
00158 bd |= (*this << SG_NS);
00159 bd |= (*this >> SG_WE);
00160 bd |= (*this << SG_WE);
00161 bd &= AllPoints(boardSize);
00162 *this |= bd;
00163 }
00164
00165 void SgPointSet::Grow(SgPointSet* newArea, int boardSize)
00166 {
00167 *newArea = (*this >> SG_NS);
00168 *newArea |= (*this << SG_NS);
00169 *newArea |= (*this >> SG_WE);
00170 *newArea |= (*this << SG_WE);
00171 *newArea &= AllPoints(boardSize);
00172 *newArea ^= (*this);
00173 *this |= *newArea;
00174 }
00175
00176 void SgPointSet::Grow8(int boardSize)
00177 {
00178 SgPointSet bd = (*this >> SG_NS);
00179 bd |= (*this << SG_NS);
00180 bd |= (*this >> SG_WE);
00181 bd |= (*this << SG_WE);
00182 bd |= (*this >> (SG_NS + SG_WE));
00183 bd |= (*this << (SG_NS + SG_WE));
00184 bd |= (*this >> (SG_NS - SG_WE));
00185 bd |= (*this << (SG_NS - SG_WE));
00186 bd &= AllPoints(boardSize);
00187 *this |= bd;
00188 }
00189
00190 SgPointSet SgPointSet::Border8(int boardSize) const
00191 {
00192 SgPointSet bd = (*this >> SG_NS);
00193 bd |= (*this << SG_NS);
00194 bd |= (*this >> SG_WE);
00195 bd |= (*this << SG_WE);
00196 bd |= (*this >> (SG_NS + SG_WE));
00197 bd |= (*this << (SG_NS + SG_WE));
00198 bd |= (*this >> (SG_NS - SG_WE));
00199 bd |= (*this << (SG_NS - SG_WE));
00200 bd -= (*this);
00201 bd &= AllPoints(boardSize);
00202 return bd;
00203 }
00204
00205 bool SgPointSet::IsSize(int size) const
00206 {
00207 SG_ASSERT(size >= 0);
00208 return (Size() == size);
00209 }
00210
00211 bool SgPointSet::MinSetSize(int size) const
00212 {
00213 return Size() >= size;
00214 }
00215
00216 bool SgPointSet::MaxSetSize(int size) const
00217 {
00218 return Size() <= size;
00219 }
00220
00221 bool SgPointSet::Adjacent(const SgPointSet& s) const
00222 {
00223 return BorderNoClip().Overlaps(s);
00224 }
00225
00226 bool SgPointSet::AllAdjacentTo(const SgPointSet& s) const
00227 {
00228 return SubsetOf(s.BorderNoClip());
00229 }
00230
00231 bool SgPointSet::AdjacentOnlyTo(const SgPointSet& s, int boardSize) const
00232 {
00233 return Border(boardSize).SubsetOf(s);
00234 }
00235
00236 bool SgPointSet::IsCloseTo(SgPoint p) const
00237 {
00238 const int MAX_CLOSE_DISTANCE = 3;
00239 if (Contains(p))
00240 return true;
00241
00242 for (SgSetIterator it(*this); it; ++it)
00243 {
00244 if (MaxDistance(*it, p) <= MAX_CLOSE_DISTANCE)
00245 return true;
00246 }
00247 return false;
00248 }
00249
00250 SgPointSet SgPointSet::Kernel(int boardSize) const
00251 {
00252
00253
00254
00255 SgPointSet k = AllPoints(boardSize) - (*this);
00256 SgPointSet bd = (k >> SG_NS);
00257 bd |= (k << SG_NS);
00258 bd |= (k >> SG_WE);
00259 bd |= (k << SG_WE);
00260 return (*this) - bd;
00261 }
00262
00263 SgPoint SgPointSet::PointOf() const
00264 {
00265
00266 SgSetIterator it(*this);
00267 if (it)
00268 return *it;
00269 else
00270 return SG_NULLPOINT;
00271 }
00272
00273 SgPoint SgPointSet::Center() const
00274 {
00275 SgRect rect = EnclosingRect();
00276 if (rect.IsEmpty())
00277 return SG_NULLPOINT;
00278
00279 SgPoint idealCenter = rect.Center();
00280
00281 if (Contains(idealCenter))
00282 return idealCenter;
00283
00284 int minDist = 4 * SG_MAX_SIZE;
00285 SgPoint center = SG_NULLPOINT;
00286 for (SgSetIterator it(*this); it; ++it)
00287 {
00288 int dist =
00289 MaxDistance(*it, idealCenter)
00290 + SgPointUtil::Distance(*it, idealCenter);
00291 if (dist < minDist)
00292 {
00293 center = *it;
00294 minDist = dist;
00295 }
00296 }
00297 return center;
00298 }
00299
00300 SgRect SgPointSet::EnclosingRect() const
00301 {
00302 SgRect r;
00303 for (SgSetIterator it(*this); it; ++it)
00304 r.Include(*it);
00305 return r;
00306 }
00307
00308 bool SgPointSet::IsConnected() const
00309 {
00310 SgPoint p = PointOf();
00311 if (p == SG_NULLPOINT)
00312 return true;
00313 else
00314 return (Component(p) == (*this));
00315 }
00316
00317 bool SgPointSet::Is8Connected() const
00318 {
00319 SgPoint p = PointOf();
00320 if (p == SG_NULLPOINT)
00321 return true;
00322 else
00323 return (ConnComp8(p) == (*this));
00324 }
00325
00326
00327