initial commit, lordsawar source, slightly modified
[lordsawar] / src / vector.h
1 //  Copyright (C) 2009 Ben Asselstine
2 //  This program is free software; you can redistribute it and/or modify
3 //  it under the terms of the GNU General Public License as published by
4 //  the Free Software Foundation; either version 3 of the License, or
5 //  (at your option) any later version.
6 //
7 //  This program is distributed in the hope that it will be useful,
8 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
9 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 //  GNU Library General Public License for more details.
11 //
12 //  You should have received a copy of the GNU General Public License
13 //  along with this program; if not, write to the Free Software
14 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
15 //  02110-1301, USA.
16
17 #ifndef VECTOR_H
18 #define VECTOR_H
19
20 #include <cmath>
21 #include <stdlib.h>
22
23 //! A simple 2d point structure.
24 /**
25  * Implements a lot of overloaded operators to ease calculations.
26  * x is the axis in the left/right direction.
27  * y is the axis in the up/down direction.
28  */
29 extern int max_vector_width;
30 template <typename T>
31 struct Vector
32 {
33   T x, y;
34
35   static void setMaximumWidth(int width) {max_vector_width = width;};
36   Vector() { }
37   template <typename OT>
38   Vector(OT other_point_type): x(other_point_type.x), y(other_point_type.y)  { }
39   Vector(T px, T py): x(px), y(py) { }
40
41   // conversion from another compatible vector type
42   template <typename OT>
43   Vector(const Vector<OT> &v)
44     : x(v.x), y(v.y)
45   {
46   }
47
48   template <typename OT>
49   Vector<T> operator +=(Vector<OT> other)
50   {
51     x += other.x;
52     y += other.y;
53     return *this;
54   }
55
56   template <typename OT>
57   Vector<T> operator -=(Vector<OT> other)
58   {
59     x -= other.x;
60     y -= other.y;
61     return *this;
62   }
63
64   template <typename OT>
65   Vector<T> operator *=(OT number)
66   {
67     x *= number;
68     y *= number;
69     return *this;
70   }
71
72   template <typename OT>
73   Vector<T> operator /=(OT number)
74   {
75     x /= number;
76     y /= number;
77     return *this;
78   }
79
80   Vector<T> operator -()
81   {
82     return Vector<T>(-x, -y);
83   }
84
85     //size_t operator()(const Vector<T>&v) const
86       //{
87         //size_t size = v.x * max_vector_width + v.y;
88         //return size;
89       //};
90    T toIndex() {return y*max_vector_width+x; }
91 };
92
93 template <typename T>
94 inline Vector<T> operator +(Vector<T> lhs, Vector<T> rhs)
95 {
96   return Vector<T>(lhs.x + rhs.x, lhs.y + rhs.y);
97 }
98
99 template <typename T>
100 inline Vector<T> operator -(Vector<T> lhs, Vector<T> rhs)
101 {
102   return Vector<T>(lhs.x - rhs.x, lhs.y - rhs.y);
103 }
104
105 template <typename T, typename OT>
106 inline Vector<T> operator *(Vector<T> v, OT number)
107 {
108   return Vector<T>(v.x * number, v.y * number);
109 }
110
111 template <typename T, typename OT>
112 inline Vector<T> operator *(OT number, Vector<T> v)
113 {
114   return Vector<T>(v.x * number, v.y * number);
115 }
116
117 template <typename T, typename OT>
118 inline Vector<T> operator %(Vector<T> v, OT number)
119 {
120   return Vector<T>(v.x % number, v.y % number);
121 }
122
123 template <typename T, typename OT>
124 inline Vector<T> operator /(Vector<T> v, OT number)
125 {
126   return Vector<T>(v.x / number, v.y / number);
127 }
128
129 template <typename T>
130 inline bool operator !=(Vector<T> lhs, Vector<T> rhs)
131 {
132   return !(lhs == rhs);
133 }
134
135 template <typename T>
136 inline bool operator ==(Vector<T> lhs, Vector<T> rhs)
137 {
138   return lhs.x == rhs.x && lhs.y == rhs.y;
139 }  
140
141 template <typename T>
142 inline bool operator <(Vector<T> lhs, Vector<T> rhs)
143 {
144   T l = lhs.y * max_vector_width + lhs.x;
145   T r = rhs.y * max_vector_width + rhs.x;
146   return r < l;
147 }
148
149 template <>
150 inline bool operator ==<double>(Vector<double> lhs, Vector<double> rhs)
151 {
152   return std::abs(lhs.x - rhs.x) < 0.001 && std::abs(lhs.y - rhs.y) < 0.001;
153 }  
154
155 template <>
156 inline bool operator ==<float>(Vector<float> lhs, Vector<float> rhs)
157 {
158   return std::abs(lhs.x - rhs.x) < 0.001 && std::abs(lhs.y - rhs.y) < 0.001;
159 }  
160
161 // utilities
162
163 template <typename T>
164 inline Vector<T> make_vector(T x, T y)
165 {
166   return Vector<T>(x, y);
167 }
168
169 // distance
170 template <typename T>
171 inline T dist(Vector<T> v1, Vector<T> v2)
172 {
173   return std::sqrt((v2.x - v1.x) * (v2.x - v1.x)
174                    + (v2.y - v1.y) * (v2.y - v1.y));
175 }
176
177 // specialization to make int case work smoother
178 template <>
179 inline int dist(Vector<int> v1, Vector<int> v2)
180 {
181   return static_cast<int>(std::sqrt(float((v2.x - v1.x) * (v2.x - v1.x)
182                                           + (v2.y - v1.y) * (v2.y - v1.y))));
183 }
184
185 // length
186 template <typename T>
187 inline T length(Vector<T> v)
188 {
189   return static_cast<T>(std::sqrt(v.x * v.x + v.y * v.y));
190 }
191
192 // clipping
193 template <typename T>
194 inline Vector<T> clip(Vector<T> lower, Vector<T> val, Vector<T> upper)
195 {
196   Vector<T> tmp;
197   
198   if (val.x > upper.x)
199     tmp.x = upper.x;
200   else if (val.x < lower.x)
201     tmp.x = lower.x;
202   else
203     tmp.x = val.x;
204
205   if (val.y > upper.y)
206     tmp.y = upper.y;
207   else if (val.y < lower.y)
208     tmp.y = lower.y;
209   else
210     tmp.y = val.y;
211
212   return tmp;
213 }
214
215 // rounding
216 template <typename T>
217 inline Vector<T> round(Vector<T> v)
218 {
219   return Vector<T>(round(v.x), round(v.y));
220 }
221
222
223 // type cast template, e.g. vector_cast<int>(some_float_vector)
224 template <typename Dest, typename Src>
225 inline Vector<Dest> vector_cast(Vector<Src> v)
226 {
227   return Vector<Dest>(static_cast<Dest>(v.x), static_cast<Dest>(v.y));
228 }
229
230
231 #endif