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