1 #ifndef MATRIX_H
2 #define MATRIX_H
3
4 #include "point.h"
5
6 template<class T>
7 class Matrix
8 {
9
10 public:
11 typedef Point<unsigned> geometry;
12
13 protected:
14 /** Dimensions of the matrix. */
15 unsigned mX, mY;
16 /** The raw array. It is allocated once and afterwards only changed
17 WRT values. */
18 T * cell;
19 /** The distance between two lines. This enables sub-matrizes to be
20 created. */
21 unsigned offset;
22 /** Whether cell is our's. */
23 bool ownData;
24
25 public:
26 /** A constructor.*/
27 Matrix(unsigned mx, unsigned my);
28 Matrix(geometry geo);
29 Matrix(T * data, unsigned mx, unsigned my, unsigned offset = 0);
30 Matrix(const Matrix<T> & other,
31 unsigned sx, unsigned sy, unsigned mx, unsigned my);
32 /** The destructor. */
33 ~Matrix();
34
35 unsigned x() const
36 {return mX;}
37 unsigned y() const
38 {return mY;}
39
40 T & at(const Point<int> & pt) const
41 {return at(pt.x, pt.y);}
42 /** Get the value of the cell at (x, y). */
43 T & at(int x, int y) const
44 {return cell[x*(mY+offset) + y];}
45 /** Get the xth column. Enables expressions like myMatrix[x][y]. */
46 T * operator[](int x) const
47 {return cell + x*(mY+offset);}
48 /** Set the value at (x, y).*/
49 void set(int x, int y, const T & to)
50 {at(x, y) = to;}
51 /** Inserts a new value at (x, y) (necessary for LSC)*/
52 void insert(int x, int y, const T &to)
53 {set(x,y,to);}
54
55 void fill(const T & value)
56 {
57 for(unsigned x=0; x<mX; x++)
58 for(unsigned y=0; y<mY; y++)
59 set(x, y, value);
60 }
61
62 /** Copy the value at (x1, y1) to (x2, y2). */
63 void copy(int x1, int y1, int x2, int y2)
64 {set(x2, y2, at(x1, y1));};
65
66 /** Apply a function to each cell of a rectangular area of the matrix.
67 This can be done vertically or horizontally.
68 @param aFunction The function to apply.
69 @param xFirst In which direction to work. If set to true
70 The matrix will be iterated in x direction.
71 @param x1, y1, x2, y2 Limits of the region to apply
72 the function to. x2 and y2 are set to the right respective lower
73 border if they are smaller then x1 and y1.
74 @return A reference to the function object after the
75 last call. */
76 template<class F>
77 const F & apply(F & aFunction, bool colMajor = true,
78 unsigned x1 = 0, unsigned y1 = 0,
79 unsigned x2 = 0, unsigned y2 = 0)
80 {
81 x2 <= x1 ? (x2 = mX) : 0;
82 y2 <= y1 ? (y2 = mY) : 0;
83 unsigned x, y;
84 if (colMajor)
85 for(x=x1; x<x2; x++)
86 for(y=y1; y<y2; y++)
87 aFunction(at(x,y));
88 else
89 for(y=y1; y<y2; y++)
90 for(x=x1; x<x2; x++)
91 aFunction(at(x,y));
92
93 return aFunction;
94 }
95
96 /** Apply a function to each cell of a rectangular area of the matrix.
97 This can be done vertically or horizontally.
98 @param aFunction The function to apply.
99 @param xFirst In which direction to work. If set to true
100 The matrix will be iterated in x direction.
101 @param x1, y1, x2, y2 Limits of the region to apply
102 the function to. x2 and y2 are set to the right respective lower
103 border if they are smaller then x1 and y1.
104 @return A reference to the function object after the
105 last call. */
106 template<class F>
107 const F & scan(F & aConstFunction, bool xFirst = true,
108 unsigned x1 = 0, unsigned y1 = 0,
109 unsigned x2 = 0, unsigned y2 = 0) const
110 {
111 x2 <= x1 ? (x2 = mX) : 0;
112 y2 <= y1 ? (y2 = mY) : 0;
113 unsigned x, y;
114 if (xFirst)
115 for(x=x1; x<x2; x++)
116 for(y=y1; y<y2; y++)
117 aConstFunction(at(x,y));
118 else
119 for(y=y1; y<y2; y++)
120 for(x=x1; x<x2; x++)
121 aConstFunction(at(x,y));
122
123 return aConstFunction;
124 }
125
126 /** Create a sub-matrix. The resulting matrix operates on the same data
127 as the original one. */
128 Matrix<T> sub(unsigned x, unsigned y, unsigned w, unsigned h)
129 {
130 return Matrix<T>(&(at(x, y)), w, h, mY - h + offset);
131 }
132 };
133
134 template<class T>
135 Matrix<T>::Matrix(unsigned mx, unsigned my)
136 {
137 mX = mx;
138 mY = my;
139 offset = 0;
140 cell = new T[mX*mY];
141 ownData = true;
142 }
143
144 template<class T>
145 Matrix<T>::Matrix(geometry geo)
146 {
147 mX = geo.x;
148 mY = geo.y;
149 offset = 0;
150 cell = new T[mX*mY];
151 ownData = true;
152 }
153
154 template<class T>
155 Matrix<T>::Matrix(T * data, unsigned mx, unsigned my, unsigned offs)
156 {
157 mX = mx;
158 mY = my;
159 offset = offs;
160 cell = data;
161 ownData = false;
162 }
163
164 template<class T>
165 Matrix<T>::Matrix(const Matrix<T> & other,
166 unsigned sx, unsigned sy, unsigned mx, unsigned my)
167 {
168 cell = &(other.at(sx, sy));
169 mX = mx;
170 mY = my;
171 offset = other.mY - mY + other.offset;
172 ownData = false;
173 }
174
175 template<class T>
176 Matrix<T>::~Matrix()
177 {
178 if (!cell || !ownData) return;
179
180 delete[] cell;
181 }
182
183 #endif //MATRIX_H
184