1
////////////////////////////////////////////////////////////////////////////////////////////////
2
// 3d geometry classes - implements some peps 3d stuff
4
// g.j.hawkesford August 2003
5
////////////////////////////////////////////////////////////////////////////////////////////////
14
////////////////////////////////////////////////////////////////////////////////////////////////
16
////////////////////////////////////////////////////////////////////////////////////////////////
17
namespace geoff_geometry {
22
Matrix::Matrix(double m[16]) {
23
memcpy(e, m, sizeof(e));
27
Matrix::Matrix( Matrix& m)
33
const Matrix& Matrix::operator=( Matrix &m) {
34
for(int i = 0; i < 16; i++) e[i] = m.e[i];
36
m_mirrored = m.m_mirrored;
42
// homogenous matrix - set as unit matrix
43
for( int i = 0; i < 16; i ++ ) e[i] = 0;
44
e[0] = e[5] = e[10] = e[15] = 1;
49
void Matrix::Get(double* p) const
52
for( int i = 0; i < 16; i ++ ) p[i] = e[i];
54
void Matrix::Put(double* p)
57
for( int i = 0; i < 16; i ++ ) e[i] = p[i];
58
m_unit = false; // don't know
59
m_mirrored = -1; // don't know
62
void Matrix::Translate(double x, double y, double z)
71
void Matrix::Rotate(double angle, Vector3d *rotAxis) {
72
/// Rotation about rotAxis with angle
73
Rotate(sin(angle), cos(angle), rotAxis);
76
void Matrix::Rotate(double sinang, double cosang, Vector3d *rotAxis) {
77
/// Rotation about rotAxis with cp & dp
79
double oneminusc = 1.0 - cosang;
81
rotate.e[0] = rotAxis->getx() * rotAxis->getx() * oneminusc + cosang;
82
rotate.e[1] = rotAxis->getx() * rotAxis->gety() * oneminusc - rotAxis->getz() * sinang;
83
rotate.e[2] = rotAxis->getx() * rotAxis->getz() * oneminusc + rotAxis->gety() * sinang;
85
rotate.e[4] = rotAxis->getx() * rotAxis->gety() * oneminusc + rotAxis->getz() * sinang;
86
rotate.e[5] = rotAxis->gety() * rotAxis->gety() * oneminusc + cosang;
87
rotate.e[6] = rotAxis->gety() * rotAxis->getz() * oneminusc - rotAxis->getx() * sinang;
89
rotate.e[8] = rotAxis->getx() * rotAxis->getz() * oneminusc - rotAxis->gety() * sinang;
90
rotate.e[9] = rotAxis->gety() * rotAxis->getz() * oneminusc + rotAxis->getx() * sinang;
91
rotate.e[10] = rotAxis->getz() * rotAxis->getz() * oneminusc + cosang;
92
Multiply(rotate); // concatinate rotation with this matrix
94
m_mirrored = -1; // don't know
98
void Matrix::Rotate(double angle, int Axis)
99
{ // Rotation (Axis 1 = x , 2 = y , 3 = z
100
Rotate(sin(angle), cos(angle), Axis);
103
void Matrix::Rotate(double sinang, double cosang, int Axis)
104
{ // Rotation (Axis 1 = x , 2 = y , 3 = z
112
rotate.e[5] = rotate.e[10] = cosang;
113
rotate.e[6] = -sinang;
114
rotate.e[9] = sinang;
118
rotate.e[0] = rotate.e[10] = cosang;
119
rotate.e[2] = sinang;
120
rotate.e[8] = -sinang;
124
rotate.e[0] = rotate.e[5] = cosang;
125
rotate.e[1] = -sinang;
126
rotate.e[4] = sinang;
129
Multiply(rotate); // concatinate rotation with this matrix
131
m_mirrored = -1; // don't know
134
void Matrix::Scale(double scale)
137
Scale(scale, scale, scale);
140
void Matrix::Scale(double scalex, double scaley, double scalez)
151
m_mirrored = -1; // don't know
153
void Matrix::Multiply(Matrix& m)
155
// multiply this by give matrix - concatinate
159
for (i = 0; i < 16; i++)
161
l = i - (k = (i % 4));
162
ret.e[i] = m.e[l] * e[k] + m.e[l+1] * e[k+4] + m.e[l+2] * e[k+8] + m.e[l+3] * e[k+12];
167
void Matrix::Transform(double p0[3], double p1[3]) const
169
// transform p0 thro' this matrix
171
memcpy(p1, p0, 3 * sizeof(double));
173
p1[0] = p0[0] * e[0] + p0[1] * e[1] + p0[2] * e[2] + e[3];
174
p1[1] = p0[0] * e[4] + p0[1] * e[5] + p0[2] * e[6] + e[7];
175
p1[2] = p0[0] * e[8] + p0[1] * e[9] + p0[2] * e[10] + e[11];
178
void Matrix::Transform2d(double p0[2], double p1[2]) const
180
// transform p0 thro' this matrix (2d only)
182
memcpy(p1, p0, 2 * sizeof(double));
184
p1[0] = p0[0] * e[0] + p0[1] * e[1] + e[3];
185
p1[1] = p0[0] * e[4] + p0[1] * e[5] + e[7];
189
void Matrix::Transform(double p0[3]) const
194
memcpy(p0, p1, 3 * sizeof(double));
198
int Matrix::IsMirrored()
200
// returns true if matrix has a mirror
203
else if(m_mirrored == -1) {
205
m_mirrored = ((e[0] * (e[5] * e[10] - e[6] * e[9])
206
- e[1] * (e[4] * e[10] - e[6] * e[8])
207
+ e[2] * (e[4] * e[9] - e[5] * e[8])) < 0);
211
int Matrix::IsUnit() {
212
// returns true if unit matrix
213
for(int i = 0; i < 16; i++) {
214
if(i == 0 || i == 5 || i == 10 || i == 15) {
215
if(e[i] != 1) return m_unit = false;
218
if(e[i] != 0) return m_unit = false;
222
return m_unit = true;
225
void Matrix::GetTranslate(double& x, double& y, double& z) const
227
// return translation
232
void Matrix::GetScale(double& sx, double& sy, double& sz) const
239
sx = sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]);
240
sy = sqrt(e[4] * e[4] + e[5] * e[5] + e[6] * e[6]);
241
sz = sqrt(e[8] * e[8] + e[9] * e[9] + e[10] * e[10]);
244
bool Matrix::GetScale(double& sx) const
246
// return a uniform scale (false if differential)
252
GetScale(sx, sy, sz);
253
return (fabs(fabs(sx) - fabs(sy)) < 0.000001)?true : false;
255
void Matrix::GetRotation(double& ax, double& ay, double& az) const
257
// return the rotations
262
double a; /* cos(bx) */
263
double b; /* sin(bx) */
264
double c; /* cos(by) */
265
double d; /* sin(by) */
266
double ee; /* cos(bz) */
267
double f; /* sin(bz) */
269
GetScale(sx, sy, sz);
270
if(this->m_mirrored == -1) FAILURE(L"Don't know mirror - use IsMirrored method on object");
271
if(this->m_mirrored) sx = -sx;
273
// solve for d and decide case and solve for a, b, c, e and f
275
if((c = (1 - d) * (1 + d)) > 0.001)
290
d = ( d < 0 ) ? -1 : 1 ;
292
p = d * e[5] / sy - e[2] / sx;
293
q = d * e[6] / sy + e[1] / sx;
294
if((coef = sqrt( p * p + q * q )) > 0.001) {
302
/* dependent pairs */
310
// solve and return ax, ay and az
316
Matrix Matrix::Inverse()
318
// matrix inversion routine
320
// a is input matrix destroyed & replaced by inverse
321
// method used is gauss-jordan (ref ibm applications)
324
int i , j , k , nk , kk , ij , iz ;
325
int ki , ji , jp , jk , kj , jq , jr , ik;
327
int n = 4; // 4 x 4 matrix only
331
if(a.m_unit) return a; // unit matrix
333
// search for largest element
335
for ( k = 0 ; k < n ; k++ ) {
337
l [ k ] = m [ k ] = k ;
341
for ( j = k ; j < n ; j++ ) {
343
for ( i = k ; i < n ; i++ ) {
345
if ( fabs ( biga ) < fabs ( a.e[ ij ] ) ) {
359
for ( i = 0 ; i < n ; i++ ) {
363
a.e[ ki ] = a.e[ ji ] ;
368
// interchange columns
372
for ( j = 0 ; j < n ; j++ ) {
376
a.e[ jk ] = a.e[ ji ] ;
381
// divide columns by minus pivot (value of pivot element is contained in biga)
382
if ( fabs ( biga ) < 1.0e-10 )FAILURE(getMessage(L"Singular Matrix - Inversion failure",GEOMETRY_ERROR_MESSAGES, -1)); // singular matrix
384
for ( i = 0 ; i < n ; i++ ) {
387
a.e[ ik ] = - a.e[ ik ] /biga ;
392
for ( i = 0 ; i < n ; i++ ) {
397
for ( j = 0 ; j < n ; j++ ) {
399
if ( i != k && j != k ) {
401
a.e[ ij ] = hold * a.e[ kj ] + a.e[ ij ] ;
406
// divide row by pivot
408
for ( j = 0 ; j < n ; j++ ) {
410
if ( j != k ) a.e[ kj] = a.e[ kj ] /biga ;
413
// replace pivot by reciprocal
414
a.e[ kk ] = 1 / biga ;
417
// final row and column interchange
426
for ( j = 0 ; j < n ; j++ ) {
430
a.e[jk] = - a.e[ji] ;
439
for ( i = 1 ; i <= n ; i ++ ) {
443
a.e[ ki ] = - a.e[ ji ] ;
453
void Matrix::ToPeps(int id)
455
int set = PepsVdmMake(id, VDM_MATRIX_TYPE , VDM_LOCAL);
456
if(set < 0) FAILURE(L"Failed to create Matrix VDM");
457
struct kgm_header pepsm;
461
pepsm.off_dir = pepsm.origin_id = 0;
463
PepsVdmWriteTmx(set , &pepsm );
469
void Matrix::FromPeps(int id)
472
int set = PepsVdmOpen(id, VDM_MATRIX_TYPE , VDM_READ_ONLY | VDM_LOCAL);
473
if(set < 0) FAILURE(L"Failed to open Matrix VDM");
475
struct kgm_header pepsm;
476
PepsVdmReadTmx(set , &pepsm);
477
memcpy(e, pepsm.matrix, sizeof(pepsm.matrix));
479
for(int i = 0; i < 16; i++) {
480
// copy over matrix and check for unit matrix
481
if(i == 0 || i == 5 || i == 10 || i == 15) {
482
if((e[i] = pepsm.matrix[i]) != 1) m_unit = false;
485
if((e[i] = pepsm.matrix[i]) != 0) m_unit = false;
489
m_mirrored = IsMirrored();
494
Matrix UnitMatrix; // a global unit matrix
498
Vector2d::Vector2d(const Vector3d &v){
499
if(FEQZ(v.getz())) FAILURE(L"Converting Vector3d to Vector2d illegal");
504
bool Vector2d::operator==(const Vector2d &v)const {
505
return FEQ(dx, v.getx(), 1.0e-06) && FEQ(dy, v.gety(), 1.0e-06);
508
void Vector2d::Transform(const Matrix& m) {
510
if(m.m_unit == false) {
511
double dxt = dx * m.e[0] + dy * m.e[1];
512
double dyt = dx * m.e[4] + dy * m.e[5];
519
void Vector3d::Transform(const Matrix& m) {
521
if(m.m_unit == false) {
522
double dxt = dx * m.e[0] + dy * m.e[1] + dz * m.e[2];
523
double dyt = dx * m.e[4] + dy * m.e[5] + dz * m.e[6];
524
double dzt = dx * m.e[8] + dy * m.e[9] + dz * m.e[10];
532
void Vector3d::arbitrary_axes(Vector3d& x, Vector3d& y){
533
// arbitrary axis algorithm - acad method of generating an arbitrary but
534
// consistant set of axes from a single normal ( z )
535
// arbitrary x & y axes
537
if ( ( fabs ( this->getx() ) < 1.0/64.0 ) && (fabs(this->gety()) < 1.0/64.0))
538
x = Y_VECTOR ^ *this;
540
x = Z_VECTOR ^ *this;
545
int Vector3d::setCartesianAxes(Vector3d& b, Vector3d& c) {
547
// computes a RH triad of Axes (Cartesian) starting from a (normalised)
548
// if a & b are perpendicular then c = a ^ b
549
// if a & c are perpendicular then b = c ^ a
550
// if neither are perpendicular to a, then return arbitrary axes from a
552
// calling sequence for RH cartesian
556
if(a == NULL_VECTOR) FAILURE(L"SetAxes given a NULL Vector");
557
double epsilon = 1.0e-09;
558
bool bNull = (b == NULL_VECTOR);
559
bool cNull = (c == NULL_VECTOR);
560
bool abPerp = !bNull;
561
if(abPerp) abPerp = (fabs(a * b) < epsilon);
563
bool acPerp = !cNull;
564
if(acPerp) acPerp = (fabs(a * c) < epsilon);
576
arbitrary_axes(b, c);
b'\\ No newline at end of file'