Subversion Repositories gelsvn

Rev

Rev 2 | Rev 12 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 bj 1
#ifndef __CGLA_ARITHVEC_H__
2
#define __CGLA_ARITHVEC_H__
3
 
4
#include <iostream>
5
#include "CGLA.h"
6
 
7
 
8
namespace CGLA {
9
 
10
	/** The ArithVec class template represents a generic arithmetic
11
			vector.  The three parameters to the template are
12
 
13
			T - the scalar type (i.e. float, int, double etc.)
14
 
15
			V - the name of the vector type. This template is always (and
16
			only) used as ancestor of concrete types, and the name of the
17
			class _inheriting_ _from_ this class is used as the V argument.
18
 
19
			N - The final argument is the dimension N. For instance, N=3 for a
20
			3D vector.
21
 
22
			This class template contains all functions that are assumed to be
23
			the same for any arithmetic vector - regardless of dimension or
24
			the type of scalars used for coordinates.
25
 
26
			The template contains no virtual functions which is important
27
			since they add overhead.
28
	*/
29
 
30
	template <class T, class V, int N> 
31
	class ArithVec
32
	{
33
#define for_all_i(expr) for(int i=0;i<N;i++) {expr;}
34
 
35
	protected:
36
 
37
		/// The actual contents of the vector.
38
		T data[N];
39
 
40
	protected:
41
 
42
		//----------------------------------------------------------------------
43
		// Constructors
44
		//----------------------------------------------------------------------
45
 
46
		/// Construct 0 vector
47
		ArithVec() 
48
		{
49
		}
50
 
51
		/// Construct a vector where all coordinates are identical
52
		explicit ArithVec(T _a)
53
		{
54
			for_all_i(data[i] = _a);
55
		}
56
 
57
		/// Construct a 2D vector 
58
		ArithVec(T _a, T _b)
59
		{
60
			assert(N==2);
61
			data[0] = _a;
62
			data[1] = _b;
63
		}
64
 
65
		/// Construct a 3D vector
66
		ArithVec(T _a, T _b, T _c)
67
		{
68
			assert(N==3);
69
			data[0] = _a;
70
			data[1] = _b;
71
			data[2] = _c;
72
		}
73
 
74
		/// Construct a 4D vector
75
		ArithVec(T _a, T _b, T _c, T _d)
76
		{
77
			assert(N==4);
78
			data[0] = _a;
79
			data[1] = _b;
80
			data[2] = _c;
81
			data[3] = _d;
82
		}
83
 
84
 
85
	public:
86
 
87
		/// For convenience we define a more meaningful name for the scalar type
88
		typedef T ScalarType;
89
 
90
		/// A more meaningful name for vector type
91
		typedef V VectorType;
92
 
93
		/// Return dimension of vector
94
		static int get_dim() {return N;}
95
 
96
		/// Set all coordinates of a 2D vector.
97
		void set(T _a, T _b)
98
		{
99
			assert(N==2);
100
			data[0] = _a;
101
			data[1] = _b;
102
		}
103
 
104
		/// Set all coordinates of a 3D vector.
105
		void set(T _a, T _b, T _c)
106
		{
107
			assert(N==3);
108
			data[0] = _a;
109
			data[1] = _b;
110
			data[2] = _c;
111
		}
112
 
113
		/// Set all coordinates of a 4D vector.
114
		void set(T _a, T _b, T _c, T _d)
115
		{
116
			assert(N==4);
117
			data[0] = _a;
118
			data[1] = _b;
119
			data[2] = _c;
120
			data[3] = _d;
121
		}
122
 
123
		/// Const index operator
124
		const T& operator [] ( int i ) const
125
		{
126
			assert(i<N);
127
			return data[i];
128
		}
129
 
130
		/// Non-const index operator
131
		T& operator [] ( int i ) 
132
		{
133
			assert(i<N);
134
			return data[i];
135
		}
136
 
137
		/** Get a pointer to first element in data array.
138
				This function may be useful when interfacing with some other API 
139
				such as OpenGL (TM) */
140
		T* get() {return &data[0];}
141
 
142
		/** Get a const pointer to first element in data array.
143
				This function may be useful when interfacing with some other API 
144
				such as OpenGL (TM). */
145
		const T* get() const {return &data[0];}
146
 
147
		//----------------------------------------------------------------------
148
		// Comparison operators
149
		//----------------------------------------------------------------------
150
 
151
		/// Equality operator
152
		bool operator==(const V& v) const 
153
		{
154
			for_all_i(if (data[i] != v[i]) return false)
155
				return true;
156
		}
157
 
158
		/// Equality wrt scalar. True if all coords are equal to scalar
159
		bool operator==(T k) const 
160
		{ 
161
			for_all_i(if (data[i] != k) return false)
162
				return true;
163
		}
164
 
165
		/// Inequality operator
166
		bool operator!=(const V& v) const 
167
		{
168
			return !(*this==v);
169
		}
170
 
171
		/// Inequality wrt scalar. True if any coord not equal to scalar
172
		bool operator!=(T k) const 
173
		{ 
174
			return !(*this==k);
175
		}
176
 
177
 
178
		//----------------------------------------------------------------------
179
		// Comparison functions ... of geometric significance 
180
		//----------------------------------------------------------------------
181
 
182
		/** Compare all coordinates against other vector. ( < )
183
				Similar to testing whether we are on one side of three planes. */
184
		bool  all_l  (const V& v) const
185
		{
186
			for_all_i(if (data[i] >= v[i]) return false)
187
				return true;
188
		}
189
 
190
		/** Compare all coordinates against other vector. ( <= )
191
				Similar to testing whether we are on one side of three planes. */
192
		bool  all_le (const V& v) const
193
		{
194
			for_all_i(if (data[i] > v[i]) return false)
195
				return true;
196
		}
197
 
198
		/** Compare all coordinates against other vector. ( > )
199
				Similar to testing whether we are on one side of three planes. */
200
		bool  all_g  (const V& v) const
201
		{
202
			for_all_i(if (data[i] <= v[i]) return false)
203
				return true;
204
		}
205
 
206
		/** Compare all coordinates against other vector. ( >= )
207
				Similar to testing whether we are on one side of three planes. */
208
		bool  all_ge (const V& v) const
209
		{
210
			for_all_i(if (data[i] < v[i]) return false);
211
			return true;
212
		}
213
 
214
 
215
		//----------------------------------------------------------------------
216
		// Assignment operators
217
		//----------------------------------------------------------------------
218
 
219
		/// Assigment multiplication with scalar.
220
		const V& operator *=(T k) 
221
			{ 
222
				for_all_i(data[i] *= k); 
223
				return static_cast<const V&>(*this);
224
			}
225
 
226
		/// Assignment division with scalar.
227
		const V& operator /=(T k)
228
			{ 
229
				for_all_i(data[i] /= k); 
230
				return static_cast<const V&>(*this);
231
			}
232
 
233
		/// Assignment addition with scalar. Adds scalar to each coordinate.
234
		const V& operator +=(T k) 
235
			{
236
				for_all_i(data[i] += k); 
237
				return  static_cast<const V&>(*this);
238
			}
239
 
240
		/// Assignment subtraction with scalar. Subtracts scalar from each coord.
241
		const V& operator -=(T k) 
242
			{ 
243
				for_all_i(data[i] -= k); 
244
				return  static_cast<const V&>(*this);
245
			}
246
 
247
		/** Assignment multiplication with vector. 
248
				Multiply each coord independently. */
249
		const V& operator *=(const V& v) 
250
			{ 
251
				for_all_i(data[i] *= v[i]); 
252
				return  static_cast<const V&>(*this);
253
			}
254
 
255
		/// Assigment division with vector. Each coord divided independently.
256
		const V& operator /=(const V& v)
257
			{
258
				for_all_i(data[i] /= v[i]); 
259
				return  static_cast<const V&>(*this);
260
			}
261
 
262
		/// Assignmment addition with vector.
263
		const V& operator +=(const V& v) 
264
			{
265
				for_all_i(data[i] += v[i]); 
266
				return  static_cast<const V&>(*this);
267
			}
268
 
269
		/// Assignment subtraction with vector.
270
			const V& operator -=(const V& v) 
271
				{ 
272
					for_all_i(data[i] -= v[i]); 
273
					return  static_cast<const V&>(*this);
274
				}
275
 
276
 
277
		//----------------------------------------------------------------------
278
		// Unary operators on vectors
279
		//----------------------------------------------------------------------
280
 
281
		/// Negate vector.
282
		const V operator - () const
283
		{
284
			V v_new;
285
			for_all_i(v_new[i] = - data[i]);
286
			return v_new;
287
		}
288
 
289
		//----------------------------------------------------------------------
290
		// Binary operators on vectors
291
		//----------------------------------------------------------------------
292
 
293
		/** Multiply vector with vector. Each coord multiplied independently
294
				Do not confuse this operation with dot product. */
295
		const V operator * (const V& v1) const
296
		{
297
			V v_new;
298
			for_all_i(v_new[i] = data[i] * v1[i]);
299
			return v_new;
300
		}
301
 
302
		/// Add two vectors
303
		const V operator + (const V& v1) const
304
		{
305
			V v_new;
306
			for_all_i(v_new[i] = data[i] + v1[i]);
307
			return v_new;
308
		}
309
 
310
		/// Subtract two vectors. 
311
		const V operator - (const V& v1) const
312
		{
313
			V v_new;
314
			for_all_i(v_new[i] = data[i] - v1[i]);
315
			return v_new;
316
		}
317
 
318
		/// Divide two vectors. Each coord separately
319
		const V operator / (const V& v1) const
320
		{
321
			V v_new;
322
			for_all_i(v_new[i] = data[i] / v1[i]);
323
			return v_new;
324
		}
325
 
326
		//----------------------------------------------------------------------
327
		// Binary operators on vector and scalar
328
		//----------------------------------------------------------------------
329
 
330
		/// Multiply scalar onto vector.
331
		const V operator * (T k) const
332
		{
333
			V v_new;
334
			for_all_i(v_new[i] = data[i] * k);
335
			return v_new;
336
		}
337
 
338
 
339
		/// Divide vector by scalar.
340
		const V operator / (T k) const
341
		{
342
			V v_new;
343
			for_all_i(v_new[i] = data[i] / k);
344
			return v_new;      
345
		}
346
 
347
 
348
		/// Return the smallest coordinate of the vector
349
		const T min_coord() const 
350
		{
351
			T t = data[0];
352
			for_all_i(t = s_min(t, data[i]));
353
			return t;
354
		}
355
 
356
		/// Return the largest coordinate of the vector
357
		const T max_coord() const
358
		{
359
			T t = data[0];
360
			for_all_i(t = s_max(t, data[i]));
361
			return t;
362
		}
363
 
364
#undef for_all_i  
365
	};
366
 
367
	template <class T, class V, int N> 
368
	inline std::ostream& operator<<(std::ostream&os, const ArithVec<T,V,N>& v)
369
	{
370
		os << "[ ";
371
		for(int i=0;i<N;i++) os << v[i] << " ";
372
		os << "]";
373
		return os;
374
	}
375
 
376
	/// Get from operator for ArithVec descendants. 
377
	template <class T,class V, int N>
378
	inline std::istream& operator>>(std::istream&is, ArithVec<T,V,N>& v)
379
	{
380
		for(int i=0;i<N;i++) is>>v[i];
381
		return is;
382
	}
383
 
384
 
385
	/** Dot product for two vectors. The `*' operator is 
386
			reserved for coordinatewise	multiplication of vectors. */
387
	template <class T,class V, int N>
388
	inline T dot(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
389
	{
390
		T x = 0;
391
		for(int i=0;i<N;i++) x += v0[i]*v1[i];
392
		return x;
393
	}
394
 
395
	/** Compute the sqr length by taking dot product of vector with itself. */
396
	template <class T,class V, int N>
397
	inline T sqr_length(const ArithVec<T,V,N>& v)
398
	{
399
		return dot(v,v);
400
	}
401
 
402
	/** Multiply double onto vector. This operator handles the case 
403
			where the vector is on the righ side of the `*'.
404
 
405
			\note It seems to be optimal to put the binary operators inside the
406
			ArithVec class template, but the operator functions whose 
407
			left operand is _not_ a vector cannot be inside, hence they
408
			are here.
409
			We need three operators for scalar * vector although they are
410
			identical, because, if we use a separate template argument for
411
			the left operand, it will match any type. If we use just T as 
412
			type for the left operand hoping that other built-in types will
413
			be automatically converted, we will be disappointed. It seems that 
414
			a float * ArithVec<float,Vec3f,3> function is not found if the
415
			left operand is really a double.
416
	*/
417
 
418
	template<class T, class V, int N>
419
	inline const V operator * (double k, const ArithVec<T,V,N>& v) 
420
	{
421
		return v * k;
422
	}
423
 
424
	/** Multiply float onto vector. See the note in the documentation
425
			regarding multiplication of a double onto a vector. */
426
	template<class T, class V, int N>
427
	inline const V operator * (float k, const ArithVec<T,V,N>& v) 
428
	{
429
		return v * k;
430
	}
431
 
432
	/** Multiply int onto vector. See the note in the documentation
433
			regarding multiplication of a double onto a vector. */
434
	template<class T, class V, int N>
435
	inline const V operator * (int k, const ArithVec<T,V,N>& v) 
436
	{
437
		return v * k;
438
	}
439
 
440
	/** Returns the vector containing for each coordinate the smallest
441
			value from two vectors. */
442
	template <class T,class V, int N>
443
	inline V v_min(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
444
	{
445
		V v;
446
		for(int i=0;i<N;i++)
447
		v[i] = s_min(v0[i],v1[i]);
448
		return v;
449
	}
450
 
451
	/** Returns the vector containing for each coordinate the largest 
452
			value from two vectors. */
453
	template <class T,class V, int N>
454
	inline V v_max(const ArithVec<T,V,N>& v0, const ArithVec<T,V,N>& v1)
455
	{
456
		V v;
457
		for(int i=0;i<N;i++) 
458
		v[i] = s_max(v0[i],v1[i]);
459
		return v;
460
	}
461
 
462
 
463
}
464
 
465
#endif