Code

fix by dvlierop2 for snapping bugs 1579556 and 1579587
[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>
16 using NR::Matrix;
17 using NR::X;
18 using NR::Y;
20 inline bool point_equalp(NR::Point const &a, NR::Point const &b)
21 {
22     return ( NR_DF_TEST_CLOSE(a[X], b[X], 1e-5) &&
23              NR_DF_TEST_CLOSE(a[Y], b[Y], 1e-5)   );
24 }
26 class NrMatrixTest : public CxxTest::TestSuite
27 {
28 public:
30     NrMatrixTest() :
31         m_id( NR::identity() ),
32         r_id( NR::Point(1, 0) ),
33         t_id( 0, 0 ),
34         c16( 1.0, 2.0,
35              3.0, 4.0,
36              5.0, 6.0),
37         r86( NR::Point(.8, .6) ),
38         mr86( r86 ),
39         t23( 2.0, 3.0 ),
40         s_id( 1.0, 1.0 )
41     {
42     }
43     virtual ~NrMatrixTest() {}
45 // createSuite and destroySuite get us per-suite setup and teardown
46 // without us having to worry about static initialization order, etc.
47     static NrMatrixTest *createSuite() { return new NrMatrixTest(); }
48     static void destroySuite( NrMatrixTest *suite ) { delete suite; }
50     Matrix const m_id;
51     NR::rotate const r_id;
52     NR::translate const t_id;
53     Matrix const c16;
54     NR::rotate const r86;
55     NR::Matrix const mr86;
56     NR::translate const t23;
57     NR::scale const s_id;
62     void testCtorsAssignmentOp(void)
63     {
64         Matrix const c16_copy(c16);
65         Matrix c16_eq(m_id);
66         c16_eq = c16;
67         for(unsigned i = 0; i < 6; ++i) {
68             TS_ASSERT_EQUALS( c16[i], 1.0 + i );
69             TS_ASSERT_EQUALS( c16[i], c16_copy[i] );
70             TS_ASSERT_EQUALS( c16[i], c16_eq[i] );
71             TS_ASSERT_EQUALS( m_id[i], double( i == 0 || i == 3 ) );
72         }
73     }
75     void testScaleCtor(void)
76     {
77         NR::scale const s(2.0, 3.0);
78         NR::Matrix const ms(s);
79         NR::Point const p(5.0, 7.0);
80         TS_ASSERT_EQUALS( p * s, NR::Point(10.0, 21.0) );
81         TS_ASSERT_EQUALS( p * ms, NR::Point(10.0, 21.0) );
82     }
84     void testRotateCtor(void)
85     {
86         NR::Point const p0(1.0, 0.0);
87         NR::Point const p90(0.0, 1.0);
88         TS_ASSERT_EQUALS( p0 * r86, NR::Point(.8, .6) );
89         TS_ASSERT_EQUALS( p0 * mr86, NR::Point(.8, .6) );
90         TS_ASSERT_EQUALS( p90 * r86, NR::Point(-.6, .8) );
91         TS_ASSERT_EQUALS( p90 * mr86, NR::Point(-.6, .8) );
92         TS_ASSERT( matrix_equalp(Matrix( r86 * r86 ),
93                                  mr86 * mr86,
94                                  1e-14) );
95     }
97     void testTranslateCtor(void)
98     {
99         NR::Matrix const mt23(t23);
100         NR::Point const b(-2.0, 3.0);
101         TS_ASSERT_EQUALS( b * t23, b * mt23 );
102     }
104     void testIdentity(void)
105     {
106         TS_ASSERT( m_id.test_identity() );
107         TS_ASSERT( Matrix(t_id).test_identity() );
108         TS_ASSERT( !(Matrix(NR::translate(-2, 3)).test_identity()) );
109         TS_ASSERT( Matrix(r_id).test_identity() );
110         NR::rotate const rot180(NR::Point(-1, 0));
111         TS_ASSERT( !(Matrix(rot180).test_identity()) );
112         TS_ASSERT( Matrix(s_id).test_identity() );
113         TS_ASSERT( !(Matrix(NR::scale(1.0, 0.0)).test_identity()) );
114         TS_ASSERT( !(Matrix(NR::scale(0.0, 1.0)).test_identity()) );
115         TS_ASSERT( !(Matrix(NR::scale(1.0, -1.0)).test_identity()) );
116         TS_ASSERT( !(Matrix(NR::scale(-1.0, -1.0)).test_identity()) );
117     }
119     void testInverse(void)
120     {
121         TS_ASSERT_EQUALS( m_id.inverse(), m_id );
122         TS_ASSERT_EQUALS( Matrix(t23).inverse(), Matrix(NR::translate(-2.0, -3.0)) );
123         NR::scale const s2(-4.0, 2.0);
124         NR::scale const sp5(-.25, .5);
125         TS_ASSERT_EQUALS( Matrix(s2).inverse(), Matrix(sp5) );
126     }
128     void testNrMatrixInvert(void)
129     {
130         NRMatrix const nr_m_id(m_id);
131         Matrix const m_s2(NR::scale(-4.0, 2.0));
132         NRMatrix const nr_s2(m_s2);
133         Matrix const m_sp5(NR::scale(-.25, .5));
134         NRMatrix const nr_sp5(m_sp5);
135         Matrix const m_t23(t23);
136         NRMatrix const nr_t23(m_t23);
137         NRMatrix inv;
138         nr_matrix_invert(&inv, &nr_m_id);
139         TS_ASSERT_EQUALS( Matrix(inv), m_id );
140         nr_matrix_invert(&inv, &nr_t23);
141         TS_ASSERT_EQUALS( Matrix(inv), Matrix(NR::translate(-2.0, -3.0)) );
142         nr_matrix_invert(&inv, &nr_s2);
143         TS_ASSERT_EQUALS( Matrix(inv), Matrix(nr_sp5) );
144         nr_matrix_invert(&inv, &nr_sp5);
145         TS_ASSERT_EQUALS( Matrix(inv), Matrix(nr_s2) );
147         /* Test that nr_matrix_invert handles src == dest. */
148         inv = nr_s2;
149         nr_matrix_invert(&inv, &inv);
150         TS_ASSERT_EQUALS( Matrix(inv), Matrix(nr_sp5) );
151         inv = nr_t23;
152         nr_matrix_invert(&inv, &inv);
153         TS_ASSERT_EQUALS( Matrix(inv), Matrix(NR::translate(-2.0, -3.0)) );
154     }
156     void testEllipticQuadraticForm(void)
157     {
158         NR::Matrix const aff(1.0, 1.0,
159                              0.0, 1.0,
160                              5.0, 6.0);
161         NR::Matrix const invaff = aff.inverse();
162         TS_ASSERT_EQUALS( invaff[1], -1.0 );
163                 
164         NR::Matrix const ef(elliptic_quadratic_form(invaff));
165         NR::Matrix const exp_ef(2, -1,
166                                 -1, 1,
167                                 0, 0);
168         TS_ASSERT_EQUALS( ef, exp_ef );
169     }
171     void testMatrixStarRotate(void)
172     {
173         NR::Matrix const ma(2.0, -1.0,
174                             4.0, 4.0,
175                             -0.5, 2.0);
176         NR::Matrix const a_r86( ma * r86 );
177         NR::Matrix const ma1( a_r86 * r86.inverse() );
178         TS_ASSERT( matrix_equalp(ma1, ma, 1e-12) );
179         NR::Matrix const exp_a_r86( 2*.8 + -1*-.6,  2*.6 + -1*.8,
180                                     4*.8 + 4*-.6,   4*.6 + 4*.8,
181                                     -.5*.8 + 2*-.6, -.5*.6 + 2*.8 );
182         TS_ASSERT( matrix_equalp(a_r86, exp_a_r86, 1e-12) );
183     }
185     void testTranslateStarScale_ScaleStarTranslate(void)
186     {
187         NR::translate const t2n4(2, -4);
188         NR::scale const sn2_8(-2, 8);
189         NR::Matrix const exp_ts(-2, 0,
190                                 0,  8,
191                                 -4, -32);
192         NR::Matrix const exp_st(-2, 0,
193                                 0,  8,
194                                 2, -4);
195         TS_ASSERT_EQUALS( exp_ts, t2n4 * sn2_8 );
196         TS_ASSERT_EQUALS( exp_st, sn2_8 * t2n4 );
197     }
199     void testMatrixStarScale(void)
200     {
201         NR::Matrix const ma(2.0, -1.0,
202                             4.0, 4.0,
203                             -0.5, 2.0);
204         NR::scale const sn2_8(-2, 8);
205         NR::Matrix const exp_as(-4, -8,
206                                 -8, 32,
207                                 1,  16);
208         TS_ASSERT_EQUALS( ma * sn2_8, exp_as );
209     }
210 };
212 /*
213   Local Variables:
214   mode:c++
215   c-file-style:"stroustrup"
216   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
217   indent-tabs-mode:nil
218   fill-column:99
219   End:
220 */
221 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :