15
15
#include "nr-matrix.h"
20
* Multiply two NRMatrices together, storing the result in d.
23
nr_matrix_multiply(NRMatrix *d, NRMatrix const *m0, NRMatrix const *m1)
27
NR::Coord d0 = m0->c[0] * m1->c[0] + m0->c[1] * m1->c[2];
28
NR::Coord d1 = m0->c[0] * m1->c[1] + m0->c[1] * m1->c[3];
29
NR::Coord d2 = m0->c[2] * m1->c[0] + m0->c[3] * m1->c[2];
30
NR::Coord d3 = m0->c[2] * m1->c[1] + m0->c[3] * m1->c[3];
31
NR::Coord d4 = m0->c[4] * m1->c[0] + m0->c[5] * m1->c[2] + m1->c[4];
32
NR::Coord d5 = m0->c[4] * m1->c[1] + m0->c[5] * m1->c[3] + m1->c[5];
34
NR::Coord *dest = d->c;
48
nr_matrix_set_identity(d);
59
* Store the inverted value of Matrix m in d
62
nr_matrix_invert(NRMatrix *d, NRMatrix const *m)
65
NR::Coord const det = m->c[0] * m->c[3] - m->c[1] * m->c[2];
66
if (!NR_DF_TEST_CLOSE(det, 0.0, NR_EPSILON)) {
68
NR::Coord const idet = 1.0 / det;
69
NR::Coord *dest = d->c;
71
/* Cache m->c[0] and m->c[4] in case d == m. */
72
NR::Coord const m_c0(m->c[0]);
73
NR::Coord const m_c4(m->c[4]);
75
/*0*/ *dest++ = m->c[3] * idet;
76
/*1*/ *dest++ = -m->c[1] * idet;
77
/*2*/ *dest++ = -m->c[2] * idet;
78
/*3*/ *dest++ = m_c0 * idet;
79
/*4*/ *dest++ = -m_c4 * d->c[0] - m->c[5] * d->c[2];
80
/*5*/ *dest = -m_c4 * d->c[1] - m->c[5] * d->c[3];
83
nr_matrix_set_identity(d);
86
nr_matrix_set_identity(d);
97
* Set this matrix to a translation of x and y
100
nr_matrix_set_translate(NRMatrix *m, NR::Coord const x, NR::Coord const y)
102
NR::Coord *dest = m->c;
119
* Set this matrix to a scaling transform in sx and sy
122
nr_matrix_set_scale(NRMatrix *m, NR::Coord const sx, NR::Coord const sy)
124
NR::Coord *dest = m->c;
141
* Set this matrix to a rotating transform of angle 'theta' radians
144
nr_matrix_set_rotate(NRMatrix *m, NR::Coord const theta)
146
NR::Coord const s = sin(theta);
147
NR::Coord const c = cos(theta);
149
NR::Coord *dest = m->c;
16
#include "nr-matrix-fns.h"
179
* Constructor. Assign to nr if not null, else identity
181
Matrix::Matrix(NRMatrix const *nr)
195
30
* Multiply two matrices together
197
32
Matrix operator*(Matrix const &m0, Matrix const &m1)
216
* Multiply a matrix by another
218
Matrix &Matrix::operator*=(Matrix const &o)
229
* Multiply by a scaling matrix
231
Matrix &Matrix::operator*=(scale const &other)
233
/* This loop is massive overkill. Let's unroll.
234
* o _c[] goes from 0..5
235
* o other[] alternates between 0 and 1
238
* for (unsigned i = 0; i < 3; ++i) {
239
* for (unsigned j = 0; j < 2; ++j) {
240
* this->_c[i * 2 + j] *= other[j];
245
NR::Coord const xscale = other[0];
246
NR::Coord const yscale = other[1];
247
NR::Coord *dest = _c;
249
/*i=0 j=0*/ *dest++ *= xscale;
250
/*i=0 j=1*/ *dest++ *= yscale;
251
/*i=1 j=0*/ *dest++ *= xscale;
252
/*i=1 j=1*/ *dest++ *= yscale;
253
/*i=2 j=0*/ *dest++ *= xscale;
254
/*i=2 j=1*/ *dest *= yscale;
264
51
* Return the inverse of this matrix. If an inverse is not defined,
265
52
* then return the identity matrix.
401
* Assign a matrix to a given coordinate array
403
Matrix &Matrix::assign(Coord const *array)
405
assert(array != NULL);
407
Coord const *src = array;
410
*dest++ = *src++; //0
411
*dest++ = *src++; //1
412
*dest++ = *src++; //2
413
*dest++ = *src++; //3
414
*dest++ = *src++; //4
425
* Copy this matrix's value to a NRMatrix
427
NRMatrix *Matrix::copyto(NRMatrix *nrm) const {
431
Coord const *src = _c;
432
Coord *dest = nrm->c;
434
*dest++ = *src++; //0
435
*dest++ = *src++; //1
436
*dest++ = *src++; //2
437
*dest++ = *src++; //3
438
*dest++ = *src++; //4
448
* Copy this matrix's values to an array
450
NR::Coord *Matrix::copyto(NR::Coord *array) const {
452
assert(array != NULL);
454
Coord const *src = _c;
457
*dest++ = *src++; //0
458
*dest++ = *src++; //1
459
*dest++ = *src++; //2
460
*dest++ = *src++; //3
461
*dest++ = *src++; //4
474
double expansion(Matrix const &m) {
475
return sqrt(fabs(m.det()));
485
double Matrix::expansion() const {
486
return sqrt(fabs(det()));
496
double Matrix::expansionX() const {
497
return sqrt(_c[0] * _c[0] + _c[1] * _c[1]);
507
double Matrix::expansionY() const {
508
return sqrt(_c[2] * _c[2] + _c[3] * _c[3]);
518
190
bool Matrix::is_translation(Coord const eps) const {
222
* test whether the matrix is the identity matrix (true). (2geom's Matrix::isIdentity() does the same)
552
224
bool Matrix::test_identity() const {
553
return NR_MATRIX_DF_TEST_CLOSE(this, &NR_MATRIX_IDENTITY, NR_EPSILON);
225
return matrix_equalp(*this, NR_MATRIX_IDENTITY, NR_EPSILON);
233
* calculates the descriminant of the matrix. (Geom::Coord Matrix::descrim() does the same)
235
double expansion(Matrix const &m) {
236
return sqrt(fabs(m.det()));
563
246
bool transform_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon) {
564
return NR_MATRIX_DF_TEST_TRANSFORM_CLOSE(&m0, &m1, epsilon);
248
NR_DF_TEST_CLOSE(m0[0], m1[0], epsilon) &&
249
NR_DF_TEST_CLOSE(m0[1], m1[1], epsilon) &&
250
NR_DF_TEST_CLOSE(m0[2], m1[2], epsilon) &&
251
NR_DF_TEST_CLOSE(m0[3], m1[3], epsilon);
574
261
bool translate_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon) {
575
return NR_MATRIX_DF_TEST_TRANSLATE_CLOSE(&m0, &m1, epsilon);
262
return NR_DF_TEST_CLOSE(m0[4], m1[4], epsilon) && NR_DF_TEST_CLOSE(m0[5], m1[5], epsilon);
585
bool matrix_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon)
587
return ( NR_MATRIX_DF_TEST_TRANSFORM_CLOSE(&m0, &m1, epsilon) &&
588
NR_MATRIX_DF_TEST_TRANSLATE_CLOSE(&m0, &m1, epsilon) );
596
* A home-made assertion. Stop if the two matrixes are not 'close' to
599
void assert_close(Matrix const &a, Matrix const &b)
601
if (!matrix_equalp(a, b, 1e-3)) {
603
"a = | %g %g |,\tb = | %g %g |\n"
604
" | %g %g | \t | %g %g |\n"
605
" | %g %g | \t | %g %g |\n",
606
a[0], a[1], b[0], b[1],
607
a[2], a[3], b[2], b[3],
608
a[4], a[5], b[4], b[5]);
272
bool matrix_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon) {
273
return transform_equalp(m0, m1, epsilon) && translate_equalp(m0, m1, epsilon);