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     void _draw(const bool outline);
486 };
487 
488 // -----------------------------------------------------------------------
489 
490 /**
491    DGL Triangle class.
492 
493    This class describes a triangle, defined by 3 points.
494  */
495 template<typename T>
496 class Triangle
497 {
498 public:
499    /**
500       Constructor for a null triangle.
501     */
502     Triangle() noexcept;
503 
504    /**
505       Constructor using custom X and Y values.
506     */
507     Triangle(const T& x1, const T& y1, const T& x2, const T& y2, const T& x3, const T& y3) noexcept;
508 
509    /**
510       Constructor using custom position values.
511     */
512     Triangle(const Point<T>& pos1, const Point<T>& pos2, const Point<T>& pos3) noexcept;
513 
514    /**
515       Constructor using another Triangle class values.
516     */
517     Triangle(const Triangle<T>& tri) noexcept;
518 
519    /**
520       Draw this triangle using the current OpenGL state.
521     */
522     void draw();
523 
524    /**
525       Draw lines (outline of this triangle) using the current OpenGL state.
526     */
527     void drawOutline();
528 
529    /**
530       Return true if triangle is null (all its points are equal).
531       An null triangle is also invalid.
532     */
533     bool isNull() const noexcept;
534 
535    /**
536       Return true if triangle is not null (one its points is different from the others).
537       A non-null triangle is still invalid if two of its points are equal.
538     */
539     bool isNotNull() const noexcept;
540 
541    /**
542       Return true if triangle is valid (all its points are different).
543     */
544     bool isValid() const noexcept;
545 
546    /**
547       Return true if triangle is invalid (one or two of its points are equal).
548       An invalid triangle might not be null under some circumstances.
549     */
550     bool isInvalid() const noexcept;
551 
552     Triangle<T>& operator=(const Triangle<T>& tri) noexcept;
553     bool operator==(const Triangle<T>& tri) const noexcept;
554     bool operator!=(const Triangle<T>& tri) const noexcept;
555 
556 private:
557     Point<T> fPos1, fPos2, fPos3;
558 
559     void _draw(const bool outline);
560 };
561 
562 // -----------------------------------------------------------------------
563 
564 /**
565    DGL Rectangle class.
566 
567    This class describes a rectangle, defined by a starting point and a size.
568  */
569 template<typename T>
570 class Rectangle
571 {
572 public:
573    /**
574       Constructor for a null rectangle.
575     */
576     Rectangle() noexcept;
577 
578    /**
579       Constructor using custom X, Y, width and height values.
580     */
581     Rectangle(const T& x, const T& y, const T& width, const T& height) noexcept;
582 
583    /**
584       Constructor using custom X, Y and size values.
585     */
586     Rectangle(const T& x, const T& y, const Size<T>& size) noexcept;
587 
588    /**
589       Constructor using custom pos, width and height values.
590     */
591     Rectangle(const Point<T>& pos, const T& width, const T& height) noexcept;
592 
593    /**
594       Constructor using custom position and size.
595     */
596     Rectangle(const Point<T>& pos, const Size<T>& size) noexcept;
597 
598    /**
599       Constructor using another Rectangle class values.
600     */
601     Rectangle(const Rectangle<T>& rect) noexcept;
602 
603    /**
604       Get X value.
605     */
606     const T& getX() const noexcept;
607 
608    /**
609       Get Y value.
610     */
611     const T& getY() const noexcept;
612 
613    /**
614       Get width.
615     */
616     const T& getWidth() const noexcept;
617 
618    /**
619       Get height.
620     */
621     const T& getHeight() const noexcept;
622 
623    /**
624       Get position.
625     */
626     const Point<T>& getPos() const noexcept;
627 
628    /**
629       Get size.
630     */
631     const Size<T>& getSize() const noexcept;
632 
633    /**
634       Set X value as @a x.
635     */
636     void setX(const T& x) noexcept;
637 
638    /**
639       Set Y value as @a y.
640     */
641     void setY(const T& y) noexcept;
642 
643    /**
644       Set X and Y values as @a x and @a y respectively.
645     */
646     void setPos(const T& x, const T& y) noexcept;
647 
648    /**
649       Set X and Y values according to @a pos.
650     */
651     void setPos(const Point<T>& pos) noexcept;
652 
653    /**
654       Move this rectangle by @a x and @a y values.
655     */
656     void moveBy(const T& x, const T& y) noexcept;
657 
658    /**
659       Move this rectangle by @a pos.
660     */
661     void moveBy(const Point<T>& pos) noexcept;
662 
663    /**
664       Set width.
665     */
666     void setWidth(const T& width) noexcept;
667 
668    /**
669       Set height.
670     */
671     void setHeight(const T& height) noexcept;
672 
673    /**
674       Set size using @a width and @a height.
675     */
676     void setSize(const T& width, const T& height) noexcept;
677 
678    /**
679       Set size.
680     */
681     void setSize(const Size<T>& size) noexcept;
682 
683    /**
684       Grow size by @a multiplier.
685     */
686     void growBy(double multiplier) noexcept;
687 
688    /**
689       Shrink size by @a divider.
690     */
691     void shrinkBy(double divider) noexcept;
692 
693    /**
694       Set rectangle using @a pos and @a size.
695     */
696     void setRectangle(const Point<T>& pos, const Size<T>& size) noexcept;
697 
698    /**
699       Set rectangle.
700     */
701     void setRectangle(const Rectangle<T>& rect) noexcept;
702 
703    /**
704       Check if this rectangle contains the point defined by @a X and @a Y.
705     */
706     bool contains(const T& x, const T& y) const noexcept;
707 
708    /**
709       Check if this rectangle contains the point @a pos.
710     */
711     bool contains(const Point<T>& pos) const noexcept;
712 
713    /**
714       Check if this rectangle contains X.
715     */
716     bool containsX(const T& x) const noexcept;
717 
718    /**
719       Check if this rectangle contains Y.
720     */
721     bool containsY(const T& y) const noexcept;
722 
723    /**
724       Draw this rectangle using the current OpenGL state.
725     */
726     void draw();
727 
728    /**
729       Draw lines (outline of this rectangle) using the current OpenGL state.
730     */
731     void drawOutline();
732 
733     Rectangle<T>& operator=(const Rectangle<T>& rect) noexcept;
734     Rectangle<T>& operator*=(double m) noexcept;
735     Rectangle<T>& operator/=(double d) noexcept;
736     bool operator==(const Rectangle<T>& size) const noexcept;
737     bool operator!=(const Rectangle<T>& size) const noexcept;
738 
739 private:
740     Point<T> fPos;
741     Size<T>  fSize;
742 
743     void _draw(const bool outline);
744 };
745 
746 // -----------------------------------------------------------------------
747 
748 END_NAMESPACE_DGL
749 
750 #endif // DGL_GEOMETRY_HPP_INCLUDED
751