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