Subversion Repositories gelsvn

Rev

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