Code

d4267ffa518297af2f77dc31e74b0f05025a6306
[inkscape.git] / src / libnr / nr-matrix-test.h
1 #include <cxxtest/TestSuite.h>
3 #include <libnr/nr-matrix.h>
4 #include <libnr/nr-matrix-fns.h>
5 #include <libnr/nr-matrix-ops.h>
6 #include <libnr/nr-matrix-rotate-ops.h>
7 #include <libnr/nr-matrix-scale-ops.h>
8 #include <libnr/nr-point-matrix-ops.h>
9 #include <libnr/nr-rotate.h>
10 #include <libnr/nr-rotate-ops.h>
11 #include <libnr/nr-scale-ops.h>
12 #include <libnr/nr-scale-translate-ops.h>
13 #include <libnr/nr-translate.h>
14 #include <libnr/nr-translate-ops.h>
15 #include <libnr/nr-translate-scale-ops.h>
17 inline bool point_equalp(NR::Point const &a, NR::Point const &b)
18 {
19     return ( NR_DF_TEST_CLOSE(a[NR::X], b[NR::X], 1e-5) &&
20              NR_DF_TEST_CLOSE(a[NR::Y], b[NR::Y], 1e-5)   );
21 }
23 class NrMatrixTest : public CxxTest::TestSuite
24 {
25 public:
27     NrMatrixTest() :
28         m_id( NR::identity() ),
29         r_id( NR::Point(1, 0) ),
30         t_id( 0, 0 ),
31         c16( 1.0, 2.0,
32              3.0, 4.0,
33              5.0, 6.0),
34         r86( NR::Point(.8, .6) ),
35         mr86( r86 ),
36         t23( 2.0, 3.0 ),
37         s_id( 1.0, 1.0 )
38     {
39     }
40     virtual ~NrMatrixTest() {}
42 // createSuite and destroySuite get us per-suite setup and teardown
43 // without us having to worry about static initialization order, etc.
44     static NrMatrixTest *createSuite() { return new NrMatrixTest(); }
45     static void destroySuite( NrMatrixTest *suite ) { delete suite; }
47     NR::Matrix const m_id;
48     NR::rotate const r_id;
49     NR::translate const t_id;
50     NR::Matrix const c16;
51     NR::rotate const r86;
52     NR::Matrix const mr86;
53     NR::translate const t23;
54     NR::scale const s_id;
59     void testCtorsAssignmentOp(void)
60     {
61         NR::Matrix const c16_copy(c16);
62         NR::Matrix c16_eq(m_id);
63         c16_eq = c16;
64         for(unsigned i = 0; i < 6; ++i) {
65             TS_ASSERT_EQUALS( c16[i], 1.0 + i );
66             TS_ASSERT_EQUALS( c16[i], c16_copy[i] );
67             TS_ASSERT_EQUALS( c16[i], c16_eq[i] );
68             TS_ASSERT_EQUALS( m_id[i], double( i == 0 || i == 3 ) );
69         }
70     }
72     void testScaleCtor(void)
73     {
74         NR::scale const s(2.0, 3.0);
75         NR::Matrix const ms(s);
76         NR::Point const p(5.0, 7.0);
77         TS_ASSERT_EQUALS( p * s, NR::Point(10.0, 21.0) );
78         TS_ASSERT_EQUALS( p * ms, NR::Point(10.0, 21.0) );
79     }
81     void testRotateCtor(void)
82     {
83         NR::Point const p0(1.0, 0.0);
84         NR::Point const p90(0.0, 1.0);
85         TS_ASSERT_EQUALS( p0 * r86, NR::Point(.8, .6) );
86         TS_ASSERT_EQUALS( p0 * mr86, NR::Point(.8, .6) );
87         TS_ASSERT_EQUALS( p90 * r86, NR::Point(-.6, .8) );
88         TS_ASSERT_EQUALS( p90 * mr86, NR::Point(-.6, .8) );
89         TS_ASSERT( matrix_equalp(NR::Matrix( r86 * r86 ),
90                                  mr86 * mr86,
91                                  1e-14) );
92     }
94     void testTranslateCtor(void)
95     {
96         NR::Matrix const mt23(t23);
97         NR::Point const b(-2.0, 3.0);
98         TS_ASSERT_EQUALS( b * t23, b * mt23 );
99     }
101     void testIdentity(void)
102     {
103         TS_ASSERT( m_id.test_identity() );
104         TS_ASSERT( NR::Matrix(t_id).test_identity() );
105         TS_ASSERT( !(NR::Matrix(NR::translate(-2, 3)).test_identity()) );
106         TS_ASSERT( NR::Matrix(r_id).test_identity() );
107         NR::rotate const rot180(NR::Point(-1, 0));
108         TS_ASSERT( !(NR::Matrix(rot180).test_identity()) );
109         TS_ASSERT( NR::Matrix(s_id).test_identity() );
110         TS_ASSERT( !(NR::Matrix(NR::scale(1.0, 0.0)).test_identity()) );
111         TS_ASSERT( !(NR::Matrix(NR::scale(0.0, 1.0)).test_identity()) );
112         TS_ASSERT( !(NR::Matrix(NR::scale(1.0, -1.0)).test_identity()) );
113         TS_ASSERT( !(NR::Matrix(NR::scale(-1.0, -1.0)).test_identity()) );
114     }
116     void testInverse(void)
117     {
118         TS_ASSERT_EQUALS( m_id.inverse(), m_id );
119         TS_ASSERT_EQUALS( NR::Matrix(t23).inverse(), NR::Matrix(NR::translate(-2.0, -3.0)) );
120         NR::scale const s2(-4.0, 2.0);
121         NR::scale const sp5(-.25, .5);
122         TS_ASSERT_EQUALS( NR::Matrix(s2).inverse(), NR::Matrix(sp5) );
123         TS_ASSERT_EQUALS( NR::Matrix(sp5).inverse(), NR::Matrix(s2) );
124     }
126     void testEllipticQuadraticForm(void)
127     {
128         NR::Matrix const aff(1.0, 1.0,
129                              0.0, 1.0,
130                              5.0, 6.0);
131         NR::Matrix const invaff = aff.inverse();
132         TS_ASSERT_EQUALS( invaff[1], -1.0 );
134         NR::Matrix const ef(elliptic_quadratic_form(invaff));
135         NR::Matrix const exp_ef(2, -1,
136                                 -1, 1,
137                                 0, 0);
138         TS_ASSERT_EQUALS( ef, exp_ef );
139     }
141     void testMatrixStarRotate(void)
142     {
143         NR::Matrix const ma(2.0, -1.0,
144                             4.0, 4.0,
145                             -0.5, 2.0);
146         NR::Matrix const a_r86( ma * r86 );
147         NR::Matrix const ma1( a_r86 * r86.inverse() );
148         TS_ASSERT( matrix_equalp(ma1, ma, 1e-12) );
149         NR::Matrix const exp_a_r86( 2*.8 + -1*-.6,  2*.6 + -1*.8,
150                                     4*.8 + 4*-.6,   4*.6 + 4*.8,
151                                     -.5*.8 + 2*-.6, -.5*.6 + 2*.8 );
152         TS_ASSERT( matrix_equalp(a_r86, exp_a_r86, 1e-12) );
153     }
155     void testTranslateStarScale_ScaleStarTranslate(void)
156     {
157         NR::translate const t2n4(2, -4);
158         NR::scale const sn2_8(-2, 8);
159         NR::Matrix const exp_ts(-2, 0,
160                                 0,  8,
161                                 -4, -32);
162         NR::Matrix const exp_st(-2, 0,
163                                 0,  8,
164                                 2, -4);
165         TS_ASSERT_EQUALS( exp_ts, t2n4 * sn2_8 );
166         TS_ASSERT_EQUALS( exp_st, sn2_8 * t2n4 );
167     }
169     void testMatrixStarScale(void)
170     {
171         NR::Matrix const ma(2.0, -1.0,
172                             4.0, 4.0,
173                             -0.5, 2.0);
174         NR::scale const sn2_8(-2, 8);
175         NR::Matrix const exp_as(-4, -8,
176                                 -8, 32,
177                                 1,  16);
178         TS_ASSERT_EQUALS( ma * sn2_8, exp_as );
179     }
180 };
182 /*
183   Local Variables:
184   mode:c++
185   c-file-style:"stroustrup"
186   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
187   indent-tabs-mode:nil
188   fill-column:99
189   End:
190 */
191 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :