-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeometry.cpp
114 lines (102 loc) · 3.06 KB
/
geometry.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <vector>
#include <cassert>
#include <cmath>
#include <iostream>
#include "geometry.h"
template <> template <> Vec3<int>::Vec3<>(const Vec3<float> &v) : x(int(v.x+.5)), y(int(v.y+.5)), z(int(v.z+.5)) {}
template <> template <> Vec3<float>::Vec3<>(const Vec3<int> &v) : x(v.x), y(v.y), z(v.z) {}
Matrix::Matrix(Vec3f v) : m(std::vector<std::vector<float> >(4, std::vector<float>(1, 1.f))), rows(4), cols(1) {
m[0][0] = v.x;
m[1][0] = v.y;
m[2][0] = v.z;
}
Matrix::Matrix(int r, int c) : m(std::vector<std::vector<float> >(r, std::vector<float>(c, 0.f))), rows(r), cols(c) { }
int Matrix::nrows() {
return rows;
}
int Matrix::ncols() {
return cols;
}
Matrix Matrix::identity(int dimensions) {
Matrix E(dimensions, dimensions);
for (int i=0; i<dimensions; i++) {
for (int j=0; j<dimensions; j++) {
E[i][j] = (i==j ? 1.f : 0.f);
}
}
return E;
}
std::vector<float>& Matrix::operator[](const int i) {
assert(i>=0 && i<rows);
return m[i];
}
Matrix Matrix::operator*(const Matrix& a) {
assert(cols == a.rows);
Matrix result(rows, a.cols);
for (int i=0; i<rows; i++) {
for (int j=0; j<a.cols; j++) {
result.m[i][j] = 0.f;
for (int k=0; k<cols; k++) {
result.m[i][j] += m[i][k]*a.m[k][j];
}
}
}
return result;
}
Matrix Matrix::transpose() {
Matrix result(cols, rows);
for(int i=0; i<rows; i++)
for(int j=0; j<cols; j++)
result[j][i] = m[i][j];
return result;
}
Matrix Matrix::inverse() {
assert(rows==cols);
// augmenting the square matrix with the identity matrix of the same dimensions a => [ai]
Matrix result(rows, cols*2);
for(int i=0; i<rows; i++)
for(int j=0; j<cols; j++)
result[i][j] = m[i][j];
for(int i=0; i<rows; i++)
result[i][i+cols] = 1;
// first pass
for (int i=0; i<rows-1; i++) {
// normalize the first row
for(int j=result.cols-1; j>=0; j--)
result[i][j] /= result[i][i];
for (int k=i+1; k<rows; k++) {
float coeff = result[k][i];
for (int j=0; j<result.cols; j++) {
result[k][j] -= result[i][j]*coeff;
}
}
}
// normalize the last row
for(int j=result.cols-1; j>=rows-1; j--)
result[rows-1][j] /= result[rows-1][rows-1];
// second pass
for (int i=rows-1; i>0; i--) {
for (int k=i-1; k>=0; k--) {
float coeff = result[k][i];
for (int j=0; j<result.cols; j++) {
result[k][j] -= result[i][j]*coeff;
}
}
}
// cut the identity matrix back
Matrix truncate(rows, cols);
for(int i=0; i<rows; i++)
for(int j=0; j<cols; j++)
truncate[i][j] = result[i][j+cols];
return truncate;
}
std::ostream& operator<<(std::ostream& s, Matrix& m) {
for (int i=0; i<m.nrows(); i++) {
for (int j=0; j<m.ncols(); j++) {
s << m[i][j];
if (j<m.ncols()-1) s << "\t";
}
s << "\n";
}
return s;
}