summaryrefslogtreecommitdiffstats
path: root/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp
diff options
context:
space:
mode:
authorRhys Weatherley <rhys.weatherley@nokia.com>2009-08-19 03:25:38 (GMT)
committerRhys Weatherley <rhys.weatherley@nokia.com>2009-08-19 03:25:38 (GMT)
commit9e8ff32da0eeaa9dfe03b5ffc123bd6390951494 (patch)
tree0106b57e45688f273aaed07b761876684a3b4a23 /tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp
parentf7af55e67711270286a1addf6a28399982647a62 (diff)
downloadQt-9e8ff32da0eeaa9dfe03b5ffc123bd6390951494.zip
Qt-9e8ff32da0eeaa9dfe03b5ffc123bd6390951494.tar.gz
Qt-9e8ff32da0eeaa9dfe03b5ffc123bd6390951494.tar.bz2
Re-implement QGraphicsTransform to use QMatrix4x4
QTransform-based transformations create problems when performing X and Y axis rotations because they aren't using true 3D. This change modifies QGraphicsTransform and its sub-classes to use QMatrix4x4 as the standard transformation matrix, with a project() function to project back to 2D when required. Reviewed-by: trustme
Diffstat (limited to 'tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp')
-rw-r--r--tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp141
1 files changed, 109 insertions, 32 deletions
diff --git a/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp b/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp
index bfd346b..029c182 100644
--- a/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp
+++ b/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp
@@ -84,60 +84,131 @@ void tst_QGraphicsTransform::cleanup()
{
}
+static QTransform transform2D(const QGraphicsTransform& t)
+{
+ QMatrix4x4 m;
+ t.applyTo(&m);
+ return QGraphicsTransform::project(m);
+}
void tst_QGraphicsTransform::scale()
{
QGraphicsScale scale;
- scale.setOrigin(QPointF(10, 10));
- QTransform t;
+ // check initial conditions
+ QCOMPARE(scale.xScale(), qreal(1));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(0, 0, 0));
+
+ scale.setOrigin(QVector3D(10, 10, 0));
+
+ QCOMPARE(scale.xScale(), qreal(1));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(10, 10, 0));
+
+ QMatrix4x4 t;
scale.applyTo(&t);
- QCOMPARE(t, QTransform());
- QCOMPARE(scale.transform(), QTransform());
+ QCOMPARE(t, QMatrix4x4());
+ QCOMPARE(transform2D(scale), QTransform());
scale.setXScale(10);
- scale.setOrigin(QPointF(0, 0));
+ scale.setOrigin(QVector3D(0, 0, 0));
+
+ QCOMPARE(scale.xScale(), qreal(10));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(0, 0, 0));
QTransform res;
res.scale(10, 1);
- QCOMPARE(scale.transform(), res);
- QCOMPARE(scale.transform().map(QPointF(10, 10)), QPointF(100, 10));
+ QCOMPARE(transform2D(scale), res);
+ QCOMPARE(transform2D(scale).map(QPointF(10, 10)), QPointF(100, 10));
+
+ scale.setOrigin(QVector3D(10, 10, 0));
+ QCOMPARE(transform2D(scale).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(transform2D(scale).map(QPointF(11, 10)), QPointF(20, 10));
+
+ scale.setYScale(2);
+ scale.setZScale(4.5);
+ scale.setOrigin(QVector3D(1, 2, 3));
+
+ QCOMPARE(scale.xScale(), qreal(10));
+ QCOMPARE(scale.yScale(), qreal(2));
+ QCOMPARE(scale.zScale(), qreal(4.5));
+ QCOMPARE(scale.origin(), QVector3D(1, 2, 3));
+
+ QMatrix4x4 t2;
+ scale.applyTo(&t2);
- scale.setOrigin(QPointF(10, 10));
- QCOMPARE(scale.transform().map(QPointF(10, 10)), QPointF(10, 10));
- QCOMPARE(scale.transform().map(QPointF(11, 10)), QPointF(20, 10));
+ QCOMPARE(t2.map(QVector3D(4, 5, 6)), QVector3D(31, 8, 16.5));
+
+ // Because the origin has a non-zero z, mapping (4, 5) in 2D
+ // will introduce a projective component into the result.
+ QTransform t3 = QGraphicsTransform::project(t2);
+ QCOMPARE(t3.map(QPointF(4, 5)), QPointF(31 / t3.m33(), 8 / t3.m33()));
+}
+
+// QMatrix4x4 uses float internally, whereas QTransform uses qreal.
+// This can lead to issues with qFuzzyCompare() where it uses double
+// precision to compare values that have no more than float precision
+// after conversion from QMatrix4x4 to QTransform. The following
+// definitions correct for the difference.
+static inline bool fuzzyCompare(qreal p1, qreal p2)
+{
+ return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
+}
+static bool fuzzyCompare(const QTransform& t1, const QTransform& t2)
+{
+ return fuzzyCompare(t1.m11(), t2.m11()) &&
+ fuzzyCompare(t1.m12(), t2.m12()) &&
+ fuzzyCompare(t1.m13(), t2.m13()) &&
+ fuzzyCompare(t1.m21(), t2.m21()) &&
+ fuzzyCompare(t1.m22(), t2.m22()) &&
+ fuzzyCompare(t1.m23(), t2.m23()) &&
+ fuzzyCompare(t1.m31(), t2.m31()) &&
+ fuzzyCompare(t1.m32(), t2.m32()) &&
+ fuzzyCompare(t1.m33(), t2.m33());
}
void tst_QGraphicsTransform::rotation()
{
QGraphicsRotation rotation;
- QCOMPARE(rotation.axis().x(), (qreal)0);
- QCOMPARE(rotation.axis().y(), (qreal)0);
- QCOMPARE(rotation.axis().z(), (qreal)1);
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(0, 0, 0));
QCOMPARE(rotation.angle(), (qreal)0);
- rotation.setOrigin(QPointF(10, 10));
+ rotation.setOrigin(QVector3D(10, 10, 0));
+
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(10, 10, 0));
+ QCOMPARE(rotation.angle(), (qreal)0);
- QTransform t;
+ QMatrix4x4 t;
rotation.applyTo(&t);
- QCOMPARE(t, QTransform());
- QCOMPARE(rotation.transform(), QTransform());
+ QCOMPARE(t, QMatrix4x4());
+ QCOMPARE(transform2D(rotation), QTransform());
rotation.setAngle(40);
- rotation.setOrigin(QPointF(0, 0));
+ rotation.setOrigin(QVector3D(0, 0, 0));
+
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(0, 0, 0));
+ QCOMPARE(rotation.angle(), (qreal)40);
QTransform res;
res.rotate(40);
- QCOMPARE(rotation.transform(), res);
+ QVERIFY(fuzzyCompare(transform2D(rotation), res));
- rotation.setOrigin(QPointF(10, 10));
+ rotation.setOrigin(QVector3D(10, 10, 0));
rotation.setAngle(90);
- QCOMPARE(rotation.transform().map(QPointF(10, 10)), QPointF(10, 10));
- QCOMPARE(rotation.transform().map(QPointF(20, 10)), QPointF(10, 20));
+ QCOMPARE(transform2D(rotation).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(transform2D(rotation).map(QPointF(20, 10)), QPointF(10, 20));
}
Q_DECLARE_METATYPE(Qt::Axis);
@@ -161,38 +232,44 @@ void tst_QGraphicsTransform::rotation3d()
QGraphicsRotation rotation;
rotation.setAxis(axis);
- QTransform t;
+ QMatrix4x4 t;
rotation.applyTo(&t);
QVERIFY(t.isIdentity());
- QVERIFY(rotation.transform().isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
rotation.setAngle(angle);
+ // QGraphicsRotation uses a correct mathematical rotation in 3D.
+ // QTransform's Qt::YAxis rotation is inverted from the mathematical
+ // version of rotation. We correct for that here.
QTransform expected;
- expected.rotate(angle, axis);
+ if (axis == Qt::YAxis && angle != 180.)
+ expected.rotate(-angle, axis);
+ else
+ expected.rotate(angle, axis);
- QVERIFY(qFuzzyCompare(rotation.transform(), expected));
+ QVERIFY(fuzzyCompare(transform2D(rotation), expected));
//now let's check that a null vector will not change the transform
rotation.setAxis(QVector3D(0, 0, 0));
- rotation.setOrigin(QPointF(10, 10));
+ rotation.setOrigin(QVector3D(10, 10, 0));
- t.reset();
+ t.setIdentity();
rotation.applyTo(&t);
QVERIFY(t.isIdentity());
- QVERIFY(rotation.transform().isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
rotation.setAngle(angle);
QVERIFY(t.isIdentity());
- QVERIFY(rotation.transform().isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
- rotation.setOrigin(QPointF(0, 0));
+ rotation.setOrigin(QVector3D(0, 0, 0));
QVERIFY(t.isIdentity());
- QVERIFY(rotation.transform().isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
}
be691a23a4d2898fa15e'>tests/teapot.ppm
blob: b8ab85f3a5d23e6d7d866f9d6aba9723f988ffce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
P6
256 256
255
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\[7 eOLjQLmSMoTMnSMlRMhPL_9 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\nSMtVMzYN~[N~[N\N\O\O]O]O]O]O\O\O}[NyYNtVM\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\G-wXN}[N]O^O_O`O`O`O`OaOaOaOaOaOaOaOaO`O_O^O\N\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\aMLyYN_OaPbPcPcPdPdPdPdPdPdPdPdPdPePePePePePdPcP_OpUM\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\wXN_OdPfPgQhQhQiQiQiQiQiQjQjQjQjQjQjQjQjQjQjQiQfP`O\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\NCJiQLbPhQkQmRnRoRoRoRoRoRoRoRoRpRpSqSqSrSrSrSqSoRjQ]O\KK\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\fOLrUMcPlRqStSuTwTxTxTyTyTzTzUzUzUzUzUyTxTwTtSmRaOhPL\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\a0	cNLqUM\OfQpSwVzV|V}VVVǀVɂW̅[ՏewꪅĈgqTfQ{ZNYIK9\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\O1{G#JkRMqUMtVNiSv\dbzZvUuTsSqSnRjQeP^OrUMHh>!T4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\G-V5wE"~I#M%U+e7l:g2b*a(`(^(])^-]1S,qC$`9 R3G-\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\@)J/i>!pA"tD"wF$yH&xH&tE$wE#yG%}M+T4S5mE*Z7!K/B*;'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\aOoR{UǀVυX<(F-a: e<!h>!j@#k@$h>"d<!c=$hD-fF2[<)K0@);'5$˂VǀV|U_LKYIK\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\_OxTɂW֒k|X>f-^(Z'W&T&N>)F-J/b; g>#nD(jB&c<!b=%jH2_A/I0!<(8&5$JYS%8&;'?)E,<:HA=HE?IJAISFJYIKXIK\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\nR}UܘqʊevUe,V&VC
@|>y<u:r9o7l6
j5
h4
g3
5$D,K/b; h>"wM1tK.e="a<#cA,U8&E-<(9&.!a0	b1	c1				

+3#@)46G<:HMCIXHK\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\U*vT~X{Yk+W&N$|>u:p8k5
f3
a0	_/	].	[-	I\*_(LkRMmSMmSMnSMnSMD,R3W5mA"|O0|P1j?"c<!a=%Y7"N1F,;'NCJNCJNDJODJODJODJh>!a: X/K%