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


17 Jun 2010 Doxygen 1.4.7