00001 //---------------------------------------------------------------------------- 00002 /** @file SgRect.h 00003 Rectangle on the Go board. */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef SG_RECT_H 00007 #define SG_RECT_H 00008 00009 #include "SgPoint.h" 00010 00011 //---------------------------------------------------------------------------- 00012 00013 /** Rectangle on the Go board. 00014 top < bottom, coordinates grow from top to bottom. */ 00015 class SgRect 00016 { 00017 public: 00018 SgRect(); 00019 00020 SgRect(int left, int right, int top, int bottom) 00021 : m_left(left), 00022 m_right(right), 00023 m_top(top), 00024 m_bottom(bottom) 00025 { } 00026 00027 SgRect(const SgPoint& topleft, const SgPoint& bottomright) 00028 : m_left(SgPointUtil::Col(topleft)), 00029 m_right(SgPointUtil::Col(bottomright)), 00030 m_top(SgPointUtil::Row(topleft)), 00031 m_bottom(SgPointUtil::Row(bottomright)) 00032 { } 00033 00034 bool operator==(const SgRect& rhs) const 00035 { 00036 return m_left == rhs.m_left 00037 && m_right == rhs.m_right 00038 && m_top == rhs.m_top 00039 && m_bottom == rhs.m_bottom; 00040 } 00041 00042 void Set(int left, int right, int top, int bottom) 00043 { 00044 m_left = left; 00045 m_right = right; 00046 m_top = top; 00047 m_bottom = bottom; 00048 } 00049 00050 void MirrorX(int boardSize) 00051 { 00052 int temp = m_left; 00053 m_left = boardSize + 1 - m_right; 00054 m_right = boardSize + 1 - temp; 00055 } 00056 00057 void MirrorY(int boardSize) 00058 { 00059 int temp = m_top; 00060 m_top = boardSize + 1 - m_bottom; 00061 m_bottom = boardSize + 1 - temp; 00062 } 00063 00064 void SwapXY() 00065 { 00066 std::swap(m_top, m_left); 00067 std::swap(m_bottom, m_right); 00068 } 00069 00070 void Include(SgPoint p); 00071 00072 void Include(const SgRect& rect); 00073 00074 void Intersect(const SgRect& rect); 00075 00076 bool IsEmpty() const 00077 { 00078 // no points inside, see constructor 00079 return m_left > m_right; 00080 } 00081 00082 bool InRect(SgPoint p) const; 00083 00084 SgPoint Center() const; 00085 00086 bool Contains(SgPoint p) const 00087 { 00088 return InRect(p); 00089 } 00090 00091 bool Contains(const SgRect& rect) const; 00092 00093 bool Overlaps(const SgRect& rect) const; 00094 00095 void Expand(int margin); 00096 00097 int Left() const 00098 { 00099 return m_left; 00100 } 00101 00102 int Right() const 00103 { 00104 return m_right; 00105 } 00106 00107 int Top() const 00108 { 00109 return m_top; 00110 } 00111 00112 int Bottom() const 00113 { 00114 return m_bottom; 00115 } 00116 00117 int Width() const 00118 { 00119 SG_ASSERT(! IsEmpty()); 00120 return m_right - m_left + 1; 00121 } 00122 00123 int Height() const 00124 { 00125 SG_ASSERT(! IsEmpty()); 00126 return m_bottom - m_top + 1; 00127 } 00128 00129 int Area() const 00130 { 00131 return Width() * Height(); 00132 } 00133 00134 void IncLeft() 00135 { 00136 ++m_left; 00137 } 00138 00139 void DecRight() 00140 { 00141 --m_right; 00142 } 00143 00144 void IncTop() 00145 { 00146 ++m_top; 00147 } 00148 00149 void DecBottom() 00150 { 00151 --m_bottom; 00152 } 00153 00154 void SetLeft(int value) 00155 { 00156 m_left = value; 00157 } 00158 00159 void SetRight(int value) 00160 { 00161 m_right = value; 00162 } 00163 00164 void SetTop(int value) 00165 { 00166 m_top = value; 00167 } 00168 00169 void SetBottom(int value) 00170 { 00171 m_bottom = value; 00172 } 00173 00174 private: 00175 int m_left; 00176 00177 int m_right; 00178 00179 int m_top; 00180 00181 int m_bottom; 00182 }; 00183 00184 //---------------------------------------------------------------------------- 00185 00186 /** Iterator for rectangle on the Go board, based on SgRect object */ 00187 class SgRectIterator 00188 { 00189 public: 00190 00191 SgRectIterator(const SgRect& rect) 00192 : m_rect(rect), 00193 m_cursor(SgPointUtil::Pt(rect.Left(), rect.Top())), 00194 m_end(SgPointUtil::Pt(rect.Right(), rect.Bottom())) 00195 { } 00196 00197 /** Iterate through rectangle: left to right, top to bottom */ 00198 void operator++() 00199 { 00200 SG_ASSERT(m_rect.Contains(m_cursor)); 00201 if (SgPointUtil::Col(m_cursor) == m_rect.Right()) 00202 m_cursor += SG_NS + m_rect.Left() - m_rect.Right(); 00203 else 00204 m_cursor += SG_WE; 00205 } 00206 00207 /** Return the value of the current element. */ 00208 SgPoint operator*() const 00209 { 00210 return m_cursor; 00211 } 00212 00213 /** Return true if iteration is valid, otherwise false. */ 00214 operator bool() const 00215 { 00216 return m_cursor <= m_end; 00217 } 00218 00219 private: 00220 const SgRect& m_rect; 00221 00222 SgPoint m_cursor; 00223 00224 SgPoint m_end; 00225 }; 00226 00227 std::ostream& operator<<(std::ostream& stream, const SgRect& rect); 00228 00229 //---------------------------------------------------------------------------- 00230 00231 #endif // SG_RECT_H