1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2016 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 > 1 && fHeight > 1;
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>
draw()445 void Line<T>::draw()
446 {
447     DISTRHO_SAFE_ASSERT_RETURN(fPosStart != fPosEnd,);
448 
449     glBegin(GL_LINES);
450 
451     {
452         glVertex2d(fPosStart.fX, fPosStart.fY);
453         glVertex2d(fPosEnd.fX, fPosEnd.fY);
454     }
455 
456     glEnd();
457 }
458 
459 template<typename T>
isNull() const460 bool Line<T>::isNull() const noexcept
461 {
462     return fPosStart == fPosEnd;
463 }
464 
465 template<typename T>
isNotNull() const466 bool Line<T>::isNotNull() const noexcept
467 {
468     return fPosStart != fPosEnd;
469 }
470 
471 template<typename T>
operator =(const Line<T> & line)472 Line<T>& Line<T>::operator=(const Line<T>& line) noexcept
473 {
474     fPosStart = line.fPosStart;
475     fPosEnd   = line.fPosEnd;
476     return *this;
477 }
478 
479 template<typename T>
operator ==(const Line<T> & line) const480 bool Line<T>::operator==(const Line<T>& line) const noexcept
481 {
482     return (fPosStart == line.fPosStart && fPosEnd == line.fPosEnd);
483 }
484 
485 template<typename T>
operator !=(const Line<T> & line) const486 bool Line<T>::operator!=(const Line<T>& line) const noexcept
487 {
488     return (fPosStart != line.fPosStart || fPosEnd != line.fPosEnd);
489 }
490 
491 // -----------------------------------------------------------------------
492 // Circle
493 
494 template<typename T>
Circle()495 Circle<T>::Circle() noexcept
496     : fPos(0, 0),
497       fSize(0.0f),
498       fNumSegments(0),
499       fTheta(0.0f),
500       fCos(0.0f),
501       fSin(0.0f) {}
502 
503 template<typename T>
Circle(const T & x,const T & y,const float size,const uint numSegments)504 Circle<T>::Circle(const T& x, const T& y, const float size, const uint numSegments)
505     : fPos(x, y),
506       fSize(size),
507       fNumSegments(numSegments >= 3 ? numSegments : 3),
508       fTheta(M_2PIf / static_cast<float>(fNumSegments)),
509       fCos(std::cos(fTheta)),
510       fSin(std::sin(fTheta))
511 {
512     DISTRHO_SAFE_ASSERT(fSize > 0.0f);
513 }
514 
515 template<typename T>
Circle(const Point<T> & pos,const float size,const uint numSegments)516 Circle<T>::Circle(const Point<T>& pos, const float size, const uint numSegments)
517     : fPos(pos),
518       fSize(size),
519       fNumSegments(numSegments >= 3 ? numSegments : 3),
520       fTheta(M_2PIf / static_cast<float>(fNumSegments)),
521       fCos(std::cos(fTheta)),
522       fSin(std::sin(fTheta))
523 {
524     DISTRHO_SAFE_ASSERT(fSize > 0.0f);
525 }
526 
527 template<typename T>
Circle(const Circle<T> & cir)528 Circle<T>::Circle(const Circle<T>& cir) noexcept
529     : fPos(cir.fPos),
530       fSize(cir.fSize),
531       fNumSegments(cir.fNumSegments),
532       fTheta(cir.fTheta),
533       fCos(cir.fCos),
534       fSin(cir.fSin)
535 {
536     DISTRHO_SAFE_ASSERT(fSize > 0.0f);
537 }
538 
539 template<typename T>
getX() const540 const T& Circle<T>::getX() const noexcept
541 {
542     return fPos.fX;
543 }
544 
545 template<typename T>
getY() const546 const T& Circle<T>::getY() const noexcept
547 {
548     return fPos.fY;
549 }
550 
551 template<typename T>
getPos() const552 const Point<T>& Circle<T>::getPos() const noexcept
553 {
554     return fPos;
555 }
556 
557 template<typename T>
setX(const T & x)558 void Circle<T>::setX(const T& x) noexcept
559 {
560     fPos.fX = x;
561 }
562 
563 template<typename T>
setY(const T & y)564 void Circle<T>::setY(const T& y) noexcept
565 {
566     fPos.fY = y;
567 }
568 
569 template<typename T>
setPos(const T & x,const T & y)570 void Circle<T>::setPos(const T& x, const T& y) noexcept
571 {
572     fPos.fX = x;
573     fPos.fY = y;
574 }
575 
576 template<typename T>
setPos(const Point<T> & pos)577 void Circle<T>::setPos(const Point<T>& pos) noexcept
578 {
579     fPos = pos;
580 }
581 
582 template<typename T>
getSize() const583 float Circle<T>::getSize() const noexcept
584 {
585     return fSize;
586 }
587 
588 template<typename T>
setSize(const float size)589 void Circle<T>::setSize(const float size) noexcept
590 {
591     DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,);
592 
593     fSize = size;
594 }
595 
596 template<typename T>
getNumSegments() const597 uint Circle<T>::getNumSegments() const noexcept
598 {
599     return fNumSegments;
600 }
601 
602 template<typename T>
setNumSegments(const uint num)603 void Circle<T>::setNumSegments(const uint num)
604 {
605     DISTRHO_SAFE_ASSERT_RETURN(num >= 3,);
606 
607     if (fNumSegments == num)
608         return;
609 
610     fNumSegments = num;
611 
612     fTheta = M_2PIf / static_cast<float>(fNumSegments);
613     fCos = std::cos(fTheta);
614     fSin = std::sin(fTheta);
615 }
616 
617 template<typename T>
draw()618 void Circle<T>::draw()
619 {
620     _draw(false);
621 }
622 
623 template<typename T>
drawOutline()624 void Circle<T>::drawOutline()
625 {
626     _draw(true);
627 }
628 
629 template<typename T>
operator =(const Circle<T> & cir)630 Circle<T>& Circle<T>::operator=(const Circle<T>& cir) noexcept
631 {
632     fPos   = cir.fPos;
633     fSize  = cir.fSize;
634     fTheta = cir.fTheta;
635     fCos   = cir.fCos;
636     fSin   = cir.fSin;
637     fNumSegments = cir.fNumSegments;
638     return *this;
639 }
640 
641 template<typename T>
operator ==(const Circle<T> & cir) const642 bool Circle<T>::operator==(const Circle<T>& cir) const noexcept
643 {
644     return (fPos == cir.fPos && d_isEqual(fSize, cir.fSize) && fNumSegments == cir.fNumSegments);
645 }
646 
647 template<typename T>
operator !=(const Circle<T> & cir) const648 bool Circle<T>::operator!=(const Circle<T>& cir) const noexcept
649 {
650     return (fPos != cir.fPos || d_isNotEqual(fSize, cir.fSize) || fNumSegments != cir.fNumSegments);
651 }
652 
653 template<typename T>
_draw(const bool outline)654 void Circle<T>::_draw(const bool outline)
655 {
656     DISTRHO_SAFE_ASSERT_RETURN(fNumSegments >= 3 && fSize > 0.0f,);
657 
658     double t, x = fSize, y = 0.0;
659 
660     glBegin(outline ? GL_LINE_LOOP : GL_POLYGON);
661 
662     for (uint i=0; i<fNumSegments; ++i)
663     {
664         glVertex2d(x + fPos.fX, y + fPos.fY);
665 
666         t = x;
667         x = fCos * x - fSin * y;
668         y = fSin * t + fCos * y;
669     }
670 
671     glEnd();
672 }
673 
674 // -----------------------------------------------------------------------
675 // Triangle
676 
677 template<typename T>
Triangle()678 Triangle<T>::Triangle() noexcept
679     : fPos1(0, 0),
680       fPos2(0, 0),
681       fPos3(0, 0) {}
682 
683 template<typename T>
Triangle(const T & x1,const T & y1,const T & x2,const T & y2,const T & x3,const T & y3)684 Triangle<T>::Triangle(const T& x1, const T& y1, const T& x2, const T& y2, const T& x3, const T& y3) noexcept
685     : fPos1(x1, y1),
686       fPos2(x2, y2),
687       fPos3(x3, y3) {}
688 
689 template<typename T>
Triangle(const Point<T> & pos1,const Point<T> & pos2,const Point<T> & pos3)690 Triangle<T>::Triangle(const Point<T>& pos1, const Point<T>& pos2, const Point<T>& pos3) noexcept
691     : fPos1(pos1),
692       fPos2(pos2),
693       fPos3(pos3) {}
694 
695 template<typename T>
Triangle(const Triangle<T> & tri)696 Triangle<T>::Triangle(const Triangle<T>& tri) noexcept
697     : fPos1(tri.fPos1),
698       fPos2(tri.fPos2),
699       fPos3(tri.fPos3) {}
700 
701 template<typename T>
draw()702 void Triangle<T>::draw()
703 {
704     _draw(false);
705 }
706 
707 template<typename T>
drawOutline()708 void Triangle<T>::drawOutline()
709 {
710     _draw(true);
711 }
712 
713 template<typename T>
isNull() const714 bool Triangle<T>::isNull() const noexcept
715 {
716     return fPos1 == fPos2 && fPos1 == fPos3;
717 }
718 
719 template<typename T>
isNotNull() const720 bool Triangle<T>::isNotNull() const noexcept
721 {
722     return fPos1 != fPos2 || fPos1 != fPos3;
723 }
724 
725 template<typename T>
isValid() const726 bool Triangle<T>::isValid() const noexcept
727 {
728     return fPos1 != fPos2 && fPos1 != fPos3;
729 }
730 
731 template<typename T>
isInvalid() const732 bool Triangle<T>::isInvalid() const noexcept
733 {
734     return fPos1 == fPos2 || fPos1 == fPos3;
735 }
736 
737 template<typename T>
operator =(const Triangle<T> & tri)738 Triangle<T>& Triangle<T>::operator=(const Triangle<T>& tri) noexcept
739 {
740     fPos1 = tri.fPos1;
741     fPos2 = tri.fPos2;
742     fPos3 = tri.fPos3;
743     return *this;
744 }
745 
746 template<typename T>
operator ==(const Triangle<T> & tri) const747 bool Triangle<T>::operator==(const Triangle<T>& tri) const noexcept
748 {
749     return (fPos1 == tri.fPos1 && fPos2 == tri.fPos2 && fPos3 == tri.fPos3);
750 }
751 
752 template<typename T>
operator !=(const Triangle<T> & tri) const753 bool Triangle<T>::operator!=(const Triangle<T>& tri) const noexcept
754 {
755     return (fPos1 != tri.fPos1 || fPos2 != tri.fPos2 || fPos3 != tri.fPos3);
756 }
757 
758 template<typename T>
_draw(const bool outline)759 void Triangle<T>::_draw(const bool outline)
760 {
761     DISTRHO_SAFE_ASSERT_RETURN(fPos1 != fPos2 && fPos1 != fPos3,);
762 
763     glBegin(outline ? GL_LINE_LOOP : GL_TRIANGLES);
764 
765     {
766         glVertex2d(fPos1.fX, fPos1.fY);
767         glVertex2d(fPos2.fX, fPos2.fY);
768         glVertex2d(fPos3.fX, fPos3.fY);
769     }
770 
771     glEnd();
772 }
773 
774 // -----------------------------------------------------------------------
775 // Rectangle
776 
777 template<typename T>
Rectangle()778 Rectangle<T>::Rectangle() noexcept
779     : fPos(0, 0),
780       fSize(0, 0) {}
781 
782 template<typename T>
Rectangle(const T & x,const T & y,const T & width,const T & height)783 Rectangle<T>::Rectangle(const T& x, const T& y, const T& width, const T& height) noexcept
784     : fPos(x, y),
785       fSize(width, height) {}
786 
787 template<typename T>
Rectangle(const T & x,const T & y,const Size<T> & size)788 Rectangle<T>::Rectangle(const T& x, const T& y, const Size<T>& size) noexcept
789     : fPos(x, y),
790       fSize(size) {}
791 
792 template<typename T>
Rectangle(const Point<T> & pos,const T & width,const T & height)793 Rectangle<T>::Rectangle(const Point<T>& pos, const T& width, const T& height) noexcept
794     : fPos(pos),
795       fSize(width, height) {}
796 
797 template<typename T>
Rectangle(const Point<T> & pos,const Size<T> & size)798 Rectangle<T>::Rectangle(const Point<T>& pos, const Size<T>& size) noexcept
799     : fPos(pos),
800       fSize(size) {}
801 
802 template<typename T>
Rectangle(const Rectangle<T> & rect)803 Rectangle<T>::Rectangle(const Rectangle<T>& rect) noexcept
804     : fPos(rect.fPos),
805       fSize(rect.fSize) {}
806 
807 template<typename T>
getX() const808 const T& Rectangle<T>::getX() const noexcept
809 {
810     return fPos.fX;
811 }
812 
813 template<typename T>
getY() const814 const T& Rectangle<T>::getY() const noexcept
815 {
816     return fPos.fY;
817 }
818 
819 template<typename T>
getWidth() const820 const T& Rectangle<T>::getWidth() const noexcept
821 {
822     return fSize.fWidth;
823 }
824 
825 template<typename T>
getHeight() const826 const T& Rectangle<T>::getHeight() const noexcept
827 {
828     return fSize.fHeight;
829 }
830 
831 template<typename T>
getPos() const832 const Point<T>& Rectangle<T>::getPos() const noexcept
833 {
834     return fPos;
835 }
836 
837 template<typename T>
getSize() const838 const Size<T>& Rectangle<T>::getSize() const noexcept
839 {
840     return fSize;
841 }
842 
843 template<typename T>
setX(const T & x)844 void Rectangle<T>::setX(const T& x) noexcept
845 {
846     fPos.fX = x;
847 }
848 
849 template<typename T>
setY(const T & y)850 void Rectangle<T>::setY(const T& y) noexcept
851 {
852     fPos.fY = y;
853 }
854 
855 template<typename T>
setPos(const T & x,const T & y)856 void Rectangle<T>::setPos(const T& x, const T& y) noexcept
857 {
858     fPos.fX = x;
859     fPos.fY = y;
860 }
861 
862 template<typename T>
setPos(const Point<T> & pos)863 void Rectangle<T>::setPos(const Point<T>& pos) noexcept
864 {
865     fPos = pos;
866 }
867 
868 template<typename T>
moveBy(const T & x,const T & y)869 void Rectangle<T>::moveBy(const T& x, const T& y) noexcept
870 {
871     fPos.moveBy(x, y);
872 }
873 
874 template<typename T>
moveBy(const Point<T> & pos)875 void Rectangle<T>::moveBy(const Point<T>& pos) noexcept
876 {
877     fPos.moveBy(pos);
878 }
879 
880 template<typename T>
setWidth(const T & width)881 void Rectangle<T>::setWidth(const T& width) noexcept
882 {
883     fSize.fWidth = width;
884 }
885 
886 template<typename T>
setHeight(const T & height)887 void Rectangle<T>::setHeight(const T& height) noexcept
888 {
889     fSize.fHeight = height;
890 }
891 
892 template<typename T>
setSize(const T & width,const T & height)893 void Rectangle<T>::setSize(const T& width, const T& height) noexcept
894 {
895     fSize.fWidth  = width;
896     fSize.fHeight = height;
897 }
898 
899 template<typename T>
setSize(const Size<T> & size)900 void Rectangle<T>::setSize(const Size<T>& size) noexcept
901 {
902     fSize = size;
903 }
904 
905 template<typename T>
growBy(double multiplier)906 void Rectangle<T>::growBy(double multiplier) noexcept
907 {
908     fSize.growBy(multiplier);
909 }
910 
911 template<typename T>
shrinkBy(double divider)912 void Rectangle<T>::shrinkBy(double divider) noexcept
913 {
914     fSize.shrinkBy(divider);
915 }
916 
917 template<typename T>
setRectangle(const Point<T> & pos,const Size<T> & size)918 void Rectangle<T>::setRectangle(const Point<T>& pos, const Size<T>& size) noexcept
919 {
920     fPos  = pos;
921     fSize = size;
922 }
923 
924 template<typename T>
setRectangle(const Rectangle<T> & rect)925 void Rectangle<T>::setRectangle(const Rectangle<T>& rect) noexcept
926 {
927     fPos  = rect.fPos;
928     fSize = rect.fSize;
929 }
930 
931 template<typename T>
contains(const T & x,const T & y) const932 bool Rectangle<T>::contains(const T& x, const T& y) const noexcept
933 {
934     return (x >= fPos.fX && y >= fPos.fY && x <= fPos.fX+fSize.fWidth && y <= fPos.fY+fSize.fHeight);
935 }
936 
937 template<typename T>
contains(const Point<T> & pos) const938 bool Rectangle<T>::contains(const Point<T>& pos) const noexcept
939 {
940     return contains(pos.fX, pos.fY);
941 }
942 
943 template<typename T>
containsX(const T & x) const944 bool Rectangle<T>::containsX(const T& x) const noexcept
945 {
946     return (x >= fPos.fX && x <= fPos.fX + fSize.fWidth);
947 }
948 
949 template<typename T>
containsY(const T & y) const950 bool Rectangle<T>::containsY(const T& y) const noexcept
951 {
952     return (y >= fPos.fY && y <= fPos.fY + fSize.fHeight);
953 }
954 
955 template<typename T>
draw()956 void Rectangle<T>::draw()
957 {
958     _draw(false);
959 }
960 
961 template<typename T>
drawOutline()962 void Rectangle<T>::drawOutline()
963 {
964     _draw(true);
965 }
966 
967 template<typename T>
operator =(const Rectangle<T> & rect)968 Rectangle<T>& Rectangle<T>::operator=(const Rectangle<T>& rect) noexcept
969 {
970     fPos  = rect.fPos;
971     fSize = rect.fSize;
972     return *this;
973 }
974 
975 template<typename T>
operator *=(double m)976 Rectangle<T>& Rectangle<T>::operator*=(double m) noexcept
977 {
978     fSize *= m;
979     return *this;
980 }
981 
982 template<typename T>
operator /=(double d)983 Rectangle<T>& Rectangle<T>::operator/=(double d) noexcept
984 {
985     fSize /= d;
986     return *this;
987 }
988 
989 template<typename T>
operator ==(const Rectangle<T> & rect) const990 bool Rectangle<T>::operator==(const Rectangle<T>& rect) const noexcept
991 {
992     return (fPos == rect.fPos && fSize == rect.fSize);
993 }
994 
995 template<typename T>
operator !=(const Rectangle<T> & rect) const996 bool Rectangle<T>::operator!=(const Rectangle<T>& rect) const noexcept
997 {
998     return (fPos != rect.fPos || fSize != rect.fSize);
999 }
1000 
1001 template<typename T>
_draw(const bool outline)1002 void Rectangle<T>::_draw(const bool outline)
1003 {
1004     DISTRHO_SAFE_ASSERT_RETURN(fSize.isValid(),);
1005 
1006     glBegin(outline ? GL_LINE_LOOP : GL_QUADS);
1007 
1008     {
1009         glTexCoord2f(0.0f, 0.0f);
1010         glVertex2d(fPos.fX, fPos.fY);
1011 
1012         glTexCoord2f(1.0f, 0.0f);
1013         glVertex2d(fPos.fX+fSize.fWidth, fPos.fY);
1014 
1015         glTexCoord2f(1.0f, 1.0f);
1016         glVertex2d(fPos.fX+fSize.fWidth, fPos.fY+fSize.fHeight);
1017 
1018         glTexCoord2f(0.0f, 1.0f);
1019         glVertex2d(fPos.fX, fPos.fY+fSize.fHeight);
1020     }
1021 
1022     glEnd();
1023 }
1024 
1025 // -----------------------------------------------------------------------
1026 // Possible template data types
1027 
1028 template class Point<double>;
1029 template class Point<float>;
1030 template class Point<int>;
1031 template class Point<uint>;
1032 template class Point<short>;
1033 template class Point<ushort>;
1034 
1035 template class Size<double>;
1036 template class Size<float>;
1037 template class Size<int>;
1038 template class Size<uint>;
1039 template class Size<short>;
1040 template class Size<ushort>;
1041 
1042 template class Line<double>;
1043 template class Line<float>;
1044 template class Line<int>;
1045 template class Line<uint>;
1046 template class Line<short>;
1047 template class Line<ushort>;
1048 
1049 template class Circle<double>;
1050 template class Circle<float>;
1051 template class Circle<int>;
1052 template class Circle<uint>;
1053 template class Circle<short>;
1054 template class Circle<ushort>;
1055 
1056 template class Triangle<double>;
1057 template class Triangle<float>;
1058 template class Triangle<int>;
1059 template class Triangle<uint>;
1060 template class Triangle<short>;
1061 template class Triangle<ushort>;
1062 
1063 template class Rectangle<double>;
1064 template class Rectangle<float>;
1065 template class Rectangle<int>;
1066 template class Rectangle<uint>;
1067 template class Rectangle<short>;
1068 template class Rectangle<ushort>;
1069 
1070 // -----------------------------------------------------------------------
1071 
1072 END_NAMESPACE_DGL
1073