1
#include <utest/utest.h>
2
#include <libnr/matrix.h>
3
#include <libnr/matrix-fns.h>
4
#include <libnr/matrix-ops.h>
5
#include <libnr/matrix-rotate-ops.h>
6
#include <libnr/matrix-scale-ops.h>
7
#include <libnr/point-matrix-ops.h>
8
#include <libnr/rotate.h>
9
#include <libnr/rotate-ops.h>
10
#include <libnr/scale-ops.h>
11
#include <libnr/scale-translate-ops.h>
12
#include <libnr/translate.h>
13
#include <libnr/translate-ops.h>
14
#include <libnr/translate-scale-ops.h>
19
inline bool point_equalp(Geom::Point const &a, Geom::Point const &b)
21
return ( Geom_DF_TEST_CLOSE(a[X], b[X], 1e-5) &&
22
Geom_DF_TEST_CLOSE(a[Y], b[Y], 1e-5) );
25
int main(int argc, char *argv[])
27
int rc = EXIT_SUCCESS;
29
Matrix const m_id(Geom::identity());
30
Geom::rotate const r_id(Geom::Point(1, 0));
31
Geom::translate const t_id(0, 0);
33
utest_start("Matrix");
35
Matrix const c16(1.0, 2.0,
38
UTEST_TEST("basic constructors, operator=") {
39
Matrix const c16_copy(c16);
42
for(unsigned i = 0; i < 6; ++i) {
43
UTEST_ASSERT( c16[i] == 1.0 + i );
44
UTEST_ASSERT( c16[i] == c16_copy[i] );
45
UTEST_ASSERT( c16[i] == c16_eq[i] );
46
UTEST_ASSERT( m_id[i] == double( i == 0 || i == 3 ) );
50
UTEST_TEST("scale constructor") {
51
Geom::scale const s(2.0, 3.0);
52
Geom::Matrix const ms(s);
53
Geom::Point const p(5.0, 7.0);
54
UTEST_ASSERT( p * s == Geom::Point(10.0, 21.0) );
55
UTEST_ASSERT( p * ms == Geom::Point(10.0, 21.0) );
58
Geom::rotate const r86(Geom::Point(.8, .6));
59
Geom::Matrix const mr86(r86);
60
UTEST_TEST("rotate constructor") {
61
Geom::Point const p0(1.0, 0.0);
62
Geom::Point const p90(0.0, 1.0);
63
UTEST_ASSERT( p0 * r86 == Geom::Point(.8, .6) );
64
UTEST_ASSERT( p0 * mr86 == Geom::Point(.8, .6) );
65
UTEST_ASSERT( p90 * r86 == Geom::Point(-.6, .8) );
66
UTEST_ASSERT( p90 * mr86 == Geom::Point(-.6, .8) );
67
UTEST_ASSERT(matrix_equalp(Matrix( r86 * r86 ),
72
Geom::translate const t23(2.0, 3.0);
73
UTEST_TEST("translate constructor") {
74
Geom::Matrix const mt23(t23);
75
Geom::Point const b(-2.0, 3.0);
76
UTEST_ASSERT( b * t23 == b * mt23 );
79
Geom::scale const s_id(1.0, 1.0);
80
UTEST_TEST("test_identity") {
81
UTEST_ASSERT(m_id.test_identity());
82
UTEST_ASSERT(Matrix(t_id).test_identity());
83
UTEST_ASSERT(!(Matrix(Geom::translate(-2, 3)).test_identity()));
84
UTEST_ASSERT(Matrix(r_id).test_identity());
85
Geom::rotate const rot180(Geom::Point(-1, 0));
86
UTEST_ASSERT(!(Matrix(rot180).test_identity()));
87
UTEST_ASSERT(Matrix(s_id).test_identity());
88
UTEST_ASSERT(!(Matrix(Geom::scale(1.0, 0.0)).test_identity()));
89
UTEST_ASSERT(!(Matrix(Geom::scale(0.0, 1.0)).test_identity()));
90
UTEST_ASSERT(!(Matrix(Geom::scale(1.0, -1.0)).test_identity()));
91
UTEST_ASSERT(!(Matrix(Geom::scale(-1.0, -1.0)).test_identity()));
94
UTEST_TEST("inverse") {
95
UTEST_ASSERT( m_id.inverse() == m_id );
96
UTEST_ASSERT( Matrix(t23).inverse() == Matrix(Geom::translate(-2.0, -3.0)) );
97
Geom::scale const s2(-4.0, 2.0);
98
Geom::scale const sp5(-.25, .5);
99
UTEST_ASSERT( Matrix(s2).inverse() == Matrix(sp5) );
102
UTEST_TEST("nr_matrix_invert") {
103
NRMatrix const nr_m_id(m_id);
104
Matrix const m_s2(Geom::scale(-4.0, 2.0));
105
NRMatrix const nr_s2(m_s2);
106
Matrix const m_sp5(Geom::scale(-.25, .5));
107
NRMatrix const nr_sp5(m_sp5);
108
Matrix const m_t23(t23);
109
NRMatrix const nr_t23(m_t23);
111
nr_matrix_invert(&inv, &nr_m_id);
112
UTEST_ASSERT( Matrix(inv) == m_id );
113
nr_matrix_invert(&inv, &nr_t23);
114
UTEST_ASSERT( Matrix(inv) == Matrix(Geom::translate(-2.0, -3.0)) );
115
nr_matrix_invert(&inv, &nr_s2);
116
UTEST_ASSERT( Matrix(inv) == Matrix(nr_sp5) );
117
nr_matrix_invert(&inv, &nr_sp5);
118
UTEST_ASSERT( Matrix(inv) == Matrix(nr_s2) );
120
/* Test that nr_matrix_invert handles src == dest. */
122
nr_matrix_invert(&inv, &inv);
123
UTEST_ASSERT( Matrix(inv) == Matrix(nr_sp5) );
125
nr_matrix_invert(&inv, &inv);
126
UTEST_ASSERT( Matrix(inv) == Matrix(Geom::translate(-2.0, -3.0)) );
129
UTEST_TEST("elliptic quadratic form") {
130
Geom::Matrix const aff(1.0, 1.0,
133
Geom::Matrix const invaff = aff.inverse();
134
UTEST_ASSERT( invaff[1] == -1.0 );
136
Geom::Matrix const ef(elliptic_quadratic_form(invaff));
137
Geom::Matrix const exp_ef(2, -1,
140
UTEST_ASSERT( ef == exp_ef );
143
UTEST_TEST("Matrix * rotate") {
144
Geom::Matrix const ma(2.0, -1.0,
147
Geom::Matrix const a_r86( ma * r86 );
148
Geom::Matrix const ma1( a_r86 * r86.inverse() );
149
UTEST_ASSERT(matrix_equalp(ma1, ma, 1e-12));
150
Geom::Matrix const exp_a_r86( 2*.8 + -1*-.6, 2*.6 + -1*.8,
151
4*.8 + 4*-.6, 4*.6 + 4*.8,
152
-.5*.8 + 2*-.6, -.5*.6 + 2*.8 );
153
UTEST_ASSERT(matrix_equalp(a_r86, exp_a_r86, 1e-12));
156
UTEST_TEST("translate*scale, scale*translate") {
157
Geom::translate const t2n4(2, -4);
158
Geom::scale const sn2_8(-2, 8);
159
Geom::Matrix const exp_ts(-2, 0,
162
Geom::Matrix const exp_st(-2, 0,
165
UTEST_ASSERT( exp_ts == t2n4 * sn2_8 );
166
UTEST_ASSERT( exp_st == sn2_8 * t2n4 );
169
UTEST_TEST("Matrix * scale") {
170
Geom::Matrix const ma(2.0, -1.0,
173
Geom::scale const sn2_8(-2, 8);
174
Geom::Matrix const exp_as(-4, -8,
177
UTEST_ASSERT( ma * sn2_8 == exp_as );
191
c-file-style:"stroustrup"
192
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
197
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :