1 module prova.math.rect;
2 
3 import prova.math,
4        std.math;
5 
6 ///
7 enum Side { LEFT, RIGHT, TOP, BOTTOM }
8 
9 ///
10 struct Rect
11 {
12   ///
13   float left = 0;
14   ///
15   float top = 0;
16   ///
17   float width = 0;
18   ///
19   float height = 0;
20 
21   ///
22   this(float left, float top, float width, float height)
23   {
24     set(left, top, width, height);
25   }
26 
27   //// Sets the position and dimensions of the rect in a single statement
28   void set(float left, float top, float width, float height)
29   {
30     this.left = left;
31     this.top = top;
32     this.width = width;
33     this.height = height;
34   }
35 
36   ///
37   @property float right() const
38   {
39     return left + width;
40   }
41 
42   ///
43   @property void right(float value)
44   {
45     left = value - width;
46   }
47 
48   ///
49   @property float bottom() const
50   {
51     return top - height;
52   }
53 
54   ///
55   @property void bottom(float value)
56   {
57     top = value + height;
58   }
59 
60   ///
61   Vector2 getSize() const
62   {
63     return Vector2(width, height);
64   }
65 
66   ///
67   Vector2 getCenter() const
68   {
69     return Vector2(left + width / 2, top - height / 2);
70   }
71 
72   ///
73   Vector2 getTopLeft() const
74   {
75     return Vector2(left, top);
76   }
77 
78   ///
79   Vector2 getTopRight() const
80   {
81     return Vector2(right, top);
82   }
83 
84   ///
85   Vector2 getBottomLeft() const
86   {
87     return Vector2(left, bottom);
88   }
89 
90   ///
91   Vector2 getBottomRight() const
92   {
93     return Vector2(right, bottom);
94   }
95 
96   ///
97   Side getClosestSide(Rect rect) const
98   {
99     const Vector2 center = getCenter();
100     const Vector2 rectCenter = rect.getCenter();
101 
102     return getClosestSide(
103       (rectCenter.x - center.x) / (width + rect.width),
104       (rectCenter.y - center.y) / (height + rect.height)
105     );
106   }
107 
108   ///
109   Side getClosestSide(Vector2 position) const
110   {
111     const Vector2 center = getCenter();
112 
113     return getClosestSide(
114       (position.x - center.x) / width,
115       (position.y - center.y) / height
116     );
117   }
118 
119   private Side getClosestSide(float fractionX, float fractionY) const
120   {
121     if(abs(fractionX) > abs(fractionY)) {
122       if(fractionX > 0)
123         return Side.RIGHT;
124       if(fractionX < 0)
125         return Side.LEFT;
126     } else {
127       if(fractionY > 0)
128         return Side.TOP;
129       if(fractionY < 0)
130         return Side.BOTTOM;
131     }
132 
133     // default to the left side
134     return Side.LEFT;
135   }
136 }