1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2019 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 #include "../Geometry.hpp"
18 
19 #include <cmath>
20 
21 START_NAMESPACE_DGL
22 
23 static const float M_2PIf = 3.14159265358979323846f*2.0f;
24 
25 // -----------------------------------------------------------------------
26 // Point
27 
28 template<typename T>
Point()29 Point<T>::Point() noexcept
30     : fX(0),
31       fY(0) {}
32 
33 template<typename T>
Point(const T & x,const T & y)34 Point<T>::Point(const T& x, const T& y) noexcept
35     : fX(x),
36       fY(y) {}
37 
38 template<typename T>
Point(const Point<T> & pos)39 Point<T>::Point(const Point<T>& pos) noexcept
40     : fX(pos.fX),
41       fY(pos.fY) {}
42 
43 template<typename T>
getX() const44 const T& Point<T>::getX() const noexcept
45 {
46     return fX;
47 }
48 
49 template<typename T>
getY() const50 const T& Point<T>::getY() const noexcept
51 {
52     return fY;
53 }
54 
55 template<typename T>
setX(const T & x)56 void Point<T>::setX(const T& x) noexcept
57 {
58     fX = x;
59 }
60 
61 template<typename T>
setY(const T & y)62 void Point<T>::setY(const T& y) noexcept
63 {
64     fY = y;
65 }
66 
67 template<typename T>
setPos(const T & x,const T & y)68 void Point<T>::setPos(const T& x, const T& y) noexcept
69 {
70     fX = x;
71     fY = y;
72 }
73 
74 template<typename T>
setPos(const Point<T> & pos)75 void Point<T>::setPos(const Point<T>& pos) noexcept
76 {
77     fX = pos.fX;
78     fY = pos.fY;
79 }
80 
81 template<typename T>
moveBy(const T & x,const T & y)82 void Point<T>::moveBy(const T& x, const T& y) noexcept
83 {
84     fX = static_cast<T>(fX+x);
85     fY = static_cast<T>(fY+y);
86 }
87 
88 template<typename T>
moveBy(const Point<T> & pos)89 void Point<T>::moveBy(const Point<T>& pos) noexcept
90 {
91     fX = static_cast<T>(fX+pos.fX);
92     fY = static_cast<T>(fY+pos.fY);
93 }
94 
95 template<typename T>
isZero() const96 bool Point<T>::isZero() const noexcept
97 {
98     return fX == 0 && fY == 0;
99 }
100 
101 template<typename T>
isNotZero() const102 bool Point<T>::isNotZero() const noexcept
103 {
104     return fX != 0 || fY != 0;
105 }
106 
107 template<typename T>
operator +(const Point<T> & pos)108 Point<T> Point<T>::operator+(const Point<T>& pos) noexcept
109 {
110     return Point<T>(fX+pos.fX, fY+pos.fY);
111 }
112 
113 template<typename T>
operator -(const Point<T> & pos)114 Point<T> Point<T>::operator-(const Point<T>& pos) noexcept
115 {
116     return Point<T>(fX-pos.fX, fY-pos.fY);
117 }
118 
119 template<typename T>
operator =(const Point<T> & pos)120 Point<T>& Point<T>::operator=(const Point<T>& pos) noexcept
121 {
122     fX = pos.fX;
123     fY = pos.fY;
124     return *this;
125 }
126 
127 template<typename T>
operator +=(const Point<T> & pos)128 Point<T>& Point<T>::operator+=(const Point<T>& pos) noexcept
129 {
130     fX = static_cast<T>(fX+pos.fX);
131     fY = static_cast<T>(fY+pos.fY);
132     return *this;
133 }
134 
135 template<typename T>
operator -=(const Point<T> & pos)136 Point<T>& Point<T>::operator-=(const Point<T>& pos) noexcept
137 {
138     fX = static_cast<T>(fX-pos.fX);
139     fY = static_cast<T>(fY-pos.fY);
140     return *this;
141 }
142 
143 template<typename T>
operator ==(const Point<T> & pos) const144 bool Point<T>::operator==(const Point<T>& pos) const noexcept
145 {
146     return (fX == pos.fX && fY == pos.fY);
147 }
148 
149 template<typename T>
operator !=(const Point<T> & pos) const150 bool Point<T>::operator!=(const Point<T>& pos) const noexcept
151 {
152     return (fX != pos.fX || fY != pos.fY);
153 }
154 
155 // -----------------------------------------------------------------------
156 // Size
157 
158 template<typename T>
Size()159 Size<T>::Size() noexcept
160     : fWidth(0),
161       fHeight(0) {}
162 
163 template<typename T>
Size(const T & width,const T & height)164 Size<T>::Size(const T& width, const T& height) noexcept
165     : fWidth(width),
166       fHeight(height) {}
167 
168 template<typename T>
Size(const Size<T> & size)169 Size<T>::Size(const Size<T>& size) noexcept
170     : fWidth(size.fWidth),
171       fHeight(size.fHeight) {}
172 
173 template<typename T>
getWidth() const174 const T& Size<T>::getWidth() const noexcept
175 {
176     return fWidth;
177 }
178 
179 template<typename T>
getHeight() const180 const T& Size<T>::getHeight() const noexcept
181 {
182     return fHeight;
183 }
184 
185 template<typename T>
setWidth(const T & width)186 void Size<T>::setWidth(const T& width) noexcept
187 {
188     fWidth = width;
189 }
190 
191 template<typename T>
setHeight(const T & height)192 void Size<T>::setHeight(const T& height) noexcept
193 {
194     fHeight = height;
195 }
196 
197 template<typename T>
setSize(const T & width,const T & height)198 void Size<T>::setSize(const T& width, const T& height) noexcept
199 {
200     fWidth  = width;
201     fHeight = height;
202 }
203 
204 template<typename T>
setSize(const Size<T> & size)205 void Size<T>::setSize(const Size<T>& size) noexcept
206 {
207     fWidth  = size.fWidth;
208     fHeight = size.fHeight;
209 }
210 
211 template<typename T>
growBy(double multiplier)212 void Size<T>::growBy(double multiplier) noexcept
213 {
214     fWidth  = static_cast<T>(static_cast<double>(fWidth)*multiplier);
215     fHeight = static_cast<T>(static_cast<double>(fHeight)*multiplier);
216 }
217 
218 template<typename T>
shrinkBy(double divider)219 void Size<T>::shrinkBy(double divider) noexcept
220 {
221     fWidth  = static_cast<T>(static_cast<double>(fWidth)/divider);
222     fHeight = static_cast<T>(static_cast<double>(fHeight)/divider);
223 }
224 
225 template<typename T>
isNull() const226 bool Size<T>::isNull() const noexcept
227 {
228     return fWidth == 0 && fHeight == 0;
229 }
230 
231 template<typename T>
isNotNull() const232 bool Size<T>::isNotNull() const noexcept
233 {
234     return fWidth != 0 || fHeight != 0;
235 }
236 
237 template<typename T>
isValid() const238 bool Size<T>::isValid() const noexcept
239 {
240     return fWidth > 0 && fHeight > 0;
241 }
242 
243 template<typename T>
isInvalid() const244 bool Size<T>::isInvalid() const noexcept
245 {
246     return fWidth <= 0 || fHeight <= 0;
247 }
248 
249 template<typename T>
operator +(const Size<T> & size)250 Size<T> Size<T>::operator+(const Size<T>& size) noexcept
251 {
252     return Size<T>(fWidth+size.fWidth, fHeight+size.fHeight);
253 }
254 
255 template<typename T>
operator -(const Size<T> & size)256 Size<T> Size<T>::operator-(const Size<T>& size) noexcept
257 {
258     return Size<T>(fWidth-size.fWidth, fHeight-size.fHeight);
259 }
260 
261 template<typename T>
operator =(const Size<T> & size)262 Size<T>& Size<T>::operator=(const Size<T>& size) noexcept
263 {
264     fWidth  = size.fWidth;
265     fHeight = size.fHeight;
266     return *this;
267 }
268 
269 template<typename T>
operator +=(const Size<T> & size)270 Size<T>& Size<T>::operator+=(const Size<T>& size) noexcept
271 {
272     fWidth  = static_cast<T>(fWidth+size.fWidth);
273     fHeight = static_cast<T>(fHeight+size.fHeight);
274     return *this;
275 }
276 
277 template<typename T>
operator -=(const Size<T> & size)278 Size<T>& Size<T>::operator-=(const Size<T>& size) noexcept
279 {
280     fWidth  = static_cast<T>(fWidth-size.fWidth);
281     fHeight = static_cast<T>(fHeight-size.fHeight);
282     return *this;
283 }
284 
285 template<typename T>
operator *=(double m)286 Size<T>& Size<T>::operator*=(double m) noexcept
287 {
288     fWidth  = static_cast<T>(static_cast<double>(fWidth)*m);
289     fHeight = static_cast<T>(static_cast<double>(fHeight)*m);
290     return *this;
291 }
292 
293 template<typename T>
operator /=(double d)294 Size<T>& Size<T>::operator/=(double d) noexcept
295 {
296     fWidth  = static_cast<T>(static_cast<double>(fWidth)/d);
297     fHeight = static_cast<T>(static_cast<double>(fHeight)/d);
298     return *this;
299 }
300 
301 template<typename T>
operator ==(const Size<T> & size) const302 bool Size<T>::operator==(const Size<T>& size) const noexcept
303 {
304     return (fWidth == size.fWidth && fHeight == size.fHeight);
305 }
306 
307 template<typename T>
operator !=(const Size<T> & size) const308 bool Size<T>::operator!=(const Size<T>& size) const noexcept
309 {
310     return (fWidth != size.fWidth || fHeight != size.fHeight);
311 }
312 
313 // -----------------------------------------------------------------------
314 // Line
315 
316 template<typename T>
Line()317 Line<T>::Line() noexcept
318     : fPosStart(0, 0),
319       fPosEnd(0, 0) {}
320 
321 template<typename T>
Line(const T & startX,const T & startY,const T & endX,const T & endY)322 Line<T>::Line(const T& startX, const T& startY, const T& endX, const T& endY) noexcept
323     : fPosStart(startX, startY),
324       fPosEnd(endX, endY) {}
325 
326 template<typename T>
Line(const T & startX,const T & startY,const Point<T> & endPos)327 Line<T>::Line(const T& startX, const T& startY, const Point<T>& endPos) noexcept
328     : fPosStart(startX, startY),
329       fPosEnd(endPos) {}
330 
331 template<typename T>
Line(const Point<T> & startPos,const T & endX,const T & endY)332 Line<T>::Line(const Point<T>& startPos, const T& endX, const T& endY) noexcept
333     : fPosStart(startPos),
334       fPosEnd(endX, endY) {}
335 
336 template<typename T>
Line(const Point<T> & startPos,const Point<T> & endPos)337 Line<T>::Line(const Point<T>& startPos, const Point<T>& endPos) noexcept
338     : fPosStart(startPos),
339       fPosEnd(endPos) {}
340 
341 template<typename T>
Line(const Line<T> & line)342 Line<T>::Line(const Line<T>& line) noexcept
343     : fPosStart(line.fPosStart),
344       fPosEnd(line.fPosEnd) {}
345 
346 template<typename T>
getStartX() const347 const T& Line<T>::getStartX() const noexcept
348 {
349     return fPosStart.fX;
350 }
351 
352 template<typename T>
getStartY() const353 const T& Line<T>::getStartY() const noexcept
354 {
355     return fPosStart.fY;
356 }
357 
358 template<typename T>
getEndX() const359 const T& Line<T>::getEndX() const noexcept
360 {
361     return fPosEnd.fX;
362 }
363 
364 template<typename T>
getEndY() const365 const T& Line<T>::getEndY() const noexcept
366 {
367     return fPosEnd.fY;
368 }
369 
370 template<typename T>
getStartPos() const371 const Point<T>& Line<T>::getStartPos() const noexcept
372 {
373     return fPosStart;
374 }
375 
376 template<typename T>
getEndPos() const377 const Point<T>& Line<T>::getEndPos() const noexcept
378 {
379     return fPosEnd;
380 }
381 
382 template<typename T>
setStartX(const T & x)383 void Line<T>::setStartX(const T& x) noexcept
384 {
385     fPosStart.fX = x;
386 }
387 
388 template<typename T>
setStartY(const T & y)389 void Line<T>::setStartY(const T& y) noexcept
390 {
391     fPosStart.fY = y;
392 }
393 
394 template<typename T>
setStartPos(const T & x,const T & y)395 void Line<T>::setStartPos(const T& x, const T& y) noexcept
396 {
397     fPosStart = Point<T>(x, y);
398 }
399 
400 template<typename T>
setStartPos(const Point<T> & pos)401 void Line<T>::setStartPos(const Point<T>& pos) noexcept
402 {
403     fPosStart = pos;
404 }
405 
406 template<typename T>
setEndX(const T & x)407 void Line<T>::setEndX(const T& x) noexcept
408 {
409     fPosEnd.fX = x;
410 }
411 
412 template<typename T>
setEndY(const T & y)413 void Line<T>::setEndY(const T& y) noexcept
414 {
415     fPosEnd.fY = y;
416 }
417 
418 template<typename T>
setEndPos(const T & x,const T & y)419 void Line<T>::setEndPos(const T& x, const T& y) noexcept
420 {
421     fPosEnd = Point<T>(x, y);
422 }
423 
424 template<typename T>
setEndPos(const Point<T> & pos)425 void Line<T>::setEndPos(const Point<T>& pos) noexcept
426 {
427     fPosEnd = pos;
428 }
429 
430 template<typename T>
moveBy(const T & x,const T & y)431 void Line<T>::moveBy(const T& x, const T& y) noexcept
432 {
433     fPosStart.moveBy(x, y);
434     fPosEnd.moveBy(x, y);
435 }
436 
437 template<typename T>
moveBy(const Point<T> & pos)438 void Line<T>::moveBy(const Point<T>& pos) noexcept
439 {
440     fPosStart.moveBy(pos);
441     fPosEnd.moveBy(pos);
442 }
443 
444 template<typename T>
isNull() const445 bool Line<T>::isNull() const noexcept
446 {
447     return fPosStart == fPosEnd;
448 }
449 
450 template<typename T>
isNotNull() const451 bool Line<T>::isNotNull() const noexcept
452 {
453     return fPosStart != fPosEnd;
454 }
455 
456 template<typename T>
operator =(const Line<T> & line)457 Line<T>& Line<T>::operator=(const Line<T>& line) noexcept
458 {
459     fPosStart = line.fPosStart;
460     fPosEnd   = line.fPosEnd;
461     return *this;
462 }
463 
464 template<typename T>
operator ==(const Line<T> & line) const465 bool Line<T>::operator==(const Line<T>& line) const noexcept
466 {
467     return (fPosStart == line.fPosStart && fPosEnd == line.fPosEnd);
468 }
469 
470 template<typename T>
operator !=(const Line<T> & line) const471 bool Line<T>::operator!=(const Line<T>& line) const noexcept
472 {
473     return (fPosStart != line.fPosStart || fPosEnd != line.fPosEnd);
474 }
475 
476 // -----------------------------------------------------------------------
477 // Circle
478 
479 template<typename T>
Circle()480 Circle<T>::Circle() noexcept
481     : fPos(0, 0),
482       fSize(0.0f),
483       fNumSegments(0),
484       fTheta(0.0f),
485       fCos(0.0f),
486       fSin(0.0f) {}
487 
488 template<typename T>
Circle(const T & x,const T & y,const float size,const uint numSegments)489 Circle<T>::Circle(const T& x, const T& y, const float size, const uint numSegments)
490     : fPos(x, y),
491       fSize(size),
492       fNumSegments(numSegments >= 3 ? numSegments : 3),
493       fTheta(M_2PIf / static_cast<float>(fNumSegments)),
494       fCos(std::cos(fTheta)),
495       fSin(std::sin(fTheta))
496 {
497     DISTRHO_SAFE_ASSERT(fSize > 0.0f);
498 }
499 
500 template<typename T>
Circle(const Point<T> & pos,const float size,const uint numSegments)501 Circle<T>::Circle(const Point<T>& pos, const float size, const uint numSegments)
502     : fPos(pos),
503       fSize(size),
504       fNumSegments(numSegments >= 3 ? numSegments : 3),
505       fTheta(M_2PIf / static_cast<float>(fNumSegments)),
506       fCos(std::cos(fTheta)),
507       fSin(std::sin(fTheta))
508 {
509     DISTRHO_SAFE_ASSERT(fSize > 0.0f);
510 }
511 
512 template<typename T>
Circle(const Circle<T> & cir)513 Circle<T>::Circle(const Circle<T>& cir) noexcept
514     : fPos(cir.fPos),
515       fSize(cir.fSize),
516       fNumSegments(cir.fNumSegments),
517       fTheta(cir.fTheta),
518       fCos(cir.fCos),
519       fSin(cir.fSin)
520 {
521     DISTRHO_SAFE_ASSERT(fSize > 0.0f);
522 }
523 
524 template<typename T>
getX() const525 const T& Circle<T>::getX() const noexcept
526 {
527     return fPos.fX;
528 }
529 
530 template<typename T>
getY() const531 const T& Circle<T>::getY() const noexcept
532 {
533     return fPos.fY;
534 }
535 
536 template<typename T>
getPos() const537 const Point<T>& Circle<T>::getPos() const noexcept
538 {
539     return fPos;
540 }
541 
542 template<typename T>
setX(const T & x)543 void Circle<T>::setX(const T& x) noexcept
544 {
545     fPos.fX = x;
546 }
547 
548 template<typename T>
setY(const T & y)549 void Circle<T>::setY(const T& y) noexcept
550 {
551     fPos.fY = y;
552 }
553 
554 template<typename T>
setPos(const T & x,const T & y)555 void Circle<T>::setPos(const T& x, const T& y) noexcept
556 {
557     fPos.fX = x;
558     fPos.fY = y;
559 }
560 
561 template<typename T>
setPos(const Point<T> & pos)562 void Circle<T>::setPos(const Point<T>& pos) noexcept
563 {
564     fPos = pos;
565 }
566 
567 template<typename T>
getSize() const568 float Circle<T>::getSize() const noexcept
569 {
570     return fSize;
571 }
572 
573 template<typename T>
setSize(const float size)574 void Circle<T>::setSize(const float size) noexcept
575 {
576     DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,);
577 
578     fSize = size;
579 }
580 
581 template<typename T>
getNumSegments() const582 uint Circle<T>::getNumSegments() const noexcept
583 {
584     return fNumSegments;
585 }
586 
587 template<typename T>
setNumSegments(const uint num)588 void Circle<T>::setNumSegments(const uint num)
589 {
590     DISTRHO_SAFE_ASSERT_RETURN(num >= 3,);
591 
592     if (fNumSegments == num)
593         return;
594 
595     fNumSegments = num;
596 
597     fTheta = M_2PIf / static_cast<float>(fNumSegments);
598     fCos = std::cos(fTheta);
599     fSin = std::sin(fTheta);
600 }
601 
602 template<typename T>
draw()603 void Circle<T>::draw()
604 {
605     _draw(false);
606 }
607 
608 template<typename T>
drawOutline()609 void Circle<T>::drawOutline()
610 {
611     _draw(true);
612 }
613 
614 template<typename T>
operator =(const Circle<T> & cir)615 Circle<T>& Circle<T>::operator=(const Circle<T>& cir) noexcept
616 {
617     fPos   = cir.fPos;
618     fSize  = cir.fSize;
619     fTheta = cir.fTheta;
620     fCos   = cir.fCos;
621     fSin   = cir.fSin;
622     fNumSegments = cir.fNumSegments;
623     return *this;
624 }
625 
626 template<typename T>
operator ==(const Circle<T> & cir) const627 bool Circle<T>::operator==(const Circle<T>& cir) const noexcept
628 {
629     return (fPos == cir.fPos && d_isEqual(fSize, cir.fSize) && fNumSegments == cir.fNumSegments);
630 }
631 
632 template<typename T>
operator !=(const Circle<T> & cir) const633 bool Circle<T>::operator!=(const Circle<T>& cir) const noexcept
634 {
635     return (fPos != cir.fPos || d_isNotEqual(fSize, cir.fSize) || fNumSegments != cir.fNumSegments);
636 }
637 
638 // -----------------------------------------------------------------------
639 // Triangle
640 
641 template<typename T>
Triangle()642 Triangle<T>::Triangle() noexcept
643     : fPos1(0, 0),
644       fPos2(0, 0),
645       fPos3(0, 0) {}
646 
647 template<typename T>
Triangle(const T & x1,const T & y1,const T & x2,const T & y2,const T & x3,const T & y3)648 Triangle<T>::Triangle(const T& x1, const T& y1, const T& x2, const T& y2, const T& x3, const T& y3) noexcept
649     : fPos1(x1, y1),
650       fPos2(x2, y2),
651       fPos3(x3, y3) {}
652 
653 template<typename T>
Triangle(const Point<T> & pos1,const Point<T> & pos2,const Point<T> & pos3)654 Triangle<T>::Triangle(const Point<T>& pos1, const Point<T>& pos2, const Point<T>& pos3) noexcept
655     : fPos1(pos1),
656       fPos2(pos2),
657       fPos3(pos3) {}
658 
659 template<typename T>
Triangle(const Triangle<T> & tri)660 Triangle<T>::Triangle(const Triangle<T>& tri) noexcept
661     : fPos1(tri.fPos1),
662       fPos2(tri.fPos2),
663       fPos3(tri.fPos3) {}
664 
665 template<typename T>
isNull() const666 bool Triangle<T>::isNull() const noexcept
667 {
668     return fPos1 == fPos2 && fPos1 == fPos3;
669 }
670 
671 template<typename T>
isNotNull() const672 bool Triangle<T>::isNotNull() const noexcept
673 {
674     return fPos1 != fPos2 || fPos1 != fPos3;
675 }
676 
677 template<typename T>
isValid() const678 bool Triangle<T>::isValid() const noexcept
679 {
680     return fPos1 != fPos2 && fPos1 != fPos3;
681 }
682 
683 template<typename T>
isInvalid() const684 bool Triangle<T>::isInvalid() const noexcept
685 {
686     return fPos1 == fPos2 || fPos1 == fPos3;
687 }
688 
689 template<typename T>
draw()690 void Triangle<T>::draw()
691 {
692     _draw(false);
693 }
694 
695 template<typename T>
drawOutline()696 void Triangle<T>::drawOutline()
697 {
698     _draw(true);
699 }
700 
701 template<typename T>
operator =(const Triangle<T> & tri)702 Triangle<T>& Triangle<T>::operator=(const Triangle<T>& tri) noexcept
703 {
704     fPos1 = tri.fPos1;
705     fPos2 = tri.fPos2;
706     fPos3 = tri.fPos3;
707     return *this;
708 }
709 
710 template<typename T>
operator ==(const Triangle<T> & tri) const711 bool Triangle<T>::operator==(const Triangle<T>& tri) const noexcept
712 {
713     return (fPos1 == tri.fPos1 && fPos2 == tri.fPos2 && fPos3 == tri.fPos3);
714 }
715 
716 template<typename T>
operator !=(const Triangle<T> & tri) const717 bool Triangle<T>::operator!=(const Triangle<T>& tri) const noexcept
718 {
719     return (fPos1 != tri.fPos1 || fPos2 != tri.fPos2 || fPos3 != tri.fPos3);
720 }
721 
722 // -----------------------------------------------------------------------
723 // Rectangle
724 
725 template<typename T>
Rectangle()726 Rectangle<T>::Rectangle() noexcept
727     : fPos(0, 0),
728       fSize(0, 0) {}
729 
730 template<typename T>
Rectangle(const T & x,const T & y,const T & width,const T & height)731 Rectangle<T>::Rectangle(const T& x, const T& y, const T& width, const T& height) noexcept
732     : fPos(x, y),
733       fSize(width, height) {}
734 
735 template<typename T>
Rectangle(const T & x,const T & y,const Size<T> & size)736 Rectangle<T>::Rectangle(const T& x, const T& y, const Size<T>& size) noexcept
737     : fPos(x, y),
738       fSize(size) {}
739 
740 template<typename T>
Rectangle(const Point<T> & pos,const T & width,const T & height)741 Rectangle<T>::Rectangle(const Point<T>& pos, const T& width, const T& height) noexcept
742     : fPos(pos),
743       fSize(width, height) {}
744 
745 template<typename T>
Rectangle(const Point<T> & pos,const Size<T> & size)746 Rectangle<T>::Rectangle(const Point<T>& pos, const Size<T>& size) noexcept
747     : fPos(pos),
748       fSize(size) {}
749 
750 template<typename T>
Rectangle(const Rectangle<T> & rect)751 Rectangle<T>::Rectangle(const Rectangle<T>& rect) noexcept
752     : fPos(rect.fPos),
753       fSize(rect.fSize) {}
754 
755 template<typename T>
getX() const756 const T& Rectangle<T>::getX() const noexcept
757 {
758     return fPos.fX;
759 }
760 
761 template<typename T>
getY() const762 const T& Rectangle<T>::getY() const noexcept
763 {
764     return fPos.fY;
765 }
766 
767 template<typename T>
getWidth() const768 const T& Rectangle<T>::getWidth() const noexcept
769 {
770     return fSize.fWidth;
771 }
772 
773 template<typename T>
getHeight() const774 const T& Rectangle<T>::getHeight() const noexcept
775 {
776     return fSize.fHeight;
777 }
778 
779 template<typename T>
getPos() const780 const Point<T>& Rectangle<T>::getPos() const noexcept
781 {
782     return fPos;
783 }
784 
785 template<typename T>
getSize() const786 const Size<T>& Rectangle<T>::getSize() const noexcept
787 {
788     return fSize;
789 }
790 
791 template<typename T>
setX(const T & x)792 void Rectangle<T>::setX(const T& x) noexcept
793 {
794     fPos.fX = x;
795 }
796 
797 template<typename T>
setY(const T & y)798 void Rectangle<T>::setY(const T& y) noexcept
799 {
800     fPos.fY = y;
801 }
802 
803 template<typename T>
setPos(const T & x,const T & y)804 void Rectangle<T>::setPos(const T& x, const T& y) noexcept
805 {
806     fPos.fX = x;
807     fPos.fY = y;
808 }
809 
810 template<typename T>
setPos(const Point<T> & pos)811 void Rectangle<T>::setPos(const Point<T>& pos) noexcept
812 {
813     fPos = pos;
814 }
815 
816 template<typename T>
moveBy(const T & x,const T & y)817 void Rectangle<T>::moveBy(const T& x, const T& y) noexcept
818 {
819     fPos.moveBy(x, y);
820 }
821 
822 template<typename T>
moveBy(const Point<T> & pos)823 void Rectangle<T>::moveBy(const Point<T>& pos) noexcept
824 {
825     fPos.moveBy(pos);
826 }
827 
828 template<typename T>
setWidth(const T & width)829 void Rectangle<T>::setWidth(const T& width) noexcept
830 {
831     fSize.fWidth = width;
832 }
833 
834 template<typename T>
setHeight(const T & height)835 void Rectangle<T>::setHeight(const T& height) noexcept
836 {
837     fSize.fHeight = height;
838 }
839 
840 template<typename T>
setSize(const T & width,const T & height)841 void Rectangle<T>::setSize(const T& width, const T& height) noexcept
842 {
843     fSize.fWidth  = width;
844     fSize.fHeight = height;
845 }
846 
847 template<typename T>
setSize(const Size<T> & size)848 void Rectangle<T>::setSize(const Size<T>& size) noexcept
849 {
850     fSize = size;
851 }
852 
853 template<typename T>
growBy(double multiplier)854 void Rectangle<T>::growBy(double multiplier) noexcept
855 {
856     fSize.growBy(multiplier);
857 }
858 
859 template<typename T>
shrinkBy(double divider)860 void Rectangle<T>::shrinkBy(double divider) noexcept
861 {
862     fSize.shrinkBy(divider);
863 }
864 
865 template<typename T>
setRectangle(const Point<T> & pos,const Size<T> & size)866 void Rectangle<T>::setRectangle(const Point<T>& pos, const Size<T>& size) noexcept
867 {
868     fPos  = pos;
869     fSize = size;
870 }
871 
872 template<typename T>
setRectangle(const Rectangle<T> & rect)873 void Rectangle<T>::setRectangle(const Rectangle<T>& rect) noexcept
874 {
875     fPos  = rect.fPos;
876     fSize = rect.fSize;
877 }
878 
879 template<typename T>
contains(const T & x,const T & y) const880 bool Rectangle<T>::contains(const T& x, const T& y) const noexcept
881 {
882     return (x >= fPos.fX && y >= fPos.fY && x <= fPos.fX+fSize.fWidth && y <= fPos.fY+fSize.fHeight);
883 }
884 
885 template<typename T>
contains(const Point<T> & pos) const886 bool Rectangle<T>::contains(const Point<T>& pos) const noexcept
887 {
888     return contains(pos.fX, pos.fY);
889 }
890 
891 template<typename T>
containsX(const T & x) const892 bool Rectangle<T>::containsX(const T& x) const noexcept
893 {
894     return (x >= fPos.fX && x <= fPos.fX + fSize.fWidth);
895 }
896 
897 template<typename T>
containsY(const T & y) const898 bool Rectangle<T>::containsY(const T& y) const noexcept
899 {
900     return (y >= fPos.fY && y <= fPos.fY + fSize.fHeight);
901 }
902 
903 template<typename T>
draw()904 void Rectangle<T>::draw()
905 {
906     _draw(false);
907 }
908 
909 template<typename T>
drawOutline()910 void Rectangle<T>::drawOutline()
911 {
912     _draw(true);
913 }
914 
915 template<typename T>
operator =(const Rectangle<T> & rect)916 Rectangle<T>& Rectangle<T>::operator=(const Rectangle<T>& rect) noexcept
917 {
918     fPos  = rect.fPos;
919     fSize = rect.fSize;
920     return *this;
921 }
922 
923 template<typename T>
operator *=(double m)924 Rectangle<T>& Rectangle<T>::operator*=(double m) noexcept
925 {
926     fSize *= m;
927     return *this;
928 }
929 
930 template<typename T>
operator /=(double d)931 Rectangle<T>& Rectangle<T>::operator/=(double d) noexcept
932 {
933     fSize /= d;
934     return *this;
935 }
936 
937 template<typename T>
operator ==(const Rectangle<T> & rect) const938 bool Rectangle<T>::operator==(const Rectangle<T>& rect) const noexcept
939 {
940     return (fPos == rect.fPos && fSize == rect.fSize);
941 }
942 
943 template<typename T>
operator !=(const Rectangle<T> & rect) const944 bool Rectangle<T>::operator!=(const Rectangle<T>& rect) const noexcept
945 {
946     return (fPos != rect.fPos || fSize != rect.fSize);
947 }
948 
949 // -----------------------------------------------------------------------
950 // Possible template data types
951 
952 template class Point<double>;
953 template class Point<float>;
954 template class Point<int>;
955 template class Point<uint>;
956 template class Point<short>;
957 template class Point<ushort>;
958 
959 template class Size<double>;
960 template class Size<float>;
961 template class Size<int>;
962 template class Size<uint>;
963 template class Size<short>;
964 template class Size<ushort>;
965 
966 template class Line<double>;
967 template class Line<float>;
968 template class Line<int>;
969 template class Line<uint>;
970 template class Line<short>;
971 template class Line<ushort>;
972 
973 template class Circle<double>;
974 template class Circle<float>;
975 template class Circle<int>;
976 template class Circle<uint>;
977 template class Circle<short>;
978 template class Circle<ushort>;
979 
980 template class Triangle<double>;
981 template class Triangle<float>;
982 template class Triangle<int>;
983 template class Triangle<uint>;
984 template class Triangle<short>;
985 template class Triangle<ushort>;
986 
987 template class Rectangle<double>;
988 template class Rectangle<float>;
989 template class Rectangle<int>;
990 template class Rectangle<uint>;
991 template class Rectangle<short>;
992 template class Rectangle<ushort>;
993 
994 // -----------------------------------------------------------------------
995 
996 END_NAMESPACE_DGL
997