1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkVector.h 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 This software is distributed WITHOUT ANY WARRANTY; without even 11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. See the above copyright notice for more information. 13 14 =========================================================================*/ 15 16 /** 17 * @class vtkRect 18 * @brief templated base type for storage of 2D rectangles. 19 * 20 * 21 * This class is a templated data type for storing and manipulating rectangles. 22 * The memory layout is a contiguous array of the specified type, such that a 23 * float[4] can be cast to a vtkRectf and manipulated. Also a float[12] could 24 * be cast and used as a vtkRectf[3]. 25 */ 26 27 #ifndef vtkRect_h 28 #define vtkRect_h 29 30 #include "vtkVector.h" 31 32 #include "vtkMath.h" // for Min, Max 33 34 template <typename T> 35 class vtkRect : public vtkVector<T, 4> 36 { 37 public: 38 vtkRect() = default; 39 vtkRect(const T & x,const T & y,const T & width,const T & height)40 vtkRect(const T& x, const T& y, const T& width, const T& height) 41 { 42 this->Data[0] = x; 43 this->Data[1] = y; 44 this->Data[2] = width; 45 this->Data[3] = height; 46 } 47 vtkRect(const T * init)48 explicit vtkRect(const T* init) 49 : vtkVector<T, 4>(init) 50 { 51 } 52 53 ///@{ 54 /** 55 * Set the x, y components of the rectangle, and the width/height. 56 */ Set(const T & x,const T & y,const T & width,const T & height)57 void Set(const T& x, const T& y, const T& width, const T& height) 58 { 59 this->Data[0] = x; 60 this->Data[1] = y; 61 this->Data[2] = width; 62 this->Data[3] = height; 63 } 64 ///@} 65 66 /** 67 * Set the x component of the rectangle bottom corner, i.e. element 0. 68 */ SetX(const T & x)69 void SetX(const T& x) { this->Data[0] = x; } 70 71 /** 72 * Get the x component of the rectangle bottom corner, i.e. element 0. 73 */ GetX()74 const T& GetX() const { return this->Data[0]; } 75 76 /** 77 * Set the y component of the rectangle bottom corner, i.e. element 1. 78 */ SetY(const T & y)79 void SetY(const T& y) { this->Data[1] = y; } 80 81 /** 82 * Get the y component of the rectangle bottom corner, i.e. element 1. 83 */ GetY()84 const T& GetY() const { return this->Data[1]; } 85 86 /** 87 * Set the width of the rectanle, i.e. element 2. 88 */ SetWidth(const T & width)89 void SetWidth(const T& width) { this->Data[2] = width; } 90 91 /** 92 * Get the width of the rectangle, i.e. element 2. 93 */ GetWidth()94 const T& GetWidth() const { return this->Data[2]; } 95 96 /** 97 * Set the height of the rectangle, i.e. element 3. 98 */ SetHeight(const T & height)99 void SetHeight(const T& height) { this->Data[3] = height; } 100 101 /** 102 * Get the height of the rectangle, i.e. element 3. 103 */ GetHeight()104 const T& GetHeight() const { return this->Data[3]; } 105 106 /** 107 * Get the left boundary of the rectangle along the X direction. 108 */ GetLeft()109 const T& GetLeft() const { return this->Data[0]; } 110 111 /** 112 * Get the right boundary of the rectangle along the X direction. 113 */ GetRight()114 T GetRight() const { return this->Data[0] + this->Data[2]; } 115 116 /** 117 * Get the top boundary of the rectangle along the Y direction. 118 */ GetTop()119 T GetTop() const { return this->Data[1] + this->Data[3]; } 120 121 /** 122 * Get the bottom boundary of the rectangle along the Y direction. 123 */ GetBottom()124 const T& GetBottom() const { return this->Data[1]; } 125 126 /** 127 * Get the bottom left corner of the rect as a vtkVector. 128 */ GetBottomLeft()129 vtkVector2<T> GetBottomLeft() const { return vtkVector2<T>(this->GetLeft(), this->GetBottom()); } 130 131 /** 132 * Get the top left corner of the rect as a vtkVector. 133 */ GetTopLeft()134 vtkVector<T, 2> GetTopLeft() const { return vtkVector2<T>(this->GetLeft(), this->GetTop()); } 135 136 /** 137 * Get the bottom right corner of the rect as a vtkVector. 138 */ GetBottomRight()139 vtkVector<T, 2> GetBottomRight() const 140 { 141 return vtkVector2<T>(this->GetRight(), this->GetBottom()); 142 } 143 144 /** 145 * Get the bottom left corner of the rect as a vtkVector. 146 */ GetTopRight()147 vtkVector<T, 2> GetTopRight() const { return vtkVector2<T>(this->GetRight(), this->GetTop()); } 148 149 ///@{ 150 /** 151 * Expand this rect to contain the point passed in. 152 */ AddPoint(const T point[2])153 void AddPoint(const T point[2]) 154 { 155 // This code is written like this to ensure that adding a point gives 156 // exactly the same result as AddRect(vtkRect(x,y,0,0) 157 if (point[0] < this->GetX()) 158 { 159 T dx = this->GetX() - point[0]; 160 this->SetX(point[0]); 161 this->SetWidth(dx + this->GetWidth()); 162 } 163 else if (point[0] > this->GetX()) 164 { 165 // this->GetX() is already correct 166 T dx = point[0] - this->GetX(); 167 this->SetWidth(vtkMath::Max(dx, this->GetWidth())); 168 } 169 ///@} 170 171 if (point[1] < this->GetY()) 172 { 173 T dy = this->GetY() - point[1]; 174 this->SetY(point[1]); 175 this->SetHeight(dy + this->GetHeight()); 176 } 177 else if (point[1] > this->GetY()) 178 { 179 // this->GetY() is already correct 180 T dy = point[1] - this->GetY(); 181 this->SetHeight(vtkMath::Max(dy, this->GetHeight())); 182 } 183 } 184 185 ///@{ 186 /** 187 * Expand this rect to contain the point passed in. 188 */ AddPoint(T x,T y)189 void AddPoint(T x, T y) 190 { 191 T point[2] = { x, y }; 192 this->AddPoint(point); 193 } 194 ///@} 195 196 ///@{ 197 /** 198 * Expand this rect to contain the rect passed in. 199 */ AddRect(const vtkRect<T> & rect)200 void AddRect(const vtkRect<T>& rect) 201 { 202 if (rect.GetX() < this->GetX()) 203 { 204 T dx = this->GetX() - rect.GetX(); 205 this->SetX(rect.GetX()); 206 this->SetWidth(vtkMath::Max(dx + this->GetWidth(), rect.GetWidth())); 207 } 208 else if (rect.GetX() > this->GetX()) 209 { 210 T dx = rect.GetX() - this->GetX(); 211 // this->GetX() is already correct 212 this->SetWidth(vtkMath::Max(dx + rect.GetWidth(), this->GetWidth())); 213 } 214 else 215 { 216 // this->GetX() is already correct 217 this->SetWidth(vtkMath::Max(rect.GetWidth(), this->GetWidth())); 218 } 219 ///@} 220 221 if (rect.GetY() < this->GetY()) 222 { 223 T dy = this->GetY() - rect.GetY(); 224 this->SetY(rect.GetY()); 225 this->SetHeight(vtkMath::Max(dy + this->GetHeight(), rect.GetHeight())); 226 } 227 else if (rect.GetY() > this->GetY()) 228 { 229 T dy = rect.GetY() - this->GetY(); 230 // this->GetY() is already correct 231 this->SetHeight(vtkMath::Max(dy + rect.GetHeight(), this->GetHeight())); 232 } 233 else 234 { 235 // this->GetY() is already correct 236 this->SetHeight(vtkMath::Max(rect.GetHeight(), this->GetHeight())); 237 } 238 } 239 240 /** 241 * Returns true if the rect argument overlaps this rect. 242 * If the upper bound of one rect is equal to the lower bound of 243 * the other rect, then this will return false (in that case, the 244 * rects would be considered to be adjacent but not overlapping). 245 */ IntersectsWith(const vtkRect<T> & rect)246 bool IntersectsWith(const vtkRect<T>& rect) const 247 { 248 bool intersects = true; 249 250 if (rect.GetX() < this->GetX()) 251 { 252 T dx = this->GetX() - rect.GetX(); 253 intersects &= (dx < rect.GetWidth()); 254 } 255 else if (rect.GetX() > this->GetX()) 256 { 257 T dx = rect.GetX() - this->GetX(); 258 intersects &= (dx < this->GetWidth()); 259 } 260 261 if (rect.GetY() < this->GetY()) 262 { 263 T dy = this->GetY() - rect.GetY(); 264 intersects &= (dy < rect.GetHeight()); 265 } 266 else if (rect.GetY() > this->GetY()) 267 { 268 T dy = rect.GetY() - this->GetY(); 269 intersects &= (dy < this->GetHeight()); 270 } 271 272 return intersects; 273 } 274 275 /** 276 * Move the rectangle, moving the bottom-left corner 277 * to the given position. The rectangles size remains unchanged. 278 */ MoveTo(T x,T y)279 void MoveTo(T x, T y) 280 { 281 this->Data[0] = x; 282 this->Data[1] = y; 283 } 284 285 /** 286 * Intersect with `other` rectangle. If `this->IntersectsWith(other)` is true, 287 * this method will update this rect to the intersection of `this` and 288 * `other` and return true. If `this->IntersectsWith(other)` returns false, 289 * then this method will return false leaving this rect unchanged. 290 * 291 * Returns true if the intersection was performed otherwise false. 292 */ Intersect(const vtkRect<T> & other)293 bool Intersect(const vtkRect<T>& other) 294 { 295 if (this->IntersectsWith(other)) 296 { 297 const T left = vtkMath::Max(this->GetLeft(), other.GetLeft()); 298 const T bottom = vtkMath::Max(this->GetBottom(), other.GetBottom()); 299 const T right = vtkMath::Min(this->GetRight(), other.GetRight()); 300 const T top = vtkMath::Min(this->GetTop(), other.GetTop()); 301 302 this->Data[0] = left; 303 this->Data[1] = bottom; 304 this->Data[2] = (right - left); 305 this->Data[3] = (top - bottom); 306 return true; 307 } 308 return false; 309 } 310 311 /** 312 * Returns the center of the rect as a vtkVector2d. 313 */ GetCenter()314 vtkVector2d GetCenter() const 315 { 316 return vtkVector2d( 317 this->GetX() + 0.5 * this->GetWidth(), this->GetY() + 0.5 * this->GetHeight()); 318 } 319 }; 320 321 class vtkRecti : public vtkRect<int> 322 { 323 public: 324 vtkRecti() = default; vtkRecti(int x,int y,int width,int height)325 vtkRecti(int x, int y, int width, int height) 326 : vtkRect<int>(x, y, width, height) 327 { 328 } vtkRecti(const int * init)329 explicit vtkRecti(const int* init) 330 : vtkRect<int>(init) 331 { 332 } 333 }; 334 335 class vtkRectf : public vtkRect<float> 336 { 337 public: 338 vtkRectf() = default; vtkRectf(float x,float y,float width,float height)339 vtkRectf(float x, float y, float width, float height) 340 : vtkRect<float>(x, y, width, height) 341 { 342 } vtkRectf(const float * init)343 explicit vtkRectf(const float* init) 344 : vtkRect<float>(init) 345 { 346 } 347 }; 348 349 class vtkRectd : public vtkRect<double> 350 { 351 public: 352 vtkRectd() = default; vtkRectd(double x,double y,double width,double height)353 vtkRectd(double x, double y, double width, double height) 354 : vtkRect<double>(x, y, width, height) 355 { 356 } vtkRectd(const double * init)357 explicit vtkRectd(const double* init) 358 : vtkRect<double>(init) 359 { 360 } 361 }; 362 363 #endif // vtkRect_h 364 // VTK-HeaderTest-Exclude: vtkRect.h 365