Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
affine-test.cpp
Go to the documentation of this file.
1/*
5 * Authors:
6 * Krzysztof KosiƄski <tweenk.pl@gmail.com>
7 *
8 * Copyright 2010 Authors
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it either under the terms of the GNU Lesser General Public
12 * License version 2.1 as published by the Free Software Foundation
13 * (the "LGPL") or, at your option, under the terms of the Mozilla
14 * Public License Version 1.1 (the "MPL"). If you do not alter this
15 * notice, a recipient may use your version of this file under either
16 * the MPL or the LGPL.
17 *
18 * You should have received a copy of the LGPL along with this library
19 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * You should have received a copy of the MPL along with this library
22 * in the file COPYING-MPL-1.1
23 *
24 * The contents of this file are subject to the Mozilla Public License
25 * Version 1.1 (the "License"); you may not use this file except in
26 * compliance with the License. You may obtain a copy of the License at
27 * http://www.mozilla.org/MPL/
28 *
29 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
30 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
31 * the specific language governing rights and limitations.
32 */
33
34#include <gtest/gtest.h>
35#include <2geom/affine.h>
36#include <2geom/transforms.h>
37
38namespace Geom {
39
40TEST(AffineTest, Equality) {
41 Affine e; // identity
42 Affine a(1, 2, 3, 4, 5, 6);
43 EXPECT_EQ(e, e);
44 EXPECT_EQ(e, Geom::identity());
45 EXPECT_EQ(e, Geom::Affine::identity());
46 EXPECT_NE(e, a);
47}
48
49TEST(AffineTest, Classification) {
50 {
51 Affine a; // identity
52 EXPECT_TRUE(a.isIdentity());
53 EXPECT_TRUE(a.isTranslation());
54 EXPECT_TRUE(a.isScale());
55 EXPECT_TRUE(a.isUniformScale());
56 EXPECT_TRUE(a.isRotation());
57 EXPECT_TRUE(a.isHShear());
58 EXPECT_TRUE(a.isVShear());
59 EXPECT_TRUE(a.isZoom());
60 EXPECT_FALSE(a.isNonzeroTranslation());
61 EXPECT_FALSE(a.isNonzeroScale());
62 EXPECT_FALSE(a.isNonzeroUniformScale());
63 EXPECT_FALSE(a.isNonzeroRotation());
64 EXPECT_FALSE(a.isNonzeroNonpureRotation());
65 EXPECT_FALSE(a.isNonzeroHShear());
66 EXPECT_FALSE(a.isNonzeroVShear());
67 EXPECT_TRUE(a.preservesArea());
68 EXPECT_TRUE(a.preservesAngles());
69 EXPECT_TRUE(a.preservesDistances());
70 EXPECT_FALSE(a.flips());
71 EXPECT_FALSE(a.isSingular());
72 }
73 {
74 Affine a = Translate(10, 15); // pure translation
75 EXPECT_FALSE(a.isIdentity());
76 EXPECT_TRUE(a.isTranslation());
77 EXPECT_FALSE(a.isScale());
78 EXPECT_FALSE(a.isUniformScale());
79 EXPECT_FALSE(a.isRotation());
80 EXPECT_FALSE(a.isHShear());
81 EXPECT_FALSE(a.isVShear());
82 EXPECT_TRUE(a.isZoom());
83 EXPECT_TRUE(a.isNonzeroTranslation());
84 EXPECT_FALSE(a.isNonzeroScale());
85 EXPECT_FALSE(a.isNonzeroUniformScale());
86 EXPECT_FALSE(a.isNonzeroRotation());
87 EXPECT_FALSE(a.isNonzeroNonpureRotation());
88 EXPECT_FALSE(a.isNonzeroHShear());
89 EXPECT_FALSE(a.isNonzeroVShear());
90 EXPECT_TRUE(a.preservesArea());
91 EXPECT_TRUE(a.preservesAngles());
92 EXPECT_TRUE(a.preservesDistances());
93 EXPECT_FALSE(a.flips());
94 EXPECT_FALSE(a.isSingular());
95 }
96 {
97 Affine a = Scale(-1.0, 1.0); // flip on the X axis
98 EXPECT_FALSE(a.isIdentity());
99 EXPECT_FALSE(a.isTranslation());
100 EXPECT_TRUE(a.isScale());
101 EXPECT_TRUE(a.isUniformScale());
102 EXPECT_FALSE(a.isRotation());
103 EXPECT_FALSE(a.isHShear());
104 EXPECT_FALSE(a.isVShear());
105 EXPECT_FALSE(a.isZoom()); // zoom must be non-flipping
106 EXPECT_FALSE(a.isNonzeroTranslation());
107 EXPECT_TRUE(a.isNonzeroScale());
108 EXPECT_TRUE(a.isNonzeroUniformScale());
109 EXPECT_FALSE(a.isNonzeroRotation());
110 EXPECT_FALSE(a.isNonzeroNonpureRotation());
111 EXPECT_FALSE(a.isNonzeroHShear());
112 EXPECT_FALSE(a.isNonzeroVShear());
113 EXPECT_TRUE(a.preservesArea());
114 EXPECT_TRUE(a.preservesAngles());
115 EXPECT_TRUE(a.preservesDistances());
116 EXPECT_TRUE(a.flips());
117 EXPECT_FALSE(a.isSingular());
118 }
119 {
120 Affine a = Scale(0.5, 0.5); // pure uniform scale
121 EXPECT_FALSE(a.isIdentity());
122 EXPECT_FALSE(a.isTranslation());
123 EXPECT_TRUE(a.isScale());
124 EXPECT_TRUE(a.isUniformScale());
125 EXPECT_FALSE(a.isRotation());
126 EXPECT_FALSE(a.isHShear());
127 EXPECT_FALSE(a.isVShear());
128 EXPECT_TRUE(a.isZoom());
129 EXPECT_FALSE(a.isNonzeroTranslation());
130 EXPECT_TRUE(a.isNonzeroScale());
131 EXPECT_TRUE(a.isNonzeroUniformScale());
132 EXPECT_FALSE(a.isNonzeroRotation());
133 EXPECT_FALSE(a.isNonzeroNonpureRotation());
134 EXPECT_FALSE(a.isNonzeroHShear());
135 EXPECT_FALSE(a.isNonzeroVShear());
136 EXPECT_FALSE(a.preservesArea());
137 EXPECT_TRUE(a.preservesAngles());
138 EXPECT_FALSE(a.preservesDistances());
139 EXPECT_FALSE(a.flips());
140 EXPECT_FALSE(a.isSingular());
141 }
142 {
143 Affine a = Scale(0.5, -0.5); // pure uniform flipping scale
144 EXPECT_FALSE(a.isIdentity());
145 EXPECT_FALSE(a.isTranslation());
146 EXPECT_TRUE(a.isScale());
147 EXPECT_TRUE(a.isUniformScale());
148 EXPECT_FALSE(a.isRotation());
149 EXPECT_FALSE(a.isHShear());
150 EXPECT_FALSE(a.isVShear());
151 EXPECT_FALSE(a.isZoom()); // zoom must be non-flipping
152 EXPECT_FALSE(a.isNonzeroTranslation());
153 EXPECT_TRUE(a.isNonzeroScale());
154 EXPECT_TRUE(a.isNonzeroUniformScale());
155 EXPECT_FALSE(a.isNonzeroRotation());
156 EXPECT_FALSE(a.isNonzeroNonpureRotation());
157 EXPECT_FALSE(a.isNonzeroHShear());
158 EXPECT_FALSE(a.isNonzeroVShear());
159 EXPECT_FALSE(a.preservesArea());
160 EXPECT_TRUE(a.preservesAngles());
161 EXPECT_FALSE(a.preservesDistances());
162 EXPECT_TRUE(a.flips());
163 EXPECT_FALSE(a.isSingular());
164 }
165 {
166 Affine a = Scale(0.5, 0.7); // pure non-uniform scale
167 EXPECT_FALSE(a.isIdentity());
168 EXPECT_FALSE(a.isTranslation());
169 EXPECT_TRUE(a.isScale());
170 EXPECT_FALSE(a.isUniformScale());
171 EXPECT_FALSE(a.isRotation());
172 EXPECT_FALSE(a.isHShear());
173 EXPECT_FALSE(a.isVShear());
174 EXPECT_FALSE(a.isZoom());
175 EXPECT_FALSE(a.isNonzeroTranslation());
176 EXPECT_TRUE(a.isNonzeroScale());
177 EXPECT_FALSE(a.isNonzeroUniformScale());
178 EXPECT_FALSE(a.isNonzeroRotation());
179 EXPECT_FALSE(a.isNonzeroNonpureRotation());
180 EXPECT_FALSE(a.isNonzeroHShear());
181 EXPECT_FALSE(a.isNonzeroVShear());
182 EXPECT_FALSE(a.preservesArea());
183 EXPECT_FALSE(a.preservesAngles());
184 EXPECT_FALSE(a.preservesDistances());
185 EXPECT_FALSE(a.flips());
186 EXPECT_FALSE(a.isSingular());
187 }
188 {
189 Affine a = Scale(0.5, 2.0); // "squeeze" transform (non-uniform scale with det=1)
190 EXPECT_FALSE(a.isIdentity());
191 EXPECT_FALSE(a.isTranslation());
192 EXPECT_TRUE(a.isScale());
193 EXPECT_FALSE(a.isUniformScale());
194 EXPECT_FALSE(a.isRotation());
195 EXPECT_FALSE(a.isHShear());
196 EXPECT_FALSE(a.isVShear());
197 EXPECT_FALSE(a.isZoom());
198 EXPECT_FALSE(a.isNonzeroTranslation());
199 EXPECT_TRUE(a.isNonzeroScale());
200 EXPECT_FALSE(a.isNonzeroUniformScale());
201 EXPECT_FALSE(a.isNonzeroRotation());
202 EXPECT_FALSE(a.isNonzeroNonpureRotation());
203 EXPECT_FALSE(a.isNonzeroHShear());
204 EXPECT_FALSE(a.isNonzeroVShear());
205 EXPECT_TRUE(a.preservesArea());
206 EXPECT_FALSE(a.preservesAngles());
207 EXPECT_FALSE(a.preservesDistances());
208 EXPECT_FALSE(a.flips());
209 EXPECT_FALSE(a.isSingular());
210 }
211 {
212 Affine a = Rotate(0.7); // pure rotation
213 EXPECT_FALSE(a.isIdentity());
214 EXPECT_FALSE(a.isTranslation());
215 EXPECT_FALSE(a.isScale());
216 EXPECT_FALSE(a.isUniformScale());
217 EXPECT_TRUE(a.isRotation());
218 EXPECT_FALSE(a.isHShear());
219 EXPECT_FALSE(a.isVShear());
220 EXPECT_FALSE(a.isZoom());
221 EXPECT_FALSE(a.isNonzeroTranslation());
222 EXPECT_FALSE(a.isNonzeroScale());
223 EXPECT_FALSE(a.isNonzeroUniformScale());
224 EXPECT_TRUE(a.isNonzeroRotation());
225 EXPECT_TRUE(a.isNonzeroNonpureRotation());
226 EXPECT_EQ(a.rotationCenter(), Point(0.0,0.0));
227 EXPECT_FALSE(a.isNonzeroHShear());
228 EXPECT_FALSE(a.isNonzeroVShear());
229 EXPECT_TRUE(a.preservesArea());
230 EXPECT_TRUE(a.preservesAngles());
231 EXPECT_TRUE(a.preservesDistances());
232 EXPECT_FALSE(a.flips());
233 EXPECT_FALSE(a.isSingular());
234 }
235 {
236 Point rotation_center(1.23,4.56);
237 Affine a = Translate(-rotation_center) * Rotate(0.7) * Translate(rotation_center); // rotation around (1.23,4.56)
238 EXPECT_FALSE(a.isIdentity());
239 EXPECT_FALSE(a.isTranslation());
240 EXPECT_FALSE(a.isScale());
241 EXPECT_FALSE(a.isUniformScale());
242 EXPECT_FALSE(a.isRotation());
243 EXPECT_FALSE(a.isHShear());
244 EXPECT_FALSE(a.isVShear());
245 EXPECT_FALSE(a.isZoom());
246 EXPECT_FALSE(a.isNonzeroTranslation());
247 EXPECT_FALSE(a.isNonzeroScale());
248 EXPECT_FALSE(a.isNonzeroUniformScale());
249 EXPECT_FALSE(a.isNonzeroRotation());
250 EXPECT_TRUE(a.isNonzeroNonpureRotation());
251 EXPECT_TRUE(are_near(a.rotationCenter(), rotation_center, 1e-7));
252 EXPECT_FALSE(a.isNonzeroHShear());
253 EXPECT_FALSE(a.isNonzeroVShear());
254 EXPECT_TRUE(a.preservesArea());
255 EXPECT_TRUE(a.preservesAngles());
256 EXPECT_TRUE(a.preservesDistances());
257 EXPECT_FALSE(a.flips());
258 EXPECT_FALSE(a.isSingular());
259 }
260 {
261 Affine a = HShear(0.5); // pure horizontal shear
262 EXPECT_FALSE(a.isIdentity());
263 EXPECT_FALSE(a.isTranslation());
264 EXPECT_FALSE(a.isScale());
265 EXPECT_FALSE(a.isUniformScale());
266 EXPECT_FALSE(a.isRotation());
267 EXPECT_TRUE(a.isHShear());
268 EXPECT_FALSE(a.isVShear());
269 EXPECT_FALSE(a.isZoom());
270 EXPECT_FALSE(a.isNonzeroTranslation());
271 EXPECT_FALSE(a.isNonzeroScale());
272 EXPECT_FALSE(a.isNonzeroUniformScale());
273 EXPECT_FALSE(a.isNonzeroRotation());
274 EXPECT_FALSE(a.isNonzeroNonpureRotation());
275 EXPECT_TRUE(a.isNonzeroHShear());
276 EXPECT_FALSE(a.isNonzeroVShear());
277 EXPECT_TRUE(a.preservesArea());
278 EXPECT_FALSE(a.preservesAngles());
279 EXPECT_FALSE(a.preservesDistances());
280 EXPECT_FALSE(a.flips());
281 EXPECT_FALSE(a.isSingular());
282 }
283 {
284 Affine a = VShear(0.5); // pure vertical shear
285 EXPECT_FALSE(a.isIdentity());
286 EXPECT_FALSE(a.isTranslation());
287 EXPECT_FALSE(a.isScale());
288 EXPECT_FALSE(a.isUniformScale());
289 EXPECT_FALSE(a.isRotation());
290 EXPECT_FALSE(a.isHShear());
291 EXPECT_TRUE(a.isVShear());
292 EXPECT_FALSE(a.isZoom());
293 EXPECT_FALSE(a.isNonzeroTranslation());
294 EXPECT_FALSE(a.isNonzeroScale());
295 EXPECT_FALSE(a.isNonzeroUniformScale());
296 EXPECT_FALSE(a.isNonzeroRotation());
297 EXPECT_FALSE(a.isNonzeroNonpureRotation());
298 EXPECT_FALSE(a.isNonzeroHShear());
299 EXPECT_TRUE(a.isNonzeroVShear());
300 EXPECT_TRUE(a.preservesArea());
301 EXPECT_FALSE(a.preservesAngles());
302 EXPECT_FALSE(a.preservesDistances());
303 EXPECT_FALSE(a.flips());
304 EXPECT_FALSE(a.isSingular());
305 }
306 {
307 Affine a = Zoom(3.0, Translate(10, 15)); // zoom
308 EXPECT_FALSE(a.isIdentity());
309 EXPECT_FALSE(a.isTranslation());
310 EXPECT_FALSE(a.isScale());
311 EXPECT_FALSE(a.isUniformScale());
312 EXPECT_FALSE(a.isRotation());
313 EXPECT_FALSE(a.isHShear());
314 EXPECT_FALSE(a.isVShear());
315 EXPECT_TRUE(a.isZoom());
316 EXPECT_FALSE(a.isNonzeroTranslation());
317 EXPECT_FALSE(a.isNonzeroScale());
318 EXPECT_FALSE(a.isNonzeroUniformScale());
319 EXPECT_FALSE(a.isNonzeroRotation());
320 EXPECT_FALSE(a.isNonzeroNonpureRotation());
321 EXPECT_FALSE(a.isNonzeroHShear());
322 EXPECT_FALSE(a.isNonzeroVShear());
323 EXPECT_FALSE(a.preservesArea());
324 EXPECT_TRUE(a.preservesAngles());
325 EXPECT_FALSE(a.preservesDistances());
326 EXPECT_FALSE(a.flips());
327 EXPECT_FALSE(a.isSingular());
328
329 EXPECT_TRUE(a.withoutTranslation().isUniformScale());
330 EXPECT_TRUE(a.withoutTranslation().isNonzeroUniformScale());
331 }
332 {
333 Affine a(0, 0, 0, 0, 0, 0); // zero matrix (singular)
334 EXPECT_FALSE(a.isIdentity());
335 EXPECT_FALSE(a.isTranslation());
336 EXPECT_FALSE(a.isScale());
337 EXPECT_FALSE(a.isUniformScale());
338 EXPECT_FALSE(a.isRotation());
339 EXPECT_FALSE(a.isHShear());
340 EXPECT_FALSE(a.isVShear());
341 EXPECT_FALSE(a.isZoom());
342 EXPECT_FALSE(a.isNonzeroTranslation());
343 EXPECT_FALSE(a.isNonzeroScale());
344 EXPECT_FALSE(a.isNonzeroUniformScale());
345 EXPECT_FALSE(a.isNonzeroRotation());
346 EXPECT_FALSE(a.isNonzeroNonpureRotation());
347 EXPECT_FALSE(a.isNonzeroHShear());
348 EXPECT_FALSE(a.isNonzeroVShear());
349 EXPECT_FALSE(a.preservesArea());
350 EXPECT_FALSE(a.preservesAngles());
351 EXPECT_FALSE(a.preservesDistances());
352 EXPECT_FALSE(a.flips());
353 EXPECT_TRUE(a.isSingular());
354 }
355 {
356 Affine a(0, 1, 0, 1, 10, 10); // another singular matrix
357 EXPECT_FALSE(a.isIdentity());
358 EXPECT_FALSE(a.isTranslation());
359 EXPECT_FALSE(a.isScale());
360 EXPECT_FALSE(a.isUniformScale());
361 EXPECT_FALSE(a.isRotation());
362 EXPECT_FALSE(a.isHShear());
363 EXPECT_FALSE(a.isVShear());
364 EXPECT_FALSE(a.isZoom());
365 EXPECT_FALSE(a.isNonzeroTranslation());
366 EXPECT_FALSE(a.isNonzeroScale());
367 EXPECT_FALSE(a.isNonzeroUniformScale());
368 EXPECT_FALSE(a.isNonzeroRotation());
369 EXPECT_FALSE(a.isNonzeroNonpureRotation());
370 EXPECT_FALSE(a.isNonzeroHShear());
371 EXPECT_FALSE(a.isNonzeroVShear());
372 EXPECT_FALSE(a.preservesArea());
373 EXPECT_FALSE(a.preservesAngles());
374 EXPECT_FALSE(a.preservesDistances());
375 EXPECT_FALSE(a.flips());
376 EXPECT_TRUE(a.isSingular());
377 }
378}
379
380TEST(AffineTest, Inversion) {
381 Affine i(1, 2, 1, -2, 10, 15); // invertible
382 Affine n(1, 2, 1, 2, 15, 30); // non-invertible
383 Affine e; // identity
384 EXPECT_EQ(i * i.inverse(), e);
385 EXPECT_EQ(i.inverse().inverse(), i);
386 EXPECT_EQ(n.inverse(), e);
387 EXPECT_EQ(e.inverse(), e);
388}
389
390TEST(AffineTest, CoordinateAccess) {
391 Affine a(0, 1, 2, 3, 4, 5);
392 for (int i=0; i<6; ++i) {
393 EXPECT_EQ(a[i], i);
394 }
395 for (int i=0; i<6; ++i) {
396 a[i] = 5*i;
397 }
398 for (int i=0; i<6; ++i) {
399 EXPECT_EQ(a[i], 5*i);
400 }
401}
402
403TEST(AffineTest, Nearness) {
404 Affine a1(1, 0, 1, 2, 1e-8, 1e-8);
405 Affine a2(1+1e-8, 0, 1, 2-1e-8, -1e-8, -1e-8);
406 EXPECT_TRUE(are_near(a1, a2, 1e-7));
407 EXPECT_FALSE(are_near(a1, a2, 1e-9));
408}
409
410TEST(AffineTest, Multiplication) {
411 // test whether noncommutative multiplications work correctly
412 Affine a1 = Scale(0.1), a2 = Translate(10, 10), a3 = Scale(10.0);
413 Affine t1 = Translate(1, 1), t100 = Translate(100, 100);
414 EXPECT_EQ(a1 * a2 * a3, t100);
415 EXPECT_EQ(a3 * a2 * a1, t1);
416}
417
418} // end namespace Geom
419
420/*
421 Local Variables:
422 mode:c++
423 c-file-style:"stroustrup"
424 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
425 indent-tabs-mode:nil
426 fill-column:99
427 End:
428*/
429// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
3x3 affine transformation matrix.
3x3 matrix representing an affine transformation.
Definition affine.h:70
bool isHShear(Coord eps=EPSILON) const
Check whether this matrix represents pure horizontal shearing.
Definition affine.cpp:256
bool isNonzeroScale(Coord eps=EPSILON) const
Check whether this matrix represents pure, nonzero scaling.
Definition affine.cpp:160
bool flips() const
Check whether this transformation flips objects.
Definition affine.cpp:368
bool preservesDistances(Coord eps=EPSILON) const
Check whether the transformation preserves distances between points.
Definition affine.cpp:359
bool preservesAngles(Coord eps=EPSILON) const
Check whether the transformation preserves angles between lines.
Definition affine.cpp:339
bool preservesArea(Coord eps=EPSILON) const
Check whether the transformation preserves areas of polygons.
Definition affine.cpp:321
bool isNonzeroNonpureRotation(Coord eps=EPSILON) const
Check whether this matrix represents a non-zero rotation about any point.
Definition affine.cpp:233
bool isScale(Coord eps=EPSILON) const
Check whether this matrix represents pure scaling.
Definition affine.cpp:147
bool isUniformScale(Coord eps=EPSILON) const
Check whether this matrix represents pure uniform scaling.
Definition affine.cpp:174
bool isNonzeroTranslation(Coord eps=EPSILON) const
Check whether this matrix represents a pure nonzero translation.
Definition affine.cpp:134
bool isNonzeroHShear(Coord eps=EPSILON) const
Check whether this matrix represents pure, nonzero horizontal shearing.
Definition affine.cpp:268
bool isVShear(Coord eps=EPSILON) const
Check whether this matrix represents pure vertical shearing.
Definition affine.cpp:281
bool isSingular(Coord eps=EPSILON) const
Check whether this matrix is singular.
Definition affine.cpp:377
bool isZoom(Coord eps=EPSILON) const
Check whether this matrix represents zooming.
Definition affine.cpp:310
bool isIdentity(Coord eps=EPSILON) const
Check whether this matrix is an identity matrix.
Definition affine.cpp:109
static Affine identity()
bool isNonzeroUniformScale(Coord eps=EPSILON) const
Check whether this matrix represents pure, nonzero uniform scaling.
Definition affine.cpp:189
Point rotationCenter() const
For a (possibly non-pure) non-zero-rotation matrix, calculate the rotation center.
Definition affine.cpp:243
bool isNonzeroVShear(Coord eps=EPSILON) const
Check whether this matrix represents pure, nonzero vertical shearing.
Definition affine.cpp:294
bool isTranslation(Coord eps=EPSILON) const
Check whether this matrix represents a pure translation.
Definition affine.cpp:123
Affine inverse() const
Compute the inverse matrix.
Definition affine.cpp:388
Affine withoutTranslation() const
Definition affine.h:169
bool isRotation(Coord eps=EPSILON) const
Check whether this matrix represents a pure rotation.
Definition affine.cpp:206
bool isNonzeroRotation(Coord eps=EPSILON) const
Check whether this matrix represents a pure, nonzero rotation.
Definition affine.cpp:219
Horizontal shearing.
Definition transforms.h:257
Two-dimensional point that doubles as a vector.
Definition point.h:66
Rotation around the origin.
Definition transforms.h:187
Scaling from the origin.
Definition transforms.h:150
Translation by a vector.
Definition transforms.h:115
Vertical shearing.
Definition transforms.h:274
Combination of a translation and uniform scale.
Definition transforms.h:292
Various utility functions.
Definition affine.h:22
Affine identity()
Create an identity matrix.
Definition affine.h:210
TEST(AffineTest, Equality)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
Affine transformation classes.