Subversion Repositories gelsvn

Rev

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

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