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