~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/libnr/nr-matrix.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Ted Gould, Kees Cook
  • Date: 2009-06-24 14:00:43 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20090624140043-07stp20mry48hqup
Tags: 0.47~pre0-0ubuntu1
* New upstream release

[ Ted Gould ]
* debian/control: Adding libgsl0 and removing version specifics on boost

[ Kees Cook ]
* debian/watch: updated to run uupdate and mangle pre-release versions.
* Dropped patches that have been taken upstream:
  - 01_mips
  - 02-poppler-0.8.3
  - 03-chinese-inkscape
  - 05_fix_latex_patch
  - 06_gcc-4.4
  - 07_cdr2svg
  - 08_skip-bad-utf-on-pdf-import
  - 09_gtk-clist
  - 10_belarussian
  - 11_libpng
  - 12_desktop
  - 13_slider
  - 100_svg_import_improvements
  - 102_sp_pattern_painter_free
  - 103_bitmap_type_print

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
 
14
14
#include <cstdlib>
15
15
#include "nr-matrix.h"
16
 
 
17
 
 
18
 
 
19
 
/**
20
 
 *  Multiply two NRMatrices together, storing the result in d.
21
 
 */
22
 
NRMatrix *
23
 
nr_matrix_multiply(NRMatrix *d, NRMatrix const *m0, NRMatrix const *m1)
24
 
{
25
 
    if (m0) {
26
 
        if (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];
33
 
 
34
 
            NR::Coord *dest = d->c;
35
 
            *dest++ = d0;
36
 
            *dest++ = d1;
37
 
            *dest++ = d2;
38
 
            *dest++ = d3;
39
 
            *dest++ = d4;
40
 
            *dest   = d5;
41
 
        } else {
42
 
            *d = *m0;
43
 
        }
44
 
    } else {
45
 
        if (m1) {
46
 
            *d = *m1;
47
 
        } else {
48
 
            nr_matrix_set_identity(d);
49
 
        }
50
 
    }
51
 
 
52
 
    return d;
53
 
}
54
 
 
55
 
 
56
 
 
57
 
 
58
 
/**
59
 
 *  Store the inverted value of Matrix m in d
60
 
 */
61
 
NRMatrix *
62
 
nr_matrix_invert(NRMatrix *d, NRMatrix const *m)
63
 
{
64
 
    if (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)) {
67
 
 
68
 
            NR::Coord const idet = 1.0 / det;
69
 
            NR::Coord *dest = d->c;
70
 
 
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]);
74
 
 
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];
81
 
 
82
 
        } else {
83
 
            nr_matrix_set_identity(d);
84
 
        }
85
 
    } else {
86
 
        nr_matrix_set_identity(d);
87
 
    }
88
 
 
89
 
    return d;
90
 
}
91
 
 
92
 
 
93
 
 
94
 
 
95
 
 
96
 
/**
97
 
 *  Set this matrix to a translation of x and y
98
 
 */
99
 
NRMatrix *
100
 
nr_matrix_set_translate(NRMatrix *m, NR::Coord const x, NR::Coord const y)
101
 
{
102
 
    NR::Coord *dest = m->c;
103
 
 
104
 
    *dest++ = 1.0;   //0
105
 
    *dest++ = 0.0;   //1
106
 
    *dest++ = 0.0;   //2
107
 
    *dest++ = 1.0;   //3
108
 
    *dest++ =   x;   //4
109
 
    *dest   =   y;   //5
110
 
 
111
 
    return m;
112
 
}
113
 
 
114
 
 
115
 
 
116
 
 
117
 
 
118
 
/**
119
 
 *  Set this matrix to a scaling transform in sx and sy
120
 
 */
121
 
NRMatrix *
122
 
nr_matrix_set_scale(NRMatrix *m, NR::Coord const sx, NR::Coord const sy)
123
 
{
124
 
    NR::Coord *dest = m->c;
125
 
 
126
 
    *dest++ =  sx;   //0
127
 
    *dest++ = 0.0;   //1
128
 
    *dest++ = 0.0;   //2
129
 
    *dest++ =  sy;   //3
130
 
    *dest++ = 0.0;   //4
131
 
    *dest   = 0.0;   //5
132
 
 
133
 
    return m;
134
 
}
135
 
 
136
 
 
137
 
 
138
 
 
139
 
 
140
 
/**
141
 
 *  Set this matrix to a rotating transform of angle 'theta' radians
142
 
 */
143
 
NRMatrix *
144
 
nr_matrix_set_rotate(NRMatrix *m, NR::Coord const theta)
145
 
{
146
 
    NR::Coord const s = sin(theta);
147
 
    NR::Coord const c = cos(theta);
148
 
 
149
 
    NR::Coord *dest = m->c;
150
 
 
151
 
    *dest++ =   c;   //0
152
 
    *dest++ =   s;   //1
153
 
    *dest++ =  -s;   //2
154
 
    *dest++ =   c;   //3
155
 
    *dest++ = 0.0;   //4
156
 
    *dest   = 0.0;   //5
157
 
 
158
 
    return m;
159
 
}
160
 
 
161
 
 
162
 
 
163
 
 
164
 
 
165
 
 
 
16
#include "nr-matrix-fns.h"
166
17
 
167
18
 
168
19
 
176
27
 
177
28
 
178
29
/**
179
 
 *  Constructor.  Assign to nr if not null, else identity
180
 
 */
181
 
Matrix::Matrix(NRMatrix const *nr)
182
 
{
183
 
    if (nr) {
184
 
        assign(nr->c);
185
 
    } else {
186
 
        set_identity();
187
 
    }
188
 
}
189
 
 
190
 
 
191
 
 
192
 
 
193
 
 
194
 
/**
195
30
 *  Multiply two matrices together
196
31
 */
197
32
Matrix operator*(Matrix const &m0, Matrix const &m1)
213
48
 
214
49
 
215
50
/**
216
 
 *  Multiply a matrix by another
217
 
 */
218
 
Matrix &Matrix::operator*=(Matrix const &o)
219
 
{
220
 
    *this = *this * o;
221
 
    return *this;
222
 
}
223
 
 
224
 
 
225
 
 
226
 
 
227
 
 
228
 
/**
229
 
 *  Multiply by a scaling matrix
230
 
 */
231
 
Matrix &Matrix::operator*=(scale const &other)
232
 
{
233
 
    /* This loop is massive overkill.  Let's unroll.
234
 
     *   o    _c[] goes from 0..5
235
 
     *   o    other[] alternates between 0 and 1
236
 
     */
237
 
    /*
238
 
     * for (unsigned i = 0; i < 3; ++i) {
239
 
     *     for (unsigned j = 0; j < 2; ++j) {
240
 
     *         this->_c[i * 2 + j] *= other[j];
241
 
     *     }
242
 
     * }
243
 
     */
244
 
 
245
 
    NR::Coord const xscale = other[0];
246
 
    NR::Coord const yscale = other[1];
247
 
    NR::Coord *dest = _c;
248
 
 
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;
255
 
 
256
 
    return *this;
257
 
}
258
 
 
259
 
 
260
 
 
261
 
 
262
 
 
263
 
/**
264
51
 *  Return the inverse of this matrix.  If an inverse is not defined,
265
52
 *  then return the identity matrix.
266
53
 */
398
185
 
399
186
 
400
187
/**
401
 
 *  Assign a matrix to a given coordinate array
402
 
 */
403
 
Matrix &Matrix::assign(Coord const *array)
404
 
{
405
 
    assert(array != NULL);
406
 
 
407
 
    Coord const *src = array;
408
 
    Coord *dest = _c;
409
 
 
410
 
    *dest++ = *src++;  //0
411
 
    *dest++ = *src++;  //1
412
 
    *dest++ = *src++;  //2
413
 
    *dest++ = *src++;  //3
414
 
    *dest++ = *src++;  //4
415
 
    *dest   = *src  ;  //5
416
 
 
417
 
    return *this;
418
 
}
419
 
 
420
 
 
421
 
 
422
 
 
423
 
 
424
 
/**
425
 
 *  Copy this matrix's value to a NRMatrix
426
 
 */
427
 
NRMatrix *Matrix::copyto(NRMatrix *nrm) const {
428
 
 
429
 
    assert(nrm != NULL);
430
 
 
431
 
    Coord const *src = _c;
432
 
    Coord *dest = nrm->c;
433
 
 
434
 
    *dest++ = *src++;  //0
435
 
    *dest++ = *src++;  //1
436
 
    *dest++ = *src++;  //2
437
 
    *dest++ = *src++;  //3
438
 
    *dest++ = *src++;  //4
439
 
    *dest   = *src  ;  //5
440
 
 
441
 
    return nrm;
442
 
}
443
 
 
444
 
 
445
 
 
446
 
 
447
 
/**
448
 
 *  Copy this matrix's values to an array
449
 
 */
450
 
NR::Coord *Matrix::copyto(NR::Coord *array) const {
451
 
 
452
 
    assert(array != NULL);
453
 
 
454
 
    Coord const *src = _c;
455
 
    Coord *dest = array;
456
 
 
457
 
    *dest++ = *src++;  //0
458
 
    *dest++ = *src++;  //1
459
 
    *dest++ = *src++;  //2
460
 
    *dest++ = *src++;  //3
461
 
    *dest++ = *src++;  //4
462
 
    *dest   = *src  ;  //5
463
 
 
464
 
    return array;
465
 
}
466
 
 
467
 
 
468
 
 
469
 
 
470
 
 
471
 
/**
472
 
 *
473
 
 */
474
 
double expansion(Matrix const &m) {
475
 
    return sqrt(fabs(m.det()));
476
 
}
477
 
 
478
 
 
479
 
 
480
 
 
481
 
 
482
 
/**
483
 
 *
484
 
 */
485
 
double Matrix::expansion() const {
486
 
    return sqrt(fabs(det()));
487
 
}
488
 
 
489
 
 
490
 
 
491
 
 
492
 
 
493
 
/**
494
 
 *
495
 
 */
496
 
double Matrix::expansionX() const {
497
 
    return sqrt(_c[0] * _c[0] + _c[1] * _c[1]);
498
 
}
499
 
 
500
 
 
501
 
 
502
 
 
503
 
 
504
 
/**
505
 
 *
506
 
 */
507
 
double Matrix::expansionY() const {
508
 
    return sqrt(_c[2] * _c[2] + _c[3] * _c[3]);
509
 
}
510
 
 
511
 
 
512
 
 
513
 
 
514
 
 
515
 
/**
516
188
 *
517
189
 */
518
190
bool Matrix::is_translation(Coord const eps) const {
547
219
 
548
220
 
549
221
/**
550
 
 *
 
222
 *  test whether the matrix is the identity matrix (true).  (2geom's Matrix::isIdentity() does the same)
551
223
 */
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);
 
226
}
 
227
 
 
228
 
 
229
 
 
230
 
 
231
 
 
232
/**
 
233
 * calculates the descriminant of the matrix. (Geom::Coord Matrix::descrim() does the same)
 
234
 */
 
235
double expansion(Matrix const &m) {
 
236
    return sqrt(fabs(m.det()));
554
237
}
555
238
 
556
239
 
561
244
 *
562
245
 */
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);
 
247
    return
 
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);
565
252
}
566
253
 
567
254
 
572
259
 *
573
260
 */
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);
576
263
}
577
264
 
578
265
 
582
269
/**
583
270
 *
584
271
 */
585
 
bool matrix_equalp(Matrix const &m0, Matrix const &m1, NR::Coord const epsilon)
586
 
{
587
 
    return ( NR_MATRIX_DF_TEST_TRANSFORM_CLOSE(&m0, &m1, epsilon) &&
588
 
             NR_MATRIX_DF_TEST_TRANSLATE_CLOSE(&m0, &m1, epsilon)   );
589
 
}
590
 
 
591
 
 
592
 
 
593
 
 
594
 
 
595
 
/**
596
 
 *  A home-made assertion.  Stop if the two matrixes are not 'close' to
597
 
 *  each other.
598
 
 */
599
 
void assert_close(Matrix const &a, Matrix const &b)
600
 
{
601
 
    if (!matrix_equalp(a, b, 1e-3)) {
602
 
        fprintf(stderr,
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]);
609
 
        std::abort();
610
 
    }
 
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);
611
274
}
612
275
 
613
276