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 #ifndef DGL_GEOMETRY_HPP_INCLUDED
18 #define DGL_GEOMETRY_HPP_INCLUDED
19 
20 #include "Base.hpp"
21 
22 START_NAMESPACE_DGL
23 
24 // -----------------------------------------------------------------------
25 // Forward class names
26 
27 template<typename> class Line;
28 template<typename> class Circle;
29 template<typename> class Triangle;
30 template<typename> class Rectangle;
31 
32 // -----------------------------------------------------------------------
33 
34 /**
35    DGL Point class.
36 
37    This class describes a single point in space, defined by an X and Y value.
38  */
39 template<typename T>
40 class Point
41 {
42 public:
43    /**
44       Constructor for (0, 0) point.
45     */
46     Point() noexcept;
47 
48    /**
49       Constructor using custom X and Y values.
50     */
51     Point(const T& x, const T& y) noexcept;
52 
53    /**
54       Constructor using another Point class values.
55     */
56     Point(const Point<T>& pos) noexcept;
57 
58    /**
59       Get X value.
60     */
61     const T& getX() const noexcept;
62 
63    /**
64       Get Y value.
65     */
66     const T& getY() const noexcept;
67 
68    /**
69       Set X value to @a x.
70     */
71     void setX(const T& x) noexcept;
72 
73    /**
74       Set Y value to @a y.
75     */
76     void setY(const T& y) noexcept;
77 
78    /**
79       Set X and Y values to @a x and @a y respectively.
80     */
81     void setPos(const T& x, const T& y) noexcept;
82 
83    /**
84       Set X and Y values according to @a pos.
85     */
86     void setPos(const Point<T>& pos) noexcept;
87 
88    /**
89       Move this point by @a x and @a y values.
90     */
91     void moveBy(const T& x, const T& y) noexcept;
92 
93    /**
94       Move this point by @a pos.
95     */
96     void moveBy(const Point<T>& pos) noexcept;
97 
98    /**
99       Return true if point is (0, 0).
100     */
101     bool isZero() const noexcept;
102 
103    /**
104       Return true if point is not (0, 0).
105     */
106     bool isNotZero() const noexcept;
107 
108     Point<T> operator+(const Point<T>& pos) noexcept;
109     Point<T> operator-(const Point<T>& pos) noexcept;
110     Point<T>& operator=(const Point<T>& pos) noexcept;
111     Point<T>& operator+=(const Point<T>& pos) noexcept;
112     Point<T>& operator-=(const Point<T>& pos) noexcept;
113     bool operator==(const Point<T>& pos) const noexcept;
114     bool operator!=(const Point<T>& pos) const noexcept;
115 
116 private:
117     T fX, fY;
118     template<typename> friend class Line;
119     template<typename> friend class Circle;
120     template<typename> friend class Triangle;
121     template<typename> friend class Rectangle;
122 };
123 
124 // -----------------------------------------------------------------------
125 
126 /**
127    DGL Size class.
128 
129    This class describes a size, defined by a width and height value.
130  */
131 template<typename T>
132 class Size
133 {
134 public:
135    /**
136       Constructor for null size (0x0).
137     */
138     Size() noexcept;
139 
140    /**
141       Constructor using custom width and height values.
142     */
143     Size(const T& width, const T& height) noexcept;
144 
145    /**
146       Constructor using another Size class values.
147     */
148     Size(const Size<T>& size) noexcept;
149 
150    /**
151       Get width.
152     */
153     const T& getWidth() const noexcept;
154 
155    /**
156       Get height.
157     */
158     const T& getHeight() const noexcept;
159 
160    /**
161       Set width.
162     */
163     void setWidth(const T& width) noexcept;
164 
165    /**
166       Set height.
167     */
168     void setHeight(const T& height) noexcept;
169 
170    /**
171       Set size to @a width and @a height.
172     */
173     void setSize(const T& width, const T& height) noexcept;
174 
175    /**
176       Set size.
177     */
178     void setSize(const Size<T>& size) noexcept;
179 
180    /**
181       Grow size by @a multiplier.
182     */
183     void growBy(double multiplier) noexcept;
184 
185    /**
186       Shrink size by @a divider.
187     */
188     void shrinkBy(double divider) noexcept;
189 
190    /**
191       Return true if size is null (0x0).
192       An null size is also invalid.
193     */
194     bool isNull() const noexcept;
195 
196    /**
197       Return true if size is not null (0x0).
198       A non-null size is still invalid if its width or height is negative.
199     */
200     bool isNotNull() const noexcept;
201 
202    /**
203       Return true if size is valid (width and height are higher than zero).
204     */
205     bool isValid() const noexcept;
206 
207    /**
208       Return true if size is invalid (width or height are lower or equal to zero).
209       An invalid size might not be null under some circumstances.
210     */
211     bool isInvalid() const noexcept;
212 
213     Size<T> operator+(const Size<T>& size) noexcept;
214     Size<T> operator-(const Size<T>& size) noexcept;
215     Size<T>& operator=(const Size<T>& size) noexcept;
216     Size<T>& operator+=(const Size<T>& size) noexcept;
217     Size<T>& operator-=(const Size<T>& size) noexcept;
218     Size<T>& operator*=(double m) noexcept;
219     Size<T>& operator/=(double d) noexcept;
220     bool operator==(const Size<T>& size) const noexcept;
221     bool operator!=(const Size<T>& size) const noexcept;
222 
223 private:
224     T fWidth, fHeight;
225     template<typename> friend class Rectangle;
226 };
227 
228 // -----------------------------------------------------------------------
229 
230 /**
231    DGL Line class.
232 
233    This class describes a line, defined by two points.
234  */
235 template<typename T>
236 class Line
237 {
238 public:
239    /**
240       Constructor for a null line ([0,0] to [0,0]).
241     */
242     Line() noexcept;
243 
244    /**
245       Constructor using custom start X, start Y, end X and end Y values.
246     */
247     Line(const T& startX, const T& startY, const T& endX, const T& endY) noexcept;
248 
249    /**
250       Constructor using custom start X, start Y and end pos values.
251     */
252     Line(const T& startX, const T& startY, const Point<T>& endPos) noexcept;
253 
254    /**
255       Constructor using custom start pos, end X and end Y values.
256     */
257     Line(const Point<T>& startPos, const T& endX, const T& endY) noexcept;
258 
259    /**
260       Constructor using custom start and end pos values.
261     */
262     Line(const Point<T>& startPos, const Point<T>& endPos) noexcept;
263 
264    /**
265       Constructor using another Line class values.
266     */
267     Line(const Line<T>& line) noexcept;
268 
269    /**
270       Get start X value.
271     */
272     const T& getStartX() const noexcept;
273 
274    /**
275       Get start Y value.
276     */
277     const T& getStartY() const noexcept;
278 
279    /**
280       Get end X value.
281     */
282     const T& getEndX() const noexcept;
283 
284    /**
285       Get end Y value.
286     */
287     const T& getEndY() const noexcept;
288 
289    /**
290       Get start position.
291     */
292     const Point<T>& getStartPos() const noexcept;
293 
294    /**
295       Get end position.
296     */
297     const Point<T>& getEndPos() const noexcept;
298 
299    /**
300       Set start X value to @a x.
301     */
302     void setStartX(const T& x) noexcept;
303 
304    /**
305       Set start Y value to @a y.
306     */
307     void setStartY(const T& y) noexcept;
308 
309    /**
310       Set start X and Y values to @a x and @a y respectively.
311     */
312     void setStartPos(const T& x, const T& y) noexcept;
313 
314    /**
315       Set start X and Y values according to @a pos.
316     */
317     void setStartPos(const Point<T>& pos) noexcept;
318 
319    /**
320       Set end X value to @a x.
321     */
322     void setEndX(const T& x) noexcept;
323 
324    /**
325       Set end Y value to @a y.
326     */
327     void setEndY(const T& y) noexcept;
328 
329    /**
330       Set end X and Y values to @a x and @a y respectively.
331     */
332     void setEndPos(const T& x, const T& y) noexcept;
333 
334    /**
335       Set end X and Y values according to @a pos.
336     */
337     void setEndPos(const Point<T>& pos) noexcept;
338 
339    /**
340       Move this line by @a x and @a y values.
341     */
342     void moveBy(const T& x, const T& y) noexcept;
343 
344    /**
345       Move this line by @a pos.
346     */
347     void moveBy(const Point<T>& pos) noexcept;
348 
349    /**
350       Draw this line using the current OpenGL state.
351     */
352     void draw();
353 
354    /**
355       Return true if line is null (start and end pos are equal).
356     */
357     bool isNull() const noexcept;
358 
359    /**
360       Return true if line is not null (start and end pos are different).
361     */
362     bool isNotNull() const noexcept;
363 
364     Line<T>& operator=(const Line<T>& line) noexcept;
365     bool operator==(const Line<T>& line) const noexcept;
366     bool operator!=(const Line<T>& line) const noexcept;
367 
368 private:
369     Point<T> fPosStart, fPosEnd;
370 };
371 
372 // -----------------------------------------------------------------------
373 
374 /**
375    DGL Circle class.
376 
377    This class describes a circle, defined by position, size and a minimum of 3 segments.
378 
379    TODO: report if circle starts at top-left, bottom-right or center.
380          and size grows from which point?
381  */
382 template<typename T>
383 class Circle
384 {
385 public:
386    /**
387       Constructor for a null circle.
388     */
389     Circle() noexcept;
390 
391    /**
392       Constructor using custom X, Y and size values.
393     */
394     Circle(const T& x, const T& y, const float size, const uint numSegments = 300);
395 
396    /**
397       Constructor using custom position and size values.
398     */
399     Circle(const Point<T>& pos, const float size, const uint numSegments = 300);
400 
401    /**
402       Constructor using another Circle class values.
403     */
404     Circle(const Circle<T>& cir) noexcept;
405 
406    /**
407       Get X value.
408     */
409     const T& getX() const noexcept;
410 
411    /**
412       Get Y value.
413     */
414     const T& getY() const noexcept;
415 
416    /**
417       Get position.
418     */
419     const Point<T>& getPos() const noexcept;
420 
421    /**
422       Set X value to @a x.
423     */
424     void setX(const T& x) noexcept;
425 
426    /**
427       Set Y value to @a y.
428     */
429     void setY(const T& y) noexcept;
430 
431    /**
432       Set X and Y values to @a x and @a y respectively.
433     */
434     void setPos(const T& x, const T& y) noexcept;
435 
436    /**
437       Set X and Y values according to @a pos.
438     */
439     void setPos(const Point<T>& pos) noexcept;
440 
441    /**
442       Get size.
443     */
444     float getSize() const noexcept;
445 
446    /**
447       Set size.
448       @note Must always be > 0
449     */
450     void setSize(const float size) noexcept;
451 
452    /**
453       Get the current number of line segments that make this circle.
454     */
455     uint getNumSegments() const noexcept;
456 
457    /**
458       Set the number of line segments that will make this circle.
459       @note Must always be >= 3
460     */
461     void setNumSegments(const uint num);
462 
463    /**
464       Draw this circle using the current OpenGL state.
465     */
466     void draw();
467 
468    /**
469       Draw lines (outline of this circle) using the current OpenGL state.
470     */
471     void drawOutline();
472 
473     Circle<T>& operator=(const Circle<T>& cir) noexcept;
474     bool operator==(const Circle<T>& cir) const noexcept;
475     bool operator!=(const Circle<T>& cir) const noexcept;
476 
477 private:
478     Point<T> fPos;
479     float    fSize;
480     uint     fNumSegments;
481 
482     // cached values
483     float fTheta, fCos, fSin;
484 
485    /** @internal */
486     void _draw(const bool outline);
487 };
488 
489 // -----------------------------------------------------------------------
490 
491 /**
492    DGL Triangle class.
493 
494    This class describes a triangle, defined by 3 points.
495  */
496 template<typename T>
497 class Triangle
498 {
499 public:
500    /**
501       Constructor for a null triangle.
502     */
503     Triangle() noexcept;
504 
505    /**
506       Constructor using custom X and Y values.
507     */
508     Triangle(const T& x1, const T& y1, const T& x2, const T& y2, const T& x3, const T& y3) noexcept;
509 
510    /**
511       Constructor using custom position values.
512     */
513     Triangle(const Point<T>& pos1, const Point<T>& pos2, const Point<T>& pos3) noexcept;
514 
515    /**
516       Constructor using another Triangle class values.
517     */
518     Triangle(const Triangle<T>& tri) noexcept;
519 
520    /**
521       Return true if triangle is null (all its points are equal).
522       An null triangle is also invalid.
523     */
524     bool isNull() const noexcept;
525 
526    /**
527       Return true if triangle is not null (one its points is different from the others).
528       A non-null triangle is still invalid if two of its points are equal.
529     */
530     bool isNotNull() const noexcept;
531 
532    /**
533       Return true if triangle is valid (all its points are different).
534     */
535     bool isValid() const noexcept;
536 
537    /**
538       Return true if triangle is invalid (one or two of its points are equal).
539       An invalid triangle might not be null under some circumstances.
540     */
541     bool isInvalid() const noexcept;
542 
543    /**
544       Draw this triangle using the current OpenGL state.
545     */
546     void draw();
547 
548    /**
549       Draw lines (outline of this triangle) using the current OpenGL state.
550     */
551     void drawOutline();
552 
553     Triangle<T>& operator=(const Triangle<T>& tri) noexcept;
554     bool operator==(const Triangle<T>& tri) const noexcept;
555     bool operator!=(const Triangle<T>& tri) const noexcept;
556 
557 private:
558     Point<T> fPos1, fPos2, fPos3;
559 
560    /** @internal */
561     void _draw(const bool outline);
562 };
563 
564 // -----------------------------------------------------------------------
565 
566 /**
567    DGL Rectangle class.
568 
569    This class describes a rectangle, defined by a starting point and a size.
570  */
571 template<typename T>
572 class Rectangle
573 {
574 public:
575    /**
576       Constructor for a null rectangle.
577     */
578     Rectangle() noexcept;
579 
580    /**
581       Constructor using custom X, Y, width and height values.
582     */
583     Rectangle(const T& x, const T& y, const T& width, const T& height) noexcept;
584 
585    /**
586       Constructor using custom X, Y and size values.
587     */
588     Rectangle(const T& x, const T& y, const Size<T>& size) noexcept;
589 
590    /**
591       Constructor using custom pos, width and height values.
592     */
593     Rectangle(const Point<T>& pos, const T& width, const T& height) noexcept;
594 
595    /**
596       Constructor using custom position and size.
597     */
598     Rectangle(const Point<T>& pos, const Size<T>& size) noexcept;
599 
600    /**
601       Constructor using another Rectangle class values.
602     */
603     Rectangle(const Rectangle<T>& rect) noexcept;
604 
605    /**
606       Get X value.
607     */
608     const T& getX() const noexcept;
609 
610    /**
611       Get Y value.
612     */
613     const T& getY() const noexcept;
614 
615    /**
616       Get width.
617     */
618     const T& getWidth() const noexcept;
619 
620    /**
621       Get height.
622     */
623     const T& getHeight() const noexcept;
624 
625    /**
626       Get position.
627     */
628     const Point<T>& getPos() const noexcept;
629 
630    /**
631       Get size.
632     */
633     const Size<T>& getSize() const noexcept;
634 
635    /**
636       Set X value as @a x.
637     */
638     void setX(const T& x) noexcept;
639 
640    /**
641       Set Y value as @a y.
642     */
643     void setY(const T& y) noexcept;
644 
645    /**
646       Set X and Y values as @a x and @a y respectively.
647     */
648     void setPos(const T& x, const T& y) noexcept;
649 
650    /**
651       Set X and Y values according to @a pos.
652     */
653     void setPos(const Point<T>& pos) noexcept;
654 
655    /**
656       Move this rectangle by @a x and @a y values.
657     */
658     void moveBy(const T& x, const T& y) noexcept;
659 
660    /**
661       Move this rectangle by @a pos.
662     */
663     void moveBy(const Point<T>& pos) noexcept;
664 
665    /**
666       Set width.
667     */
668     void setWidth(const T& width) noexcept;
669 
670    /**
671       Set height.
672     */
673     void setHeight(const T& height) noexcept;
674 
675    /**
676       Set size using @a width and @a height.
677     */
678     void setSize(const T& width, const T& height) noexcept;
679 
680    /**
681       Set size.
682     */
683     void setSize(const Size<T>& size) noexcept;
684 
685    /**
686       Grow size by @a multiplier.
687     */
688     void growBy(double multiplier) noexcept;
689 
690    /**
691       Shrink size by @a divider.
692     */
693     void shrinkBy(double divider) noexcept;
694 
695    /**
696       Set rectangle using @a pos and @a size.
697     */
698     void setRectangle(const Point<T>& pos, const Size<T>& size) noexcept;
699 
700    /**
701       Set rectangle.
702     */
703     void setRectangle(const Rectangle<T>& rect) noexcept;
704 
705    /**
706       Check if this rectangle contains the point defined by @a X and @a Y.
707     */
708     bool contains(const T& x, const T& y) const noexcept;
709 
710    /**
711       Check if this rectangle contains the point @a pos.
712     */
713     bool contains(const Point<T>& pos) const noexcept;
714 
715    /**
716       Check if this rectangle contains X.
717     */
718     bool containsX(const T& x) const noexcept;
719 
720    /**
721       Check if this rectangle contains Y.
722     */
723     bool containsY(const T& y) const noexcept;
724 
725    /**
726       Draw this rectangle using the current OpenGL state.
727     */
728     void draw();
729 
730    /**
731       Draw lines (outline of this rectangle) using the current OpenGL state.
732     */
733     void drawOutline();
734 
735     Rectangle<T>& operator=(const Rectangle<T>& rect) noexcept;
736     Rectangle<T>& operator*=(double m) noexcept;
737     Rectangle<T>& operator/=(double d) noexcept;
738     bool operator==(const Rectangle<T>& size) const noexcept;
739     bool operator!=(const Rectangle<T>& size) const noexcept;
740 
741 private:
742     Point<T> fPos;
743     Size<T>  fSize;
744 
745    /** @internal */
746     void _draw(const bool outline);
747 };
748 
749 // -----------------------------------------------------------------------
750 
751 END_NAMESPACE_DGL
752 
753 #endif // DGL_GEOMETRY_HPP_INCLUDED
754