diff options
| author | manuel <manuel@mausz.at> | 2020-10-19 00:52:24 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2020-10-19 00:52:24 +0200 |
| commit | be933ef2241d79558f91796cc5b3a161f72ebf9c (patch) | |
| tree | fe3ab2f130e20c99001f2d7a81d610c78c96a3f4 /xbmc/utils/Geometry.h | |
| parent | 5f8335c1e49ce108ef3481863833c98efa00411b (diff) | |
| download | kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.gz kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.bz2 kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.zip | |
sync with upstream
Diffstat (limited to 'xbmc/utils/Geometry.h')
| -rw-r--r-- | xbmc/utils/Geometry.h | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/xbmc/utils/Geometry.h b/xbmc/utils/Geometry.h new file mode 100644 index 0000000..878905b --- /dev/null +++ b/xbmc/utils/Geometry.h | |||
| @@ -0,0 +1,484 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005-2018 Team Kodi | ||
| 3 | * This file is part of Kodi - https://kodi.tv | ||
| 4 | * | ||
| 5 | * SPDX-License-Identifier: GPL-2.0-or-later | ||
| 6 | * See LICENSES/README.md for more information. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #pragma once | ||
| 10 | |||
| 11 | #ifdef __GNUC__ | ||
| 12 | // under gcc, inline will only take place if optimizations are applied (-O). this will force inline even with optimizations. | ||
| 13 | #define XBMC_FORCE_INLINE __attribute__((always_inline)) | ||
| 14 | #else | ||
| 15 | #define XBMC_FORCE_INLINE | ||
| 16 | #endif | ||
| 17 | |||
| 18 | #include <algorithm> | ||
| 19 | #include <stdexcept> | ||
| 20 | #include <vector> | ||
| 21 | |||
| 22 | template <typename T> class CPointGen | ||
| 23 | { | ||
| 24 | public: | ||
| 25 | typedef CPointGen<T> this_type; | ||
| 26 | |||
| 27 | CPointGen() noexcept = default; | ||
| 28 | |||
| 29 | constexpr CPointGen(T a, T b) | ||
| 30 | : x{a}, y{b} | ||
| 31 | {} | ||
| 32 | |||
| 33 | template<class U> explicit constexpr CPointGen(const CPointGen<U>& rhs) | ||
| 34 | : x{static_cast<T> (rhs.x)}, y{static_cast<T> (rhs.y)} | ||
| 35 | {} | ||
| 36 | |||
| 37 | constexpr this_type operator+(const this_type &point) const | ||
| 38 | { | ||
| 39 | return {x + point.x, y + point.y}; | ||
| 40 | }; | ||
| 41 | |||
| 42 | this_type& operator+=(const this_type &point) | ||
| 43 | { | ||
| 44 | x += point.x; | ||
| 45 | y += point.y; | ||
| 46 | return *this; | ||
| 47 | }; | ||
| 48 | |||
| 49 | constexpr this_type operator-(const this_type &point) const | ||
| 50 | { | ||
| 51 | return {x - point.x, y - point.y}; | ||
| 52 | }; | ||
| 53 | |||
| 54 | this_type& operator-=(const this_type &point) | ||
| 55 | { | ||
| 56 | x -= point.x; | ||
| 57 | y -= point.y; | ||
| 58 | return *this; | ||
| 59 | }; | ||
| 60 | |||
| 61 | constexpr this_type operator*(T factor) const | ||
| 62 | { | ||
| 63 | return {x * factor, y * factor}; | ||
| 64 | } | ||
| 65 | |||
| 66 | this_type& operator*=(T factor) | ||
| 67 | { | ||
| 68 | x *= factor; | ||
| 69 | y *= factor; | ||
| 70 | return *this; | ||
| 71 | } | ||
| 72 | |||
| 73 | constexpr this_type operator/(T factor) const | ||
| 74 | { | ||
| 75 | return {x / factor, y / factor}; | ||
| 76 | } | ||
| 77 | |||
| 78 | this_type& operator/=(T factor) | ||
| 79 | { | ||
| 80 | x /= factor; | ||
| 81 | y /= factor; | ||
| 82 | return *this; | ||
| 83 | } | ||
| 84 | |||
| 85 | T x{}, y{}; | ||
| 86 | }; | ||
| 87 | |||
| 88 | template<typename T> | ||
| 89 | constexpr bool operator==(const CPointGen<T> &point1, const CPointGen<T> &point2) noexcept | ||
| 90 | { | ||
| 91 | return (point1.x == point2.x && point1.y == point2.y); | ||
| 92 | } | ||
| 93 | |||
| 94 | template<typename T> | ||
| 95 | constexpr bool operator!=(const CPointGen<T> &point1, const CPointGen<T> &point2) noexcept | ||
| 96 | { | ||
| 97 | return !(point1 == point2); | ||
| 98 | } | ||
| 99 | |||
| 100 | using CPoint = CPointGen<float>; | ||
| 101 | using CPointInt = CPointGen<int>; | ||
| 102 | |||
| 103 | |||
| 104 | /** | ||
| 105 | * Generic two-dimensional size representation | ||
| 106 | * | ||
| 107 | * Class invariant: width and height are both non-negative | ||
| 108 | * Throws std::out_of_range if invariant would be violated. The class | ||
| 109 | * is exception-safe. If modification would violate the invariant, the size | ||
| 110 | * is not changed. | ||
| 111 | */ | ||
| 112 | template <typename T> class CSizeGen | ||
| 113 | { | ||
| 114 | T m_w{}, m_h{}; | ||
| 115 | |||
| 116 | void CheckSet(T width, T height) | ||
| 117 | { | ||
| 118 | if (width < 0) | ||
| 119 | { | ||
| 120 | throw std::out_of_range("Size may not have negative width"); | ||
| 121 | } | ||
| 122 | if (height < 0) | ||
| 123 | { | ||
| 124 | throw std::out_of_range("Size may not have negative height"); | ||
| 125 | } | ||
| 126 | m_w = width; | ||
| 127 | m_h = height; | ||
| 128 | } | ||
| 129 | |||
| 130 | public: | ||
| 131 | typedef CSizeGen<T> this_type; | ||
| 132 | |||
| 133 | CSizeGen() noexcept = default; | ||
| 134 | |||
| 135 | CSizeGen(T width, T height) | ||
| 136 | { | ||
| 137 | CheckSet(width, height); | ||
| 138 | } | ||
| 139 | |||
| 140 | T Width() const | ||
| 141 | { | ||
| 142 | return m_w; | ||
| 143 | } | ||
| 144 | |||
| 145 | T Height() const | ||
| 146 | { | ||
| 147 | return m_h; | ||
| 148 | } | ||
| 149 | |||
| 150 | void SetWidth(T width) | ||
| 151 | { | ||
| 152 | CheckSet(width, m_h); | ||
| 153 | } | ||
| 154 | |||
| 155 | void SetHeight(T height) | ||
| 156 | { | ||
| 157 | CheckSet(m_w, height); | ||
| 158 | } | ||
| 159 | |||
| 160 | void Set(T width, T height) | ||
| 161 | { | ||
| 162 | CheckSet(width, height); | ||
| 163 | } | ||
| 164 | |||
| 165 | bool IsZero() const | ||
| 166 | { | ||
| 167 | return (m_w == static_cast<T> (0) && m_h == static_cast<T> (0)); | ||
| 168 | } | ||
| 169 | |||
| 170 | T Area() const | ||
| 171 | { | ||
| 172 | return m_w * m_h; | ||
| 173 | } | ||
| 174 | |||
| 175 | CPointGen<T> ToPoint() const | ||
| 176 | { | ||
| 177 | return {m_w, m_h}; | ||
| 178 | } | ||
| 179 | |||
| 180 | template<class U> explicit CSizeGen<T>(const CSizeGen<U>& rhs) | ||
| 181 | { | ||
| 182 | CheckSet(static_cast<T> (rhs.m_w), static_cast<T> (rhs.m_h)); | ||
| 183 | } | ||
| 184 | |||
| 185 | this_type operator+(const this_type& size) const | ||
| 186 | { | ||
| 187 | return {m_w + size.m_w, m_h + size.m_h}; | ||
| 188 | }; | ||
| 189 | |||
| 190 | this_type& operator+=(const this_type& size) | ||
| 191 | { | ||
| 192 | CheckSet(m_w + size.m_w, m_h + size.m_h); | ||
| 193 | return *this; | ||
| 194 | }; | ||
| 195 | |||
| 196 | this_type operator-(const this_type& size) const | ||
| 197 | { | ||
| 198 | return {m_w - size.m_w, m_h - size.m_h}; | ||
| 199 | }; | ||
| 200 | |||
| 201 | this_type& operator-=(const this_type& size) | ||
| 202 | { | ||
| 203 | CheckSet(m_w - size.m_w, m_h - size.m_h); | ||
| 204 | return *this; | ||
| 205 | }; | ||
| 206 | |||
| 207 | this_type operator*(T factor) const | ||
| 208 | { | ||
| 209 | return {m_w * factor, m_h * factor}; | ||
| 210 | } | ||
| 211 | |||
| 212 | this_type& operator*=(T factor) | ||
| 213 | { | ||
| 214 | CheckSet(m_w * factor, m_h * factor); | ||
| 215 | return *this; | ||
| 216 | } | ||
| 217 | |||
| 218 | this_type operator/(T factor) const | ||
| 219 | { | ||
| 220 | return {m_w / factor, m_h / factor}; | ||
| 221 | } | ||
| 222 | |||
| 223 | this_type& operator/=(T factor) | ||
| 224 | { | ||
| 225 | CheckSet(m_w / factor, m_h / factor); | ||
| 226 | return *this; | ||
| 227 | } | ||
| 228 | }; | ||
| 229 | |||
| 230 | template<typename T> | ||
| 231 | inline bool operator==(const CSizeGen<T>& size1, const CSizeGen<T>& size2) noexcept | ||
| 232 | { | ||
| 233 | return (size1.Width() == size2.Width() && size1.Height() == size2.Height()); | ||
| 234 | } | ||
| 235 | |||
| 236 | template<typename T> | ||
| 237 | inline bool operator!=(const CSizeGen<T>& size1, const CSizeGen<T>& size2) noexcept | ||
| 238 | { | ||
| 239 | return !(size1 == size2); | ||
| 240 | } | ||
| 241 | |||
| 242 | using CSize = CSizeGen<float>; | ||
| 243 | using CSizeInt = CSizeGen<int>; | ||
| 244 | |||
| 245 | |||
| 246 | template <typename T> class CRectGen | ||
| 247 | { | ||
| 248 | public: | ||
| 249 | typedef CRectGen<T> this_type; | ||
| 250 | typedef CPointGen<T> point_type; | ||
| 251 | typedef CSizeGen<T> size_type; | ||
| 252 | |||
| 253 | CRectGen() noexcept = default; | ||
| 254 | |||
| 255 | constexpr CRectGen(T left, T top, T right, T bottom) | ||
| 256 | : x1{left}, y1{top}, x2{right}, y2{bottom} | ||
| 257 | {} | ||
| 258 | |||
| 259 | constexpr CRectGen(const point_type &p1, const point_type &p2) | ||
| 260 | : x1{p1.x}, y1{p1.y}, x2{p2.x}, y2{p2.y} | ||
| 261 | {} | ||
| 262 | |||
| 263 | constexpr CRectGen(const point_type &origin, const size_type &size) | ||
| 264 | : x1{origin.x}, y1{origin.y}, x2{x1 + size.Width()}, y2{y1 + size.Height()} | ||
| 265 | {} | ||
| 266 | |||
| 267 | template<class U> explicit constexpr CRectGen(const CRectGen<U>& rhs) | ||
| 268 | : x1{static_cast<T> (rhs.x1)}, y1{static_cast<T> (rhs.y1)}, x2{static_cast<T> (rhs.x2)}, y2{static_cast<T> (rhs.y2)} | ||
| 269 | {} | ||
| 270 | |||
| 271 | void SetRect(T left, T top, T right, T bottom) | ||
| 272 | { | ||
| 273 | x1 = left; | ||
| 274 | y1 = top; | ||
| 275 | x2 = right; | ||
| 276 | y2 = bottom; | ||
| 277 | } | ||
| 278 | |||
| 279 | constexpr bool PtInRect(const point_type &point) const | ||
| 280 | { | ||
| 281 | return (x1 <= point.x && point.x <= x2 && y1 <= point.y && point.y <= y2); | ||
| 282 | }; | ||
| 283 | |||
| 284 | this_type& operator-=(const point_type &point) XBMC_FORCE_INLINE | ||
| 285 | { | ||
| 286 | x1 -= point.x; | ||
| 287 | y1 -= point.y; | ||
| 288 | x2 -= point.x; | ||
| 289 | y2 -= point.y; | ||
| 290 | return *this; | ||
| 291 | }; | ||
| 292 | |||
| 293 | constexpr this_type operator-(const point_type &point) const | ||
| 294 | { | ||
| 295 | return {x1 - point.x, y1 - point.y, x2 - point.x, y2 - point.y}; | ||
| 296 | } | ||
| 297 | |||
| 298 | this_type& operator+=(const point_type &point) XBMC_FORCE_INLINE | ||
| 299 | { | ||
| 300 | x1 += point.x; | ||
| 301 | y1 += point.y; | ||
| 302 | x2 += point.x; | ||
| 303 | y2 += point.y; | ||
| 304 | return *this; | ||
| 305 | }; | ||
| 306 | |||
| 307 | constexpr this_type operator+(const point_type &point) const | ||
| 308 | { | ||
| 309 | return {x1 + point.x, y1 + point.y, x2 + point.x, y2 + point.y}; | ||
| 310 | } | ||
| 311 | |||
| 312 | this_type& operator-=(const size_type &size) | ||
| 313 | { | ||
| 314 | x2 -= size.Width(); | ||
| 315 | y2 -= size.Height(); | ||
| 316 | return *this; | ||
| 317 | }; | ||
| 318 | |||
| 319 | constexpr this_type operator-(const size_type &size) const | ||
| 320 | { | ||
| 321 | return {x1, y1, x2 - size.Width(), y2 - size.Height()}; | ||
| 322 | } | ||
| 323 | |||
| 324 | this_type& operator+=(const size_type &size) | ||
| 325 | { | ||
| 326 | x2 += size.Width(); | ||
| 327 | y2 += size.Height(); | ||
| 328 | return *this; | ||
| 329 | }; | ||
| 330 | |||
| 331 | constexpr this_type operator+(const size_type &size) const | ||
| 332 | { | ||
| 333 | return {x1, y1, x2 + size.Width(), y2 + size.Height()}; | ||
| 334 | } | ||
| 335 | |||
| 336 | this_type& Intersect(const this_type &rect) | ||
| 337 | { | ||
| 338 | x1 = clamp_range(x1, rect.x1, rect.x2); | ||
| 339 | x2 = clamp_range(x2, rect.x1, rect.x2); | ||
| 340 | y1 = clamp_range(y1, rect.y1, rect.y2); | ||
| 341 | y2 = clamp_range(y2, rect.y1, rect.y2); | ||
| 342 | return *this; | ||
| 343 | }; | ||
| 344 | |||
| 345 | this_type& Union(const this_type &rect) | ||
| 346 | { | ||
| 347 | if (IsEmpty()) | ||
| 348 | *this = rect; | ||
| 349 | else if (!rect.IsEmpty()) | ||
| 350 | { | ||
| 351 | x1 = std::min(x1,rect.x1); | ||
| 352 | y1 = std::min(y1,rect.y1); | ||
| 353 | |||
| 354 | x2 = std::max(x2,rect.x2); | ||
| 355 | y2 = std::max(y2,rect.y2); | ||
| 356 | } | ||
| 357 | |||
| 358 | return *this; | ||
| 359 | }; | ||
| 360 | |||
| 361 | constexpr bool IsEmpty() const XBMC_FORCE_INLINE | ||
| 362 | { | ||
| 363 | return (x2 - x1) * (y2 - y1) == 0; | ||
| 364 | }; | ||
| 365 | |||
| 366 | constexpr point_type P1() const XBMC_FORCE_INLINE | ||
| 367 | { | ||
| 368 | return {x1, y1}; | ||
| 369 | } | ||
| 370 | |||
| 371 | constexpr point_type P2() const XBMC_FORCE_INLINE | ||
| 372 | { | ||
| 373 | return {x2, y2}; | ||
| 374 | } | ||
| 375 | |||
| 376 | constexpr T Width() const XBMC_FORCE_INLINE | ||
| 377 | { | ||
| 378 | return x2 - x1; | ||
| 379 | }; | ||
| 380 | |||
| 381 | constexpr T Height() const XBMC_FORCE_INLINE | ||
| 382 | { | ||
| 383 | return y2 - y1; | ||
| 384 | }; | ||
| 385 | |||
| 386 | constexpr T Area() const XBMC_FORCE_INLINE | ||
| 387 | { | ||
| 388 | return Width() * Height(); | ||
| 389 | }; | ||
| 390 | |||
| 391 | size_type ToSize() const | ||
| 392 | { | ||
| 393 | return {Width(), Height()}; | ||
| 394 | }; | ||
| 395 | |||
| 396 | std::vector<this_type> SubtractRect(this_type splitterRect) | ||
| 397 | { | ||
| 398 | std::vector<this_type> newRectanglesList; | ||
| 399 | this_type intersection = splitterRect.Intersect(*this); | ||
| 400 | |||
| 401 | if (!intersection.IsEmpty()) | ||
| 402 | { | ||
| 403 | this_type add; | ||
| 404 | |||
| 405 | // add rect above intersection if not empty | ||
| 406 | add = this_type(x1, y1, x2, intersection.y1); | ||
| 407 | if (!add.IsEmpty()) | ||
| 408 | newRectanglesList.push_back(add); | ||
| 409 | |||
| 410 | // add rect below intersection if not empty | ||
| 411 | add = this_type(x1, intersection.y2, x2, y2); | ||
| 412 | if (!add.IsEmpty()) | ||
| 413 | newRectanglesList.push_back(add); | ||
| 414 | |||
| 415 | // add rect left intersection if not empty | ||
| 416 | add = this_type(x1, intersection.y1, intersection.x1, intersection.y2); | ||
| 417 | if (!add.IsEmpty()) | ||
| 418 | newRectanglesList.push_back(add); | ||
| 419 | |||
| 420 | // add rect right intersection if not empty | ||
| 421 | add = this_type(intersection.x2, intersection.y1, x2, intersection.y2); | ||
| 422 | if (!add.IsEmpty()) | ||
| 423 | newRectanglesList.push_back(add); | ||
| 424 | } | ||
| 425 | else | ||
| 426 | { | ||
| 427 | newRectanglesList.push_back(*this); | ||
| 428 | } | ||
| 429 | |||
| 430 | return newRectanglesList; | ||
| 431 | } | ||
| 432 | |||
| 433 | std::vector<this_type> SubtractRects(std::vector<this_type> intersectionList) | ||
| 434 | { | ||
| 435 | std::vector<this_type> fragmentsList; | ||
| 436 | fragmentsList.push_back(*this); | ||
| 437 | |||
| 438 | for (typename std::vector<this_type>::iterator splitter = intersectionList.begin(); splitter != intersectionList.end(); ++splitter) | ||
| 439 | { | ||
| 440 | typename std::vector<this_type> toAddList; | ||
| 441 | |||
| 442 | for (typename std::vector<this_type>::iterator fragment = fragmentsList.begin(); fragment != fragmentsList.end(); ++fragment) | ||
| 443 | { | ||
| 444 | std::vector<this_type> newFragmentsList = fragment->SubtractRect(*splitter); | ||
| 445 | toAddList.insert(toAddList.end(), newFragmentsList.begin(), newFragmentsList.end()); | ||
| 446 | } | ||
| 447 | |||
| 448 | fragmentsList.clear(); | ||
| 449 | fragmentsList.insert(fragmentsList.end(), toAddList.begin(), toAddList.end()); | ||
| 450 | } | ||
| 451 | |||
| 452 | return fragmentsList; | ||
| 453 | } | ||
| 454 | |||
| 455 | void GetQuad(point_type (&points)[4]) | ||
| 456 | { | ||
| 457 | points[0] = { x1, y1 }; | ||
| 458 | points[1] = { x2, y1 }; | ||
| 459 | points[2] = { x2, y2 }; | ||
| 460 | points[3] = { x1, y2 }; | ||
| 461 | } | ||
| 462 | |||
| 463 | T x1{}, y1{}, x2{}, y2{}; | ||
| 464 | private: | ||
| 465 | static constexpr T clamp_range(T x, T l, T h) XBMC_FORCE_INLINE | ||
| 466 | { | ||
| 467 | return (x > h) ? h : ((x < l) ? l : x); | ||
| 468 | } | ||
| 469 | }; | ||
| 470 | |||
| 471 | template<typename T> | ||
| 472 | constexpr bool operator==(const CRectGen<T> &rect1, const CRectGen<T> &rect2) noexcept | ||
| 473 | { | ||
| 474 | return (rect1.x1 == rect2.x1 && rect1.y1 == rect2.y1 && rect1.x2 == rect2.x2 && rect1.y2 == rect2.y2); | ||
| 475 | } | ||
| 476 | |||
| 477 | template<typename T> | ||
| 478 | constexpr bool operator!=(const CRectGen<T> &rect1, const CRectGen<T> &rect2) noexcept | ||
| 479 | { | ||
| 480 | return !(rect1 == rect2); | ||
| 481 | } | ||
| 482 | |||
| 483 | using CRect = CRectGen<float>; | ||
| 484 | using CRectInt = CRectGen<int>; | ||
