DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

Geometry.cpp (22638B)


      1 /*
      2  * DISTRHO Plugin Framework (DPF)
      3  * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
      4  *
      5  * Permission to use, copy, modify, and/or distribute this software for any purpose with
      6  * or without fee is hereby granted, provided that the above copyright notice and this
      7  * permission notice appear in all copies.
      8  *
      9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
     10  * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
     11  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
     12  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
     13  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #ifdef _MSC_VER
     18 # pragma warning(disable:4661) /* instantiated template classes whose methods are defined elsewhere */
     19 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
     20 # pragma GCC diagnostic push
     21 # pragma GCC diagnostic ignored "-Wconversion"
     22 #endif
     23 
     24 #include "../Geometry.hpp"
     25 
     26 #include <cmath>
     27 
     28 START_NAMESPACE_DGL
     29 
     30 static const float M_2PIf = 3.14159265358979323846f*2.0f;
     31 
     32 // -----------------------------------------------------------------------
     33 // Point
     34 
     35 template<typename T>
     36 Point<T>::Point() noexcept
     37     : x(0),
     38       y(0) {}
     39 
     40 template<typename T>
     41 Point<T>::Point(const T& x2, const T& y2) noexcept
     42     : x(x2),
     43       y(y2) {}
     44 
     45 template<typename T>
     46 Point<T>::Point(const Point<T>& pos) noexcept
     47     : x(pos.x),
     48       y(pos.y) {}
     49 
     50 template<typename T>
     51 const T& Point<T>::getX() const noexcept
     52 {
     53     return x;
     54 }
     55 
     56 template<typename T>
     57 const T& Point<T>::getY() const noexcept
     58 {
     59     return y;
     60 }
     61 
     62 template<typename T>
     63 void Point<T>::setX(const T& x2) noexcept
     64 {
     65     x = x2;
     66 }
     67 
     68 template<typename T>
     69 void Point<T>::setY(const T& y2) noexcept
     70 {
     71     y = y2;
     72 }
     73 
     74 template<typename T>
     75 void Point<T>::setPos(const T& x2, const T& y2) noexcept
     76 {
     77     x = x2;
     78     y = y2;
     79 }
     80 
     81 template<typename T>
     82 void Point<T>::setPos(const Point<T>& pos) noexcept
     83 {
     84     x = pos.x;
     85     y = pos.y;
     86 }
     87 
     88 template<typename T>
     89 void Point<T>::moveBy(const T& x2, const T& y2) noexcept
     90 {
     91     x = static_cast<T>(x+x2);
     92     y = static_cast<T>(y+y2);
     93 }
     94 
     95 template<typename T>
     96 void Point<T>::moveBy(const Point<T>& pos) noexcept
     97 {
     98     x = static_cast<T>(x+pos.x);
     99     y = static_cast<T>(y+pos.y);
    100 }
    101 
    102 template<typename T>
    103 bool Point<T>::isZero() const noexcept
    104 {
    105     return x == 0 && y == 0;
    106 }
    107 
    108 template<typename T>
    109 bool Point<T>::isNotZero() const noexcept
    110 {
    111     return x != 0 || y != 0;
    112 }
    113 
    114 template<typename T>
    115 Point<T> Point<T>::operator+(const Point<T>& pos) noexcept
    116 {
    117     return Point<T>(x+pos.x, y+pos.y);
    118 }
    119 
    120 template<typename T>
    121 Point<T> Point<T>::operator-(const Point<T>& pos) noexcept
    122 {
    123     return Point<T>(x-pos.x, y-pos.y);
    124 }
    125 
    126 template<typename T>
    127 Point<T>& Point<T>::operator=(const Point<T>& pos) noexcept
    128 {
    129     x = pos.x;
    130     y = pos.y;
    131     return *this;
    132 }
    133 
    134 template<typename T>
    135 Point<T>& Point<T>::operator+=(const Point<T>& pos) noexcept
    136 {
    137     x = static_cast<T>(x+pos.x);
    138     y = static_cast<T>(y+pos.y);
    139     return *this;
    140 }
    141 
    142 template<typename T>
    143 Point<T>& Point<T>::operator-=(const Point<T>& pos) noexcept
    144 {
    145     x = static_cast<T>(x-pos.x);
    146     y = static_cast<T>(y-pos.y);
    147     return *this;
    148 }
    149 
    150 template<typename T>
    151 bool Point<T>::operator==(const Point<T>& pos) const noexcept
    152 {
    153     return (x == pos.x && y == pos.y);
    154 }
    155 
    156 template<typename T>
    157 bool Point<T>::operator!=(const Point<T>& pos) const noexcept
    158 {
    159     return (x != pos.x || y != pos.y);
    160 }
    161 
    162 // -----------------------------------------------------------------------
    163 // Size
    164 
    165 template<typename T>
    166 Size<T>::Size() noexcept
    167     : fWidth(0),
    168       fHeight(0) {}
    169 
    170 template<typename T>
    171 Size<T>::Size(const T& width, const T& height) noexcept
    172     : fWidth(width),
    173       fHeight(height) {}
    174 
    175 template<typename T>
    176 Size<T>::Size(const Size<T>& size) noexcept
    177     : fWidth(size.fWidth),
    178       fHeight(size.fHeight) {}
    179 
    180 template<typename T>
    181 const T& Size<T>::getWidth() const noexcept
    182 {
    183     return fWidth;
    184 }
    185 
    186 template<typename T>
    187 const T& Size<T>::getHeight() const noexcept
    188 {
    189     return fHeight;
    190 }
    191 
    192 template<typename T>
    193 void Size<T>::setWidth(const T& width) noexcept
    194 {
    195     fWidth = width;
    196 }
    197 
    198 template<typename T>
    199 void Size<T>::setHeight(const T& height) noexcept
    200 {
    201     fHeight = height;
    202 }
    203 
    204 template<typename T>
    205 void Size<T>::setSize(const T& width, const T& height) noexcept
    206 {
    207     fWidth  = width;
    208     fHeight = height;
    209 }
    210 
    211 template<typename T>
    212 void Size<T>::setSize(const Size<T>& size) noexcept
    213 {
    214     fWidth  = size.fWidth;
    215     fHeight = size.fHeight;
    216 }
    217 
    218 template<typename T>
    219 void Size<T>::growBy(double multiplier) noexcept
    220 {
    221     fWidth  = static_cast<T>(static_cast<double>(fWidth)*multiplier);
    222     fHeight = static_cast<T>(static_cast<double>(fHeight)*multiplier);
    223 }
    224 
    225 template<typename T>
    226 void Size<T>::shrinkBy(double divider) noexcept
    227 {
    228     fWidth  = static_cast<T>(static_cast<double>(fWidth)/divider);
    229     fHeight = static_cast<T>(static_cast<double>(fHeight)/divider);
    230 }
    231 
    232 template<typename T>
    233 bool Size<T>::isNull() const noexcept
    234 {
    235     return fWidth == 0 && fHeight == 0;
    236 }
    237 
    238 template<typename T>
    239 bool Size<T>::isNotNull() const noexcept
    240 {
    241     return fWidth != 0 || fHeight != 0;
    242 }
    243 
    244 template<typename T>
    245 bool Size<T>::isValid() const noexcept
    246 {
    247     return fWidth > 0 && fHeight > 0;
    248 }
    249 
    250 template<typename T>
    251 bool Size<T>::isInvalid() const noexcept
    252 {
    253     return fWidth <= 0 || fHeight <= 0;
    254 }
    255 
    256 template<typename T>
    257 Size<int> Size<T>::toInt() const noexcept
    258 {
    259     return Size<int>(static_cast<int>(fWidth),
    260                      static_cast<int>(fHeight));
    261 }
    262 
    263 template<>
    264 Size<int> Size<double>::toInt() const noexcept
    265 {
    266     return Size<int>(static_cast<int>(fWidth + 0.5),
    267                      static_cast<int>(fHeight + 0.5));
    268 }
    269 
    270 template<>
    271 Size<int> Size<float>::toInt() const noexcept
    272 {
    273     return Size<int>(static_cast<int>(fWidth + 0.5f),
    274                      static_cast<int>(fHeight + 0.5f));
    275 }
    276 
    277 template<typename T>
    278 Size<T> Size<T>::operator+(const Size<T>& size) noexcept
    279 {
    280     return Size<T>(fWidth+size.fWidth, fHeight+size.fHeight);
    281 }
    282 
    283 template<typename T>
    284 Size<T> Size<T>::operator-(const Size<T>& size) noexcept
    285 {
    286     return Size<T>(fWidth-size.fWidth, fHeight-size.fHeight);
    287 }
    288 
    289 template<typename T>
    290 Size<T>& Size<T>::operator=(const Size<T>& size) noexcept
    291 {
    292     fWidth  = size.fWidth;
    293     fHeight = size.fHeight;
    294     return *this;
    295 }
    296 
    297 template<typename T>
    298 Size<T>& Size<T>::operator+=(const Size<T>& size) noexcept
    299 {
    300     fWidth  = static_cast<T>(fWidth+size.fWidth);
    301     fHeight = static_cast<T>(fHeight+size.fHeight);
    302     return *this;
    303 }
    304 
    305 template<typename T>
    306 Size<T>& Size<T>::operator-=(const Size<T>& size) noexcept
    307 {
    308     fWidth  = static_cast<T>(fWidth-size.fWidth);
    309     fHeight = static_cast<T>(fHeight-size.fHeight);
    310     return *this;
    311 }
    312 
    313 template<typename T>
    314 Size<T>& Size<T>::operator*=(double m) noexcept
    315 {
    316     fWidth  = static_cast<T>(static_cast<double>(fWidth)*m);
    317     fHeight = static_cast<T>(static_cast<double>(fHeight)*m);
    318     return *this;
    319 }
    320 
    321 template<typename T>
    322 Size<T>& Size<T>::operator/=(double d) noexcept
    323 {
    324     fWidth  = static_cast<T>(static_cast<double>(fWidth)/d);
    325     fHeight = static_cast<T>(static_cast<double>(fHeight)/d);
    326     return *this;
    327 }
    328 
    329 template<typename T>
    330 Size<T> Size<T>::operator*(const double m) const noexcept
    331 {
    332     Size<T> size(fWidth, fHeight);
    333     size *= m;
    334     return size;
    335 }
    336 
    337 template<typename T>
    338 Size<T> Size<T>::operator/(const double m) const noexcept
    339 {
    340     Size<T> size(fWidth, fHeight);
    341     size /= m;
    342     return size;
    343 }
    344 
    345 template<typename T>
    346 bool Size<T>::operator==(const Size<T>& size) const noexcept
    347 {
    348     return (fWidth == size.fWidth && fHeight == size.fHeight);
    349 }
    350 
    351 template<typename T>
    352 bool Size<T>::operator!=(const Size<T>& size) const noexcept
    353 {
    354     return (fWidth != size.fWidth || fHeight != size.fHeight);
    355 }
    356 
    357 // -----------------------------------------------------------------------
    358 // Line
    359 
    360 template<typename T>
    361 Line<T>::Line() noexcept
    362     : posStart(0, 0),
    363       posEnd(0, 0) {}
    364 
    365 template<typename T>
    366 Line<T>::Line(const T& startX, const T& startY, const T& endX, const T& endY) noexcept
    367     : posStart(startX, startY),
    368       posEnd(endX, endY) {}
    369 
    370 template<typename T>
    371 Line<T>::Line(const T& startX, const T& startY, const Point<T>& endPos) noexcept
    372     : posStart(startX, startY),
    373       posEnd(endPos) {}
    374 
    375 template<typename T>
    376 Line<T>::Line(const Point<T>& startPos, const T& endX, const T& endY) noexcept
    377     : posStart(startPos),
    378       posEnd(endX, endY) {}
    379 
    380 template<typename T>
    381 Line<T>::Line(const Point<T>& startPos, const Point<T>& endPos) noexcept
    382     : posStart(startPos),
    383       posEnd(endPos) {}
    384 
    385 template<typename T>
    386 Line<T>::Line(const Line<T>& line) noexcept
    387     : posStart(line.posStart),
    388       posEnd(line.posEnd) {}
    389 
    390 template<typename T>
    391 const T& Line<T>::getStartX() const noexcept
    392 {
    393     return posStart.x;
    394 }
    395 
    396 template<typename T>
    397 const T& Line<T>::getStartY() const noexcept
    398 {
    399     return posStart.y;
    400 }
    401 
    402 template<typename T>
    403 const T& Line<T>::getEndX() const noexcept
    404 {
    405     return posEnd.x;
    406 }
    407 
    408 template<typename T>
    409 const T& Line<T>::getEndY() const noexcept
    410 {
    411     return posEnd.y;
    412 }
    413 
    414 template<typename T>
    415 const Point<T>& Line<T>::getStartPos() const noexcept
    416 {
    417     return posStart;
    418 }
    419 
    420 template<typename T>
    421 const Point<T>& Line<T>::getEndPos() const noexcept
    422 {
    423     return posEnd;
    424 }
    425 
    426 template<typename T>
    427 void Line<T>::setStartX(const T& x) noexcept
    428 {
    429     posStart.x = x;
    430 }
    431 
    432 template<typename T>
    433 void Line<T>::setStartY(const T& y) noexcept
    434 {
    435     posStart.y = y;
    436 }
    437 
    438 template<typename T>
    439 void Line<T>::setStartPos(const T& x, const T& y) noexcept
    440 {
    441     posStart = Point<T>(x, y);
    442 }
    443 
    444 template<typename T>
    445 void Line<T>::setStartPos(const Point<T>& pos) noexcept
    446 {
    447     posStart = pos;
    448 }
    449 
    450 template<typename T>
    451 void Line<T>::setEndX(const T& x) noexcept
    452 {
    453     posEnd.x = x;
    454 }
    455 
    456 template<typename T>
    457 void Line<T>::setEndY(const T& y) noexcept
    458 {
    459     posEnd.y = y;
    460 }
    461 
    462 template<typename T>
    463 void Line<T>::setEndPos(const T& x, const T& y) noexcept
    464 {
    465     posEnd = Point<T>(x, y);
    466 }
    467 
    468 template<typename T>
    469 void Line<T>::setEndPos(const Point<T>& pos) noexcept
    470 {
    471     posEnd = pos;
    472 }
    473 
    474 template<typename T>
    475 void Line<T>::moveBy(const T& x, const T& y) noexcept
    476 {
    477     posStart.moveBy(x, y);
    478     posEnd.moveBy(x, y);
    479 }
    480 
    481 template<typename T>
    482 void Line<T>::moveBy(const Point<T>& pos) noexcept
    483 {
    484     posStart.moveBy(pos);
    485     posEnd.moveBy(pos);
    486 }
    487 
    488 template<typename T>
    489 bool Line<T>::isNull() const noexcept
    490 {
    491     return posStart == posEnd;
    492 }
    493 
    494 template<typename T>
    495 bool Line<T>::isNotNull() const noexcept
    496 {
    497     return posStart != posEnd;
    498 }
    499 
    500 template<typename T>
    501 Line<T>& Line<T>::operator=(const Line<T>& line) noexcept
    502 {
    503     posStart = line.posStart;
    504     posEnd   = line.posEnd;
    505     return *this;
    506 }
    507 
    508 template<typename T>
    509 bool Line<T>::operator==(const Line<T>& line) const noexcept
    510 {
    511     return (posStart == line.posStart && posEnd == line.posEnd);
    512 }
    513 
    514 template<typename T>
    515 bool Line<T>::operator!=(const Line<T>& line) const noexcept
    516 {
    517     return (posStart != line.posStart || posEnd != line.posEnd);
    518 }
    519 
    520 // -----------------------------------------------------------------------
    521 // Circle
    522 
    523 template<typename T>
    524 Circle<T>::Circle() noexcept
    525     : fPos(0, 0),
    526       fSize(0.0f),
    527       fNumSegments(0),
    528       fTheta(0.0f),
    529       fCos(0.0f),
    530       fSin(0.0f) {}
    531 
    532 template<typename T>
    533 Circle<T>::Circle(const T& x, const T& y, const float size, const uint numSegments)
    534     : fPos(x, y),
    535       fSize(size),
    536       fNumSegments(numSegments >= 3 ? numSegments : 3),
    537       fTheta(M_2PIf / static_cast<float>(fNumSegments)),
    538       fCos(std::cos(fTheta)),
    539       fSin(std::sin(fTheta))
    540 {
    541     DISTRHO_SAFE_ASSERT(fSize > 0.0f);
    542 }
    543 
    544 template<typename T>
    545 Circle<T>::Circle(const Point<T>& pos, const float size, const uint numSegments)
    546     : fPos(pos),
    547       fSize(size),
    548       fNumSegments(numSegments >= 3 ? numSegments : 3),
    549       fTheta(M_2PIf / static_cast<float>(fNumSegments)),
    550       fCos(std::cos(fTheta)),
    551       fSin(std::sin(fTheta))
    552 {
    553     DISTRHO_SAFE_ASSERT(fSize > 0.0f);
    554 }
    555 
    556 template<typename T>
    557 Circle<T>::Circle(const Circle<T>& cir) noexcept
    558     : fPos(cir.fPos),
    559       fSize(cir.fSize),
    560       fNumSegments(cir.fNumSegments),
    561       fTheta(cir.fTheta),
    562       fCos(cir.fCos),
    563       fSin(cir.fSin)
    564 {
    565     DISTRHO_SAFE_ASSERT(fSize > 0.0f);
    566 }
    567 
    568 template<typename T>
    569 const T& Circle<T>::getX() const noexcept
    570 {
    571     return fPos.x;
    572 }
    573 
    574 template<typename T>
    575 const T& Circle<T>::getY() const noexcept
    576 {
    577     return fPos.y;
    578 }
    579 
    580 template<typename T>
    581 const Point<T>& Circle<T>::getPos() const noexcept
    582 {
    583     return fPos;
    584 }
    585 
    586 template<typename T>
    587 void Circle<T>::setX(const T& x) noexcept
    588 {
    589     fPos.x = x;
    590 }
    591 
    592 template<typename T>
    593 void Circle<T>::setY(const T& y) noexcept
    594 {
    595     fPos.y = y;
    596 }
    597 
    598 template<typename T>
    599 void Circle<T>::setPos(const T& x, const T& y) noexcept
    600 {
    601     fPos.x = x;
    602     fPos.y = y;
    603 }
    604 
    605 template<typename T>
    606 void Circle<T>::setPos(const Point<T>& pos) noexcept
    607 {
    608     fPos = pos;
    609 }
    610 
    611 template<typename T>
    612 float Circle<T>::getSize() const noexcept
    613 {
    614     return fSize;
    615 }
    616 
    617 template<typename T>
    618 void Circle<T>::setSize(const float size) noexcept
    619 {
    620     DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,);
    621 
    622     fSize = size;
    623 }
    624 
    625 template<typename T>
    626 uint Circle<T>::getNumSegments() const noexcept
    627 {
    628     return fNumSegments;
    629 }
    630 
    631 template<typename T>
    632 void Circle<T>::setNumSegments(const uint num)
    633 {
    634     DISTRHO_SAFE_ASSERT_RETURN(num >= 3,);
    635 
    636     if (fNumSegments == num)
    637         return;
    638 
    639     fNumSegments = num;
    640 
    641     fTheta = M_2PIf / static_cast<float>(fNumSegments);
    642     fCos = std::cos(fTheta);
    643     fSin = std::sin(fTheta);
    644 }
    645 
    646 template<typename T>
    647 Circle<T>& Circle<T>::operator=(const Circle<T>& cir) noexcept
    648 {
    649     fPos   = cir.fPos;
    650     fSize  = cir.fSize;
    651     fTheta = cir.fTheta;
    652     fCos   = cir.fCos;
    653     fSin   = cir.fSin;
    654     fNumSegments = cir.fNumSegments;
    655     return *this;
    656 }
    657 
    658 template<typename T>
    659 bool Circle<T>::operator==(const Circle<T>& cir) const noexcept
    660 {
    661     return (fPos == cir.fPos && d_isEqual(fSize, cir.fSize) && fNumSegments == cir.fNumSegments);
    662 }
    663 
    664 template<typename T>
    665 bool Circle<T>::operator!=(const Circle<T>& cir) const noexcept
    666 {
    667     return (fPos != cir.fPos || d_isNotEqual(fSize, cir.fSize) || fNumSegments != cir.fNumSegments);
    668 }
    669 
    670 // -----------------------------------------------------------------------
    671 // Triangle
    672 
    673 template<typename T>
    674 Triangle<T>::Triangle() noexcept
    675     : pos1(0, 0),
    676       pos2(0, 0),
    677       pos3(0, 0) {}
    678 
    679 template<typename T>
    680 Triangle<T>::Triangle(const T& x1, const T& y1, const T& x2, const T& y2, const T& x3, const T& y3) noexcept
    681     : pos1(x1, y1),
    682       pos2(x2, y2),
    683       pos3(x3, y3) {}
    684 
    685 template<typename T>
    686 Triangle<T>::Triangle(const Point<T>& p1, const Point<T>& p2, const Point<T>& p3) noexcept
    687     : pos1(p1),
    688       pos2(p2),
    689       pos3(p3) {}
    690 
    691 template<typename T>
    692 Triangle<T>::Triangle(const Triangle<T>& tri) noexcept
    693     : pos1(tri.pos1),
    694       pos2(tri.pos2),
    695       pos3(tri.pos3) {}
    696 
    697 template<typename T>
    698 bool Triangle<T>::isNull() const noexcept
    699 {
    700     return pos1 == pos2 && pos1 == pos3;
    701 }
    702 
    703 template<typename T>
    704 bool Triangle<T>::isNotNull() const noexcept
    705 {
    706     return pos1 != pos2 || pos1 != pos3;
    707 }
    708 
    709 template<typename T>
    710 bool Triangle<T>::isValid() const noexcept
    711 {
    712     return pos1 != pos2 && pos1 != pos3;
    713 }
    714 
    715 template<typename T>
    716 bool Triangle<T>::isInvalid() const noexcept
    717 {
    718     return pos1 == pos2 || pos1 == pos3;
    719 }
    720 
    721 template<typename T>
    722 Triangle<T>& Triangle<T>::operator=(const Triangle<T>& tri) noexcept
    723 {
    724     pos1 = tri.pos1;
    725     pos2 = tri.pos2;
    726     pos3 = tri.pos3;
    727     return *this;
    728 }
    729 
    730 template<typename T>
    731 bool Triangle<T>::operator==(const Triangle<T>& tri) const noexcept
    732 {
    733     return (pos1 == tri.pos1 && pos2 == tri.pos2 && pos3 == tri.pos3);
    734 }
    735 
    736 template<typename T>
    737 bool Triangle<T>::operator!=(const Triangle<T>& tri) const noexcept
    738 {
    739     return (pos1 != tri.pos1 || pos2 != tri.pos2 || pos3 != tri.pos3);
    740 }
    741 
    742 // -----------------------------------------------------------------------
    743 // Rectangle
    744 
    745 template<typename T>
    746 Rectangle<T>::Rectangle() noexcept
    747     : pos(0, 0),
    748       size(0, 0) {}
    749 
    750 template<typename T>
    751 Rectangle<T>::Rectangle(const T& x, const T& y, const T& w, const T& h) noexcept
    752     : pos(x, y),
    753       size(w, h) {}
    754 
    755 template<typename T>
    756 Rectangle<T>::Rectangle(const T& x, const T& y, const Size<T>& s) noexcept
    757     : pos(x, y),
    758       size(s) {}
    759 
    760 template<typename T>
    761 Rectangle<T>::Rectangle(const Point<T>& p, const T& w, const T& h) noexcept
    762     : pos(p),
    763       size(w, h) {}
    764 
    765 template<typename T>
    766 Rectangle<T>::Rectangle(const Point<T>& p, const Size<T>& s) noexcept
    767     : pos(p),
    768       size(s) {}
    769 
    770 template<typename T>
    771 Rectangle<T>::Rectangle(const Rectangle<T>& rect) noexcept
    772     : pos(rect.pos),
    773       size(rect.size) {}
    774 
    775 template<typename T>
    776 const T& Rectangle<T>::getX() const noexcept
    777 {
    778     return pos.x;
    779 }
    780 
    781 template<typename T>
    782 const T& Rectangle<T>::getY() const noexcept
    783 {
    784     return pos.y;
    785 }
    786 
    787 template<typename T>
    788 const T& Rectangle<T>::getWidth() const noexcept
    789 {
    790     return size.fWidth;
    791 }
    792 
    793 template<typename T>
    794 const T& Rectangle<T>::getHeight() const noexcept
    795 {
    796     return size.fHeight;
    797 }
    798 
    799 template<typename T>
    800 const Point<T>& Rectangle<T>::getPos() const noexcept
    801 {
    802     return pos;
    803 }
    804 
    805 template<typename T>
    806 const Size<T>& Rectangle<T>::getSize() const noexcept
    807 {
    808     return size;
    809 }
    810 
    811 template<typename T>
    812 void Rectangle<T>::setX(const T& x) noexcept
    813 {
    814     pos.x = x;
    815 }
    816 
    817 template<typename T>
    818 void Rectangle<T>::setY(const T& y) noexcept
    819 {
    820     pos.y = y;
    821 }
    822 
    823 template<typename T>
    824 void Rectangle<T>::setPos(const T& x, const T& y) noexcept
    825 {
    826     pos.x = x;
    827     pos.y = y;
    828 }
    829 
    830 template<typename T>
    831 void Rectangle<T>::setPos(const Point<T>& pos2) noexcept
    832 {
    833     pos = pos2;
    834 }
    835 
    836 template<typename T>
    837 void Rectangle<T>::moveBy(const T& x, const T& y) noexcept
    838 {
    839     pos.moveBy(x, y);
    840 }
    841 
    842 template<typename T>
    843 void Rectangle<T>::moveBy(const Point<T>& pos2) noexcept
    844 {
    845     pos.moveBy(pos2);
    846 }
    847 
    848 template<typename T>
    849 void Rectangle<T>::setWidth(const T& width) noexcept
    850 {
    851     size.fWidth = width;
    852 }
    853 
    854 template<typename T>
    855 void Rectangle<T>::setHeight(const T& height) noexcept
    856 {
    857     size.fHeight = height;
    858 }
    859 
    860 template<typename T>
    861 void Rectangle<T>::setSize(const T& width, const T& height) noexcept
    862 {
    863     size.fWidth  = width;
    864     size.fHeight = height;
    865 }
    866 
    867 template<typename T>
    868 void Rectangle<T>::setSize(const Size<T>& size2) noexcept
    869 {
    870     size = size2;
    871 }
    872 
    873 template<typename T>
    874 void Rectangle<T>::growBy(double multiplier) noexcept
    875 {
    876     size.growBy(multiplier);
    877 }
    878 
    879 template<typename T>
    880 void Rectangle<T>::shrinkBy(double divider) noexcept
    881 {
    882     size.shrinkBy(divider);
    883 }
    884 
    885 template<typename T>
    886 void Rectangle<T>::setRectangle(const Point<T>& pos2, const Size<T>& size2) noexcept
    887 {
    888     pos  = pos2;
    889     size = size2;
    890 }
    891 
    892 template<typename T>
    893 void Rectangle<T>::setRectangle(const Rectangle<T>& rect) noexcept
    894 {
    895     pos  = rect.pos;
    896     size = rect.size;
    897 }
    898 
    899 template<typename T>
    900 bool Rectangle<T>::contains(const T& x, const T& y) const noexcept
    901 {
    902     return (x >= pos.x && y >= pos.y && x <= pos.x+size.fWidth && y <= pos.y+size.fHeight);
    903 }
    904 
    905 template<typename T>
    906 bool Rectangle<T>::contains(const Point<T>& p) const noexcept
    907 {
    908     return contains(p.x, p.y);
    909 }
    910 
    911 template<typename T>
    912 template<typename T2>
    913 bool Rectangle<T>::contains(const Point<T2>& p) const noexcept
    914 {
    915     return (p.x >= pos.x && p.y >= pos.y && p.x <= pos.x+size.fWidth && p.y <= pos.y+size.fHeight);
    916 }
    917 
    918 template<> template<>
    919 bool Rectangle<int>::contains(const Point<double>& p) const noexcept
    920 {
    921     return (p.x >= pos.x && p.y >= pos.y && p.x <= pos.x+size.fWidth && p.y <= pos.y+size.fHeight);
    922 }
    923 
    924 template<> template<>
    925 bool Rectangle<uint>::contains(const Point<double>& p) const noexcept
    926 {
    927     return (p.x >= pos.x && p.y >= pos.y && p.x <= pos.x+size.fWidth && p.y <= pos.y+size.fHeight);
    928 }
    929 
    930 template<typename T>
    931 bool Rectangle<T>::containsAfterScaling(const Point<T>& p, const double scaling) const noexcept
    932 {
    933     return (p.x >= pos.x && p.y >= pos.y && p.x/scaling <= pos.x+size.fWidth && p.y/scaling <= pos.y+size.fHeight);
    934 }
    935 
    936 template<typename T>
    937 bool Rectangle<T>::containsX(const T& x) const noexcept
    938 {
    939     return (x >= pos.x && x <= pos.x + size.fWidth);
    940 }
    941 
    942 template<typename T>
    943 bool Rectangle<T>::containsY(const T& y) const noexcept
    944 {
    945     return (y >= pos.y && y <= pos.y + size.fHeight);
    946 }
    947 
    948 template<typename T>
    949 bool Rectangle<T>::isNull() const noexcept
    950 {
    951     return size.isNull();
    952 }
    953 
    954 template<typename T>
    955 bool Rectangle<T>::isNotNull() const noexcept
    956 {
    957     return size.isNotNull();
    958 }
    959 
    960 template<typename T>
    961 bool Rectangle<T>::isValid() const noexcept
    962 {
    963     return size.isValid();
    964 }
    965 
    966 template<typename T>
    967 bool Rectangle<T>::isInvalid() const noexcept
    968 {
    969     return size.isInvalid();
    970 }
    971 
    972 template<typename T>
    973 Rectangle<T>& Rectangle<T>::operator=(const Rectangle<T>& rect) noexcept
    974 {
    975     pos  = rect.pos;
    976     size = rect.size;
    977     return *this;
    978 }
    979 
    980 template<typename T>
    981 Rectangle<T>& Rectangle<T>::operator*=(double m) noexcept
    982 {
    983     size *= m;
    984     return *this;
    985 }
    986 
    987 template<typename T>
    988 Rectangle<T>& Rectangle<T>::operator/=(double d) noexcept
    989 {
    990     size /= d;
    991     return *this;
    992 }
    993 
    994 template<typename T>
    995 bool Rectangle<T>::operator==(const Rectangle<T>& rect) const noexcept
    996 {
    997     return (pos == rect.pos && size == rect.size);
    998 }
    999 
   1000 template<typename T>
   1001 bool Rectangle<T>::operator!=(const Rectangle<T>& rect) const noexcept
   1002 {
   1003     return (pos != rect.pos || size != rect.size);
   1004 }
   1005 
   1006 // -----------------------------------------------------------------------
   1007 // Possible template data types
   1008 
   1009 template class Point<double>;
   1010 template class Point<float>;
   1011 template class Point<int>;
   1012 template class Point<uint>;
   1013 template class Point<short>;
   1014 template class Point<ushort>;
   1015 
   1016 template class Size<double>;
   1017 template class Size<float>;
   1018 template class Size<int>;
   1019 template class Size<uint>;
   1020 template class Size<short>;
   1021 template class Size<ushort>;
   1022 
   1023 template class Line<double>;
   1024 template class Line<float>;
   1025 template class Line<int>;
   1026 template class Line<uint>;
   1027 template class Line<short>;
   1028 template class Line<ushort>;
   1029 
   1030 template class Circle<double>;
   1031 template class Circle<float>;
   1032 template class Circle<int>;
   1033 template class Circle<uint>;
   1034 template class Circle<short>;
   1035 template class Circle<ushort>;
   1036 
   1037 template class Triangle<double>;
   1038 template class Triangle<float>;
   1039 template class Triangle<int>;
   1040 template class Triangle<uint>;
   1041 template class Triangle<short>;
   1042 template class Triangle<ushort>;
   1043 
   1044 template class Rectangle<double>;
   1045 template class Rectangle<float>;
   1046 template class Rectangle<int>;
   1047 template class Rectangle<uint>;
   1048 template class Rectangle<short>;
   1049 template class Rectangle<ushort>;
   1050 
   1051 // -----------------------------------------------------------------------
   1052 
   1053 END_NAMESPACE_DGL