1 module polyplex.math.rectangle;
2 import polyplex.math;
3 import std.traits;
4 
5 /// Base template for all AABB-types.
6 /// Params:
7 /// type = all values get stored as this type
8 struct RectangleT(T) if (isNumeric!T) {
9 public:
10 	union {
11 		struct {
12 			/// X coordinate of the top-left corner of the rectangle
13 			T X = 0;
14 
15 			/// Y coordinate of the top-left corner of the rectangle
16 			T Y = 0;
17 
18 			/// The width of the rectangle
19 			T Width = 0;
20 
21 			/// The height of the rectangle
22 			T Height = 0;
23 			
24 		}
25 
26 		/// Rectangle represented as an array, useful for passing data to the graphics API
27 		T[4] data;
28 	}
29 
30 	/// Constructor
31 	this(W, H)(W width, H height) if (isNumeric!W && isNumeric!H) {
32 		this.Width = cast(T)width;
33 		this.Height = cast(T)height;
34 	}
35 
36 	/// Constructor
37 	this(X, Y, W, H)(X x, Y y, W width, H height) if (isNumeric!X && isNumeric!Y && isNumeric!W && isNumeric!H) {
38 		this.X = cast(T)x;
39 		this.Y = cast(T)y;
40 		this.Width = cast(T)width;
41 		this.Height = cast(T)height;
42 	}
43 
44 	@trusted RectangleT!T opBinary(string op, T)(T other) if (isNumeric!(T)) {
45 		import std.format;
46 		mixin(q{
47 			return Rectangle(
48 				X %1$s cast(T)other, 
49 				Y %1$s cast(T)other, 
50 				Width %1$s cast(T)other, 
51 				Height %1$s cast(T)other);
52 		}.format(op));
53 	}
54 
55 	@trusted RectangleT!T opBinary(string op, T)(T other) if (IsRectangleT!T) {
56 		import std.format;
57 		mixin(q{
58 			return Rectangle(
59 				X %1$s cast(T)other.X, 
60 				Y %1$s cast(T)other.Y, 
61 				Width %1$s cast(T)other.Width, 
62 				Height %1$s cast(T)other.Height);
63 		}.format(op));
64 	}
65 
66 	/**
67 		Gets the X coordinate of the left side of the rectangle
68 	*/
69 	T Left() { return this.X; }
70 
71 	/**
72 		Gets the X coordinate of the right side of the rectangle
73 	*/
74 	T Right() { return this.X + this.Width; }
75 
76 	/**
77 		Gets the Y coordinate of the top of the rectangle
78 	*/
79 	T Top() { return this.Y; }
80 
81 	/**
82 		Gets the Y coordinate of the bottom of the rectangle
83 	*/
84 	T Bottom() { return this.Y + this.Height; }
85 
86 	/**
87 		Gets the center of the rectangle (as floats)
88 	*/
89 	Vector2 Center() { return Vector2(this.X + (this.Width/2), this.Y + (this.Height/2)); }
90 
91 	/**
92 		Gets wether this rectangle intersects another
93 	*/
94 	bool Intersects(T)(T other) if (IsRectangleT!T) {
95 		bool v = (other.Left >= this.Right || other.Right <= this.Left || other.Top >= this.Bottom || other.Bottom <= this.Top);
96 		return !v;
97 	}
98 
99 	/**
100 		Gets wether a 2D vector is intersecting this rectangle
101 	*/
102 	bool Intersects(U)(U other) if (IsVector2T!U) {
103 		bool v = (other.X >= this.Right || other.X < this.Left || other.Y >= this.Bottom || other.Y < this.Top);
104 		return !v;
105 	}
106 
107 	/**
108 		Returns a displaced version of this rectangle
109 	*/
110 	RectangleT!T Displace(T x, T y) {
111 		return RectangleT!T(this.X+x, this.Y+y, this.Width, this.Height);
112 	}
113 
114 	/**
115 		Returns an expanded version of this rectangle
116 	*/
117 	RectangleT!T Expand(T)(T x, T y) {
118 		return RectangleT!T(this.X-x, this.Y-y, this.Width+(x*2), this.Height+(y*2));
119 	}
120 }
121 
122 // Checks wether a type is a rectangle type
123 enum IsRectangleT(T) = is(T : RectangleT!U, U...);
124 
125 alias Rectangle = RectangleT!float;
126 alias Rectanglei = RectangleT!int;