Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgPointSet.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgPointSet.cpp */
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 } // namespace
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); // swap pointers, not sets.
00067     } while (set1 != set2);
00068     return set1;
00069 }
00070 
00071 SgPointSet SgPointSet::ConnComp(SgPoint p) const
00072 {
00073     // alternative connected component algorithm for large diameter sets
00074     SgPointSet out, in = (*this);
00075     SgPoint stack[SG_MAXPOINT]; // AR: use Stack template
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]; // AR: use Stack template
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     // Kernel is computed by growing the complement,
00253     // and subtracting that from the given set.
00254     // AR: would direct implementation be faster?
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     // slight misuse of iterator, only see if can get one point
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 { // AR: slow.
00319     SgPoint p = PointOf();
00320     if (p == SG_NULLPOINT)
00321         return true; // Empty set
00322     else 
00323         return (ConnComp8(p) == (*this));
00324 }
00325 
00326 //----------------------------------------------------------------------------
00327 


Sun Mar 13 2011 Doxygen 1.7.1