klayout/src/unit_tests/dbMatrix.cc

633 lines
26 KiB
C++
Raw Normal View History

/*
KLayout Layout Viewer
Copyright (C) 2006-2016 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dbMatrix.h"
#include "dbTrans.h"
#include "utHead.h"
TEST(1)
{
db::Matrix2d m1;
EXPECT_EQ (m1.to_string (), "(0,0) (0,0)");
EXPECT_EQ (tl::to_string (m1.is_ortho ()), "true");
m1 = db::Matrix2d (1, 2, 3, 4);
EXPECT_EQ (m1.to_string (), "(1,2) (3,4)");
EXPECT_EQ (tl::to_string (m1.is_ortho ()), "false");
EXPECT_EQ (m1.det (), -2);
EXPECT_EQ (m1.m11 (), 1);
EXPECT_EQ (m1.m12 (), 2);
EXPECT_EQ (m1.m21 (), 3);
EXPECT_EQ (m1.m22 (), 4);
db::Matrix2d m2 (5.0);
EXPECT_EQ (m2.to_string (), "(5,0) (0,5)");
EXPECT_EQ ((m2 + m1).to_string (), "(6,2) (3,9)");
m2 += m1;
EXPECT_EQ (m2.to_string (), "(6,2) (3,9)");
EXPECT_EQ ((m1 * m2).to_string (), "(12,20) (30,42)");
m1 *= m2;
EXPECT_EQ (m1.to_string (), "(12,20) (30,42)");
EXPECT_EQ ((m1 * 0.5).to_string (), "(6,10) (15,21)");
m1 *= 0.5;
EXPECT_EQ (m1.to_string (), "(6,10) (15,21)");
EXPECT_EQ ((m1 * db::DVector (1, 2)).to_string (), "26,57");
EXPECT_EQ ((m1.transposed ()).to_string (), "(6,15) (10,21)");
m1.transpose ();
EXPECT_EQ (m1.to_string (), "(6,15) (10,21)");
EXPECT_EQ (fabs ((m1 * m1.inverted ()).m11 () - 1.0) < 1e-15, true);
EXPECT_EQ (fabs ((m1 * m1.inverted ()).m12 ()) < 1e-15, true);
EXPECT_EQ (fabs ((m1 * m1.inverted ()).m21 ()) < 1e-15, true);
EXPECT_EQ (fabs ((m1 * m1.inverted ()).m22 () - 1.0) < 1e-15, true);
db::Matrix2d m1s = m1;
m1.invert ();
EXPECT_EQ (fabs ((m1 * m1s).m11 () - 1.0) < 1e-15, true);
EXPECT_EQ (fabs ((m1 * m1s).m12 ()) < 1e-15, true);
EXPECT_EQ (fabs ((m1 * m1s).m21 ()) < 1e-15, true);
EXPECT_EQ (fabs ((m1 * m1s).m22 () - 1.0) < 1e-15, true);
EXPECT_EQ (fabs ((m1s * m1).m11 () - 1.0) < 1e-15, true);
EXPECT_EQ (fabs ((m1s * m1).m12 ()) < 1e-15, true);
EXPECT_EQ (fabs ((m1s * m1).m21 ()) < 1e-15, true);
EXPECT_EQ (fabs ((m1s * m1).m22 () - 1.0) < 1e-15, true);
db::CplxTrans t (2.0, 90.0, false, db::DVector ());
EXPECT_EQ (fabs (db::Matrix2d (t).m11 ()) < 1e-15, true);
EXPECT_EQ (fabs (db::Matrix2d (t).m12 () + 2.0) < 1e-15, true);
EXPECT_EQ (fabs (db::Matrix2d (t).m21 () - 2.0) < 1e-15, true);
EXPECT_EQ (fabs (db::Matrix2d (t).m22 ()) < 1e-15, true);
// Base transformations and decomposition
EXPECT_EQ (tl::to_string (db::Matrix2d (1.0).mag_x ()), "1");
EXPECT_EQ (tl::to_string (db::Matrix2d (1.0).mag_y ()), "1");
EXPECT_EQ (tl::to_string (db::Matrix2d (1.0).is_mirror ()), "false");
EXPECT_EQ (tl::to_string (db::Matrix2d (1.0).angle ()), "0");
EXPECT_EQ (tl::to_string (db::Matrix2d (1.0).shear_angle ()), "0");
EXPECT_EQ (tl::to_string (db::Matrix2d (1.0).has_shear ()), "false");
EXPECT_EQ (tl::to_string (db::Matrix2d::mag (17.5).mag_x ()), "17.5");
EXPECT_EQ (tl::to_string (db::Matrix2d::mag (17.5).mag_x ()), "17.5");
EXPECT_EQ (tl::to_string (db::Matrix2d::mag (17.5).shear_angle ()), "0");
EXPECT_EQ (tl::to_string (db::Matrix2d::mag (17.5).angle ()), "0");
EXPECT_EQ (tl::to_string (db::Matrix2d::mag (17.5).is_mirror ()), "false");
EXPECT_EQ (tl::to_string (db::Matrix2d::mirror (true).is_mirror ()), "true");
EXPECT_EQ (tl::to_string (db::Matrix2d::mirror (false).is_mirror ()), "false");
EXPECT_EQ (tl::to_string (db::Matrix2d::mirror (true).shear_angle ()), "0");
EXPECT_EQ (tl::to_string (db::Matrix2d::mirror (true).angle ()), "0");
EXPECT_EQ (tl::to_string (db::Matrix2d::rotation (25).angle ()), "25");
EXPECT_EQ (tl::to_string (db::Matrix2d::rotation (-25).angle ()), "-25");
EXPECT_EQ (tl::to_string (db::Matrix2d::rotation (115).angle ()), "115");
EXPECT_EQ (tl::to_string (db::Matrix2d::rotation (-115).angle ()), "-115");
EXPECT_EQ (tl::to_string (1e-6 * floor (0.5 + 1e6 * db::Matrix2d::rotation (-115).shear_angle ())), "0");
EXPECT_EQ (tl::to_string (db::Matrix2d::shear (17).shear_angle ()), "17");
EXPECT_EQ (tl::to_string (1e-6 * floor (0.5 + 1e6 * db::Matrix2d::shear (17).angle ())), "0");
EXPECT_EQ (tl::to_string (db::Matrix2d::shear (17).mag_x ()), "1");
EXPECT_EQ (tl::to_string (db::Matrix2d::shear (17).mag_y ()), "1");
EXPECT_EQ (tl::to_string (db::Matrix2d::shear (17).has_shear ()), "true");
EXPECT_EQ (tl::to_string (db::Matrix2d::shear (40).shear_angle ()), "40");
EXPECT_EQ (tl::to_string (db::Matrix2d::shear (-40).shear_angle ()), "-40");
EXPECT_EQ (tl::to_string (1.0 / db::Matrix2d::mag (17.5).inverted ().mag ().first), "17.5");
EXPECT_EQ (tl::to_string (1.0 / db::Matrix2d::mag (17.5).inverted ().mag ().second), "17.5");
EXPECT_EQ (tl::to_string (1.0 / db::Matrix2d::mag (27.5, 7.5).inverted ().mag ().first), "27.5");
EXPECT_EQ (tl::to_string (1.0 / db::Matrix2d::mag (27.5, 7.5).inverted ().mag ().second), "7.5");
EXPECT_EQ (tl::to_string (db::Matrix2d::mirror (true).inverted ().is_mirror ()), "true");
EXPECT_EQ (tl::to_string (db::Matrix2d::mirror (false).inverted ().is_mirror ()), "false");
EXPECT_EQ (tl::to_string (db::Matrix2d::rotation (25).inverted ().angle ()), "-25");
EXPECT_EQ (tl::to_string (db::Matrix2d::shear (17).inverted ().shear_angle ()), "-17");
db::Matrix2d m = db::Matrix2d::rotation (25) * (db::Matrix2d::shear (17) * (db::Matrix2d::mirror (true) * db::Matrix2d::mag (7.5, 27.5)));
EXPECT_EQ (tl::to_string (m.mag_x ()), "7.5");
EXPECT_EQ (tl::to_string (m.mag_y ()), "27.5");
EXPECT_EQ (tl::to_string (m.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m.angle ()), "25");
EXPECT_EQ (tl::to_string (m.shear_angle ()), "17");
m = db::Matrix2d::rotation (-25) * (db::Matrix2d::shear (-17) * (db::Matrix2d::mirror (true) * db::Matrix2d::mag (27.5, 7.5)));
EXPECT_EQ (tl::to_string (m.mag_x ()), "27.5");
EXPECT_EQ (tl::to_string (m.mag_y ()), "7.5");
EXPECT_EQ (tl::to_string (m.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m.angle ()), "-25");
EXPECT_EQ (tl::to_string (m.shear_angle ()), "-17");
}
TEST(2)
{
db::Matrix2d m (1.0, 0.0, 0.0, 1.0);
db::DVector d;
std::vector<db::DPoint> p, q;
p.push_back (db::DPoint (1, 2));
q.push_back (db::DPoint (2, 4));
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Displacement);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1,2");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Displacement);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1,2");
// one more point
p.clear (); q.clear ();
p.push_back (db::DPoint (1, 2));
p.push_back (db::DPoint (2, 3));
q.push_back (db::DPoint (2, 4));
q.push_back (db::DPoint (4, 6));
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Displacement);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1.5,2.5");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Displacement);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1.5,2.5");
// once again with focus on the first points
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Displacement, 0);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1,2");
// .. and on the second
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Displacement, 1);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "2,3");
}
TEST(3)
{
db::Matrix2d m (1.0, 0.0, 0.0, 1.0);
db::DVector d;
std::vector<db::DPoint> p, q;
p.push_back (db::DPoint (1, 2));
p.push_back (db::DPoint (2, 2));
q.push_back (db::DPoint (2, 4));
q.push_back (db::DPoint (2, 6));
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Rotation);
EXPECT_EQ (m.to_string (), "(0,-1) (1,0)");
EXPECT_EQ (tl::to_string (m.is_ortho ()), "true");
EXPECT_EQ (d.to_string (), "4,3.5");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Rotation);
EXPECT_EQ (m.to_string (), "(0,-1) (1,0)");
EXPECT_EQ (d.to_string (), "4,3.5");
// once again with focus on the first point
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Rotation, 0);
EXPECT_EQ (m.to_string (), "(0,-1) (1,0)");
EXPECT_EQ (d.to_string (), "4,3");
// .. and on the second
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Rotation, 1);
EXPECT_EQ (m.to_string (), "(0,-1) (1,0)");
EXPECT_EQ (d.to_string (), "4,4");
// Degenerated
m = db::Matrix2d (1.0, 0.0, 0.0, 1.0);
d = db::DVector ();
p.clear (); q.clear ();
p.push_back (db::DPoint (1, 2));
p.push_back (db::DPoint (1, 2));
q.push_back (db::DPoint (2, 4));
q.push_back (db::DPoint (2, 4));
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Rotation);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1,2");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Rotation);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1,2");
p.clear (); q.clear ();
p.push_back (db::DPoint (1, 2));
p.push_back (db::DPoint (1, 2));
q.push_back (db::DPoint (2, 4));
q.push_back (db::DPoint (2, 5));
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Rotation);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1,2.5");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Rotation);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1,2.5");
p.clear (); q.clear ();
p.push_back (db::DPoint (1, 2));
p.push_back (db::DPoint (1, 3));
q.push_back (db::DPoint (2, 4));
q.push_back (db::DPoint (2, 4));
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Rotation);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1,1.5");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Rotation);
EXPECT_EQ (m.to_string (), "(1,0) (0,1)");
EXPECT_EQ (d.to_string (), "1,1.5");
}
TEST(4)
{
db::Matrix2d m (1.0, 0.0, 0.0, 1.0);
db::DVector d;
std::vector<db::DPoint> p, q;
p.push_back (db::DPoint (3, 6));
p.push_back (db::DPoint (6, 6));
p.push_back (db::DPoint (3, 9));
q.push_back (db::DPoint (6, 12));
q.push_back (db::DPoint (6, 18));
q.push_back (db::DPoint (0, 12));
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::RotationMirror);
EXPECT_EQ (m.to_string (), "(0,-1) (1,0)");
EXPECT_EQ (d.to_string (), "11,10");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::RotationMirror);
EXPECT_EQ (m.to_string (), "(0,-1) (1,0)");
EXPECT_EQ (d.to_string (), "11,10");
// once again with focus on the first point
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::RotationMirror, 0);
EXPECT_EQ (m.to_string (), "(0,-1) (1,0)");
EXPECT_EQ (d.to_string (), "12,9");
// .. and on the second
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::RotationMirror, 2);
EXPECT_EQ (m.to_string (), "(0,-1) (1,0)");
EXPECT_EQ (d.to_string (), "9,9");
m = db::Matrix2d (1.0, 0.0, 0.0, 1.0);
d = db::DVector ();
p.clear (); q.clear ();
p.push_back (db::DPoint (3, 6));
p.push_back (db::DPoint (6, 6));
p.push_back (db::DPoint (3, 3));
q.push_back (db::DPoint (6, 12));
q.push_back (db::DPoint (6, 18));
q.push_back (db::DPoint (0, 12));
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::RotationMirror);
EXPECT_EQ (m.to_string (), "(0,1) (1,0)");
EXPECT_EQ (d.to_string (), "-1,10");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::RotationMirror);
EXPECT_EQ (m.to_string (), "(0,1) (1,0)");
EXPECT_EQ (d.to_string (), "-1,10");
// once again with focus on the first point
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::RotationMirror, 0);
EXPECT_EQ (m.to_string (), "(0,1) (1,0)");
EXPECT_EQ (d.to_string (), "0,9");
// .. and on the second
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::RotationMirror, 2);
EXPECT_EQ (m.to_string (), "(0,1) (1,0)");
EXPECT_EQ (d.to_string (), "-3,9");
// special case of axis normalization:
m = db::Matrix2d (1.0, 0.0, 0.0, 1.0);
d = db::DVector ();
p.clear (); q.clear ();
p.push_back (db::DPoint (3, 6));
p.push_back (db::DPoint (7, 6));
p.push_back (db::DPoint (3, 7));
q.push_back (db::DPoint (6, 12));
q.push_back (db::DPoint (6, 17));
q.push_back (db::DPoint (1, 12));
// once again with focus on the first point
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::RotationMirror, 0);
EXPECT_EQ (m.to_string (), "(0,-1) (1,0)");
EXPECT_EQ (d.to_string (), "12,9");
}
TEST(5)
{
db::Matrix2d m (1.0, 0.0, 0.0, 1.0);
db::DVector d;
std::vector<db::DPoint> p, q;
p.push_back (db::DPoint (3, 6));
p.push_back (db::DPoint (6, 6));
p.push_back (db::DPoint (3, 9));
q.push_back (db::DPoint (6, 12));
q.push_back (db::DPoint (6, 18));
q.push_back (db::DPoint (0, 12));
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Magnification);
EXPECT_EQ (m.to_string (), "(0,-2) (2,0)");
EXPECT_EQ (d.to_string (), "18,6");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Magnification);
EXPECT_EQ (m.to_string (), "(0,-2) (2,0)");
EXPECT_EQ (d.to_string (), "18,6");
// once again with focus on the first point
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Magnification, 0);
EXPECT_EQ (m.to_string (), "(0,-2) (2,0)");
EXPECT_EQ (d.to_string (), "18,6");
// .. and on the second
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::Magnification, 2);
EXPECT_EQ (m.to_string (), "(0,-2) (2,0)");
EXPECT_EQ (d.to_string (), "18,6");
}
TEST(6)
{
db::Matrix2d m (1.0, 0.0, 0.0, 1.0);
db::DVector d;
std::vector<db::DPoint> p, q;
p.push_back (db::DPoint (3, 6));
p.push_back (db::DPoint (6, 6));
p.push_back (db::DPoint (3, 9));
p.push_back (db::DPoint (6, 9));
q.push_back (db::DPoint (6, 12));
q.push_back (db::DPoint (6, 18));
q.push_back (db::DPoint (0, 12));
q.push_back (db::DPoint (0, 18));
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::All);
EXPECT_EQ (m.to_string (), "(0,-2) (2,0)");
EXPECT_EQ (d.to_string (), "18,6");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::All);
EXPECT_EQ (m.to_string (), "(0,-2) (2,0)");
EXPECT_EQ (d.to_string (), "18,6");
// once again with focus on the first point
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::All, 0);
EXPECT_EQ (m.to_string (), "(0,-2) (2,0)");
EXPECT_EQ (d.to_string (), "18,6");
// .. and on the second
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::All, 2);
EXPECT_EQ (m.to_string (), "(0,-2) (2,0)");
EXPECT_EQ (d.to_string (), "18,6");
db::Matrix2d n = db::Matrix2d::rotation (-25) * (db::Matrix2d::shear (-17) * (db::Matrix2d::mirror (true) * db::Matrix2d::mag (17.5, 7.5)));
db::DVector dd (0.5, -1);
p.clear (); q.clear ();
p.push_back (db::DPoint (0, 0));
p.push_back (db::DPoint (1, 0));
p.push_back (db::DPoint (0, 1));
p.push_back (db::DPoint (1, 1));
q.push_back (n * p[0] + dd);
q.push_back (n * p[1] + dd);
q.push_back (n * p[2] + dd);
q.push_back (n * p[3] + dd);
m = db::Matrix2d (1.0, 0.0, 0.0, 1.0);
d = db::DVector ();
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::All);
EXPECT_EQ (tl::to_string (m.is_ortho ()), "false");
EXPECT_EQ (tl::to_string (m.shear_angle ()), "-17");
EXPECT_EQ (tl::to_string (m.has_shear ()), "true");
EXPECT_EQ (tl::to_string (m.angle ()), "-25");
EXPECT_EQ (tl::to_string (m.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m.mag_x ()), "17.5");
EXPECT_EQ (tl::to_string (m.mag_y ()), "7.5");
EXPECT_EQ (d.to_string (), "0.5,-1");
// once again with the previous transformation as the initial one
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::All);
EXPECT_EQ (tl::to_string (m.shear_angle ()), "-17");
EXPECT_EQ (tl::to_string (m.angle ()), "-25");
EXPECT_EQ (tl::to_string (m.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m.mag_x ()), "17.5");
EXPECT_EQ (tl::to_string (m.mag_y ()), "7.5");
EXPECT_EQ (d.to_string (), "0.5,-1");
// once again with focus on the first point
adjust_matrix (m, d, p, q, db::MatrixAdjustFlags::All, 0);
EXPECT_EQ (tl::to_string (m.shear_angle ()), "-17");
EXPECT_EQ (tl::to_string (m.angle ()), "-25");
EXPECT_EQ (tl::to_string (m.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m.mag_x ()), "17.5");
EXPECT_EQ (tl::to_string (m.mag_y ()), "7.5");
EXPECT_EQ (d.to_string (), "0.5,-1");
m = db::Matrix2d (1, 5, 3, 9);
db::Matrix2d mm = db::Matrix2d::rotation (m.angle ()) * db::Matrix2d::shear (m.shear_angle ()) * db::Matrix2d::mag (m.mag_x (), m.mag_y ()) * db::Matrix2d::mirror (m.is_mirror ());
EXPECT_EQ (mm.to_string (), "(1,5) (3,9)");
}
TEST(7)
{
db::CplxTrans t (1.5, 45.0, true, db::DVector (10, -20));
EXPECT_EQ (tl::to_string (db::Matrix3d (t).angle ()), "45");
EXPECT_EQ (tl::to_string (db::Matrix3d (t).is_mirror ()), "true");
EXPECT_EQ (tl::to_string (db::Matrix3d (t).mag_x ()), "1.5");
EXPECT_EQ (tl::to_string (db::Matrix3d (t).mag_y ()), "1.5");
EXPECT_EQ (tl::to_string (db::Matrix3d (t).disp ().x ()), "10");
EXPECT_EQ (tl::to_string (db::Matrix3d (t).disp ().y ()), "-20");
db::Matrix3d m;
m = db::Matrix3d (2.0);
EXPECT_EQ (tl::to_string (m.is_ortho ()), "true");
EXPECT_EQ (m.to_string (), "(2,0,0) (0,2,0) (0,0,1)");
EXPECT_EQ (m.inverted ().to_string (), "(0.5,0,0) (0,0.5,0) (0,0,1)");
m = db::Matrix3d ();
EXPECT_EQ (m.to_string (), "(0,0,0) (0,0,0) (0,0,0)");
m = db::Matrix3d (2.0, 0.0, 0.0, 3.0);
EXPECT_EQ (m.to_string (), "(2,0,0) (0,3,0) (0,0,1)");
m = db::Matrix3d::rotation (90.0);
EXPECT_EQ (m.to_string (), "(0,-1,0) (1,0,0) (0,0,1)");
EXPECT_EQ (tl::to_string (m.is_ortho ()), "true");
m = db::Matrix3d::perspective (45.0, 0.0, 1.0);
EXPECT_EQ (m.to_string (), "(1,0,0) (0,1,0) (1,0,1)");
m = db::Matrix3d (1, 2, 3, 4, 2, 1, 1, 2, 5);
EXPECT_EQ ((m * (m.inverted () * m)).to_string (), "(1,2,3) (4,2,1) (1,2,5)");
m = db::Matrix3d::perspective (18, -5, 1);
EXPECT_EQ (tl::to_string (m.is_ortho ()), "false");
EXPECT_EQ (tl::to_string (m.perspective_tilt_x (1)), "18");
EXPECT_EQ (tl::to_string (m.perspective_tilt_y (1)), "-5");
m = db::Matrix3d::disp (db::DVector (-5, 3)) * db::Matrix3d::perspective (18, -5, 1);
EXPECT_EQ (tl::to_string (m.is_ortho ()), "false");
EXPECT_EQ (tl::to_string (m.perspective_tilt_x (1)), "18");
EXPECT_EQ (tl::to_string (m.perspective_tilt_y (1)), "-5");
m = db::Matrix3d::disp (db::DVector (-5, 3)) * db::Matrix3d::perspective (18, -5, 1.5);
EXPECT_EQ (tl::to_string (m.is_ortho ()), "false");
EXPECT_EQ (tl::to_string (m.perspective_tilt_x (1.5)), "18");
EXPECT_EQ (tl::to_string (m.perspective_tilt_y (1.5)), "-5");
m = db::Matrix3d::disp (db::DVector (-5, 3)) * db::Matrix3d::perspective (18, -5, 1) * db::Matrix3d::rotation (33) * db::Matrix3d::shear (21) * db::Matrix3d::mag (2.5) * db::Matrix3d::mirror (true);
EXPECT_EQ (tl::to_string (m.is_ortho ()), "false");
EXPECT_EQ (tl::to_string (m.perspective_tilt_x (1)), "18");
EXPECT_EQ (tl::to_string (m.perspective_tilt_y (1)), "-5");
EXPECT_EQ (m.disp ().to_string (), "-5,3");
EXPECT_EQ (tl::to_string (m.shear_angle ()), "21");
EXPECT_EQ (tl::to_string (m.has_shear ()), "true");
EXPECT_EQ (tl::to_string (m.mag_x ()), "2.5");
EXPECT_EQ (tl::to_string (m.mag_y ()), "2.5");
EXPECT_EQ (tl::to_string (m.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m.angle ()), "33");
m = db::Matrix3d (1, 5, 0, 3, 9, 0, 0, 0, 1);
db::Matrix3d mm = db::Matrix3d::rotation (m.angle ()) * db::Matrix3d::shear (m.shear_angle ()) * db::Matrix3d::mag (m.mag_x (), m.mag_y ()) * db::Matrix3d::mirror (m.is_mirror ());
EXPECT_EQ (mm.to_string (), "(1,5,0) (3,9,0) (0,0,1)");
m = db::Matrix3d (1, 5, 3, 3, 9, 4, 6, 1, 1);
mm = db::Matrix3d::disp (m.disp ()) * db::Matrix3d::perspective (m.perspective_tilt_x (1), m.perspective_tilt_y (1), 1) * db::Matrix3d::rotation (m.angle ()) * db::Matrix3d::shear (m.shear_angle ()) * db::Matrix3d::mag (m.mag_x (), m.mag_y ()) * db::Matrix3d::mirror (m.is_mirror ());
// TODO: why does it need normalization?
mm *= 1.0 / mm.m ()[2][2];
EXPECT_EQ (mm.to_string (), "(1,5,3) (3,9,4) (6,1,1)");
}
TEST(7a)
{
db::Matrix3d m (0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);
EXPECT_EQ (m.inverted ().to_string (), "(0,1,0) (1,0,0) (0,0,1)");
}
TEST(7b)
{
db::Matrix3d m (0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0);
EXPECT_EQ (m.inverted ().to_string (), "(0,-1,0) (1,0,0) (0,0,1)");
}
TEST(7c)
{
db::Matrix3d m (0.5, 1.0, 0.75, -1.0, 0.25, -0.25, -0.5, 0.0, 2.0);
db::DPoint p0 (1.0, -1.75);
db::DPoint p1 (-0.5, 1);
EXPECT_EQ (m.can_transform (db::DPoint (4.0, 0.0)), false);
EXPECT_EQ (m.can_transform (db::DPoint (4.0, 1.0)), false);
EXPECT_EQ (m.can_transform (db::DPoint (3.9, 0.0)), true);
EXPECT_EQ (m.can_transform (db::DPoint (3.9, 1.0)), true);
EXPECT_EQ (m.can_transform (db::DPoint (4.1, 0.0)), false);
EXPECT_EQ (m.can_transform (db::DPoint (4.1, 1.0)), false);
db::DVector v1 (m * p1 - m * p0);
v1 *= 1.0 / v1.double_length ();
db::DVector v2 (m.trans (p0, db::DVector (p1 - p0)));
v2 *= 1.0 / v2.double_length ();
EXPECT_EQ (v1.to_string (), v2.to_string ());
}
TEST(8)
{
db::Matrix3d n = db::Matrix3d::disp (db::DVector (-5, 3)) * db::Matrix3d::perspective (18, -5, 1) * db::Matrix3d::rotation (33) * db::Matrix3d::shear (21) * db::Matrix3d::mag (2.5) * db::Matrix3d::mirror (true);
std::vector<db::DPoint> p, q;
p.push_back (db::DPoint (0, 0));
p.push_back (db::DPoint (1, 0));
p.push_back (db::DPoint (0, 1));
p.push_back (db::DPoint (1, 1));
p.push_back (db::DPoint (1, 2));
p.push_back (db::DPoint (2, 1));
q.push_back (n * p[0]);
q.push_back (n * p[1]);
q.push_back (n * p[2]);
q.push_back (n * p[3]);
q.push_back (n * p[4]);
q.push_back (n * p[5]);
db::Matrix3d m (1.0);
EXPECT_EQ (tl::to_string (m.shear_angle ()), "0");
EXPECT_EQ (tl::to_string (m.has_shear ()), "false");
adjust_matrix (m, p, q, db::MatrixAdjustFlags::All);
EXPECT_EQ (tl::to_string (m.perspective_tilt_x (1)), "18");
EXPECT_EQ (tl::to_string (m.perspective_tilt_y (1)), "-5");
EXPECT_EQ (tl::to_string (m.shear_angle ()), "21");
EXPECT_EQ (tl::to_string (m.angle ()), "33");
EXPECT_EQ (tl::to_string (m.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m.mag_x ()), "2.5");
EXPECT_EQ (tl::to_string (m.mag_y ()), "2.5");
EXPECT_EQ (m.disp ().to_string (), "-5,3");
// once again with the previous transformation as the initial one
m = db::Matrix3d (1.0);
adjust_matrix (m, p, q, db::MatrixAdjustFlags::All);
EXPECT_EQ (tl::to_string (m.perspective_tilt_x (1)), "18");
EXPECT_EQ (tl::to_string (m.perspective_tilt_y (1)), "-5");
EXPECT_EQ (tl::to_string (m.shear_angle ()), "21");
EXPECT_EQ (tl::to_string (m.angle ()), "33");
EXPECT_EQ (tl::to_string (m.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m.mag_x ()), "2.5");
EXPECT_EQ (tl::to_string (m.mag_y ()), "2.5");
EXPECT_EQ (m.disp ().to_string (), "-5,3");
// once again with focus on the first point
m = db::Matrix3d (1.0);
adjust_matrix (m, p, q, db::MatrixAdjustFlags::All, 1);
EXPECT_EQ (tl::to_string (m.perspective_tilt_x (1)), "18");
EXPECT_EQ (tl::to_string (m.perspective_tilt_y (1)), "-5");
EXPECT_EQ (tl::to_string (m.shear_angle ()), "21");
EXPECT_EQ (tl::to_string (m.angle ()), "33");
EXPECT_EQ (tl::to_string (m.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m.mag_x ()), "2.5");
EXPECT_EQ (tl::to_string (m.mag_y ()), "2.5");
EXPECT_EQ (m.disp ().to_string (), "-5,3");
}
TEST(9)
{
db::Matrix3d n = db::Matrix3d::disp (db::DVector (-5, 3)) * db::Matrix3d::perspective (18, -5, 1) * db::Matrix3d::rotation (33) * db::Matrix3d::shear (21) * db::Matrix3d::mag (2.5, 1.5) * db::Matrix3d::mirror (true);
std::string ns = n.to_string ();
tl::Extractor ex (ns.c_str ());
db::Matrix3d m;
ex.read (m);
EXPECT_EQ (m.equal (n), true);
EXPECT_EQ (m.less (n), false);
EXPECT_EQ (tl::to_string (m.perspective_tilt_x (1), 8), "18");
EXPECT_EQ (tl::to_string (m.perspective_tilt_y (1), 8), "-5");
EXPECT_EQ (tl::to_string (m.shear_angle ()), "21");
EXPECT_EQ (tl::to_string (m.angle ()), "33");
EXPECT_EQ (tl::to_string (m.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m.mag_x (), 8), "2.5");
EXPECT_EQ (tl::to_string (m.mag_y (), 8), "1.5");
EXPECT_EQ (tl::to_string (m.disp ().x (), 8), "-5");
EXPECT_EQ (tl::to_string (m.disp ().y (), 8), "3");
db::Matrix2d n2 = db::Matrix2d::rotation (-25) * (db::Matrix2d::shear (-17) * (db::Matrix2d::mirror (true) * db::Matrix2d::mag (17.5)));
ns = n2.to_string ();
ex = tl::Extractor (ns.c_str ());
db::Matrix2d m2;
ex.read (m2);
EXPECT_EQ (m2.equal (n2), true);
EXPECT_EQ (m2.less (n2), false);
EXPECT_EQ (tl::to_string (m2.mag_x (), 8), "17.5");
EXPECT_EQ (tl::to_string (m2.mag_y (), 8), "17.5");
EXPECT_EQ (tl::to_string (m2.is_mirror ()), "true");
EXPECT_EQ (tl::to_string (m2.angle (), 8), "-25"); // some roundoff happens here ..
EXPECT_EQ (tl::to_string (m2.shear_angle (), 8), "-17"); // some roundoff happens here ..
}
TEST(10)
{
db::Matrix3d m (1.0);
std::vector<db::DPoint> p, q;
p.push_back (db::DPoint (1, 1));
p.push_back (db::DPoint (2, 1));
p.push_back (db::DPoint (2, 2));
q.push_back (db::DPoint (1, 1));
q.push_back (db::DPoint (2, 1));
q.push_back (db::DPoint (2, 3));
adjust_matrix (m, p, q, db::MatrixAdjustFlags::All);
EXPECT_EQ ((m * p[0]).to_string (), "1,1");
EXPECT_EQ ((m * p[1]).to_string (), "2,1");
EXPECT_EQ ((m * p[2]).to_string (), "2,3");
m = db::Matrix3d (1.0);
adjust_matrix (m, p, q, db::MatrixAdjustFlags::All, 2);
EXPECT_EQ ((m * p[0]).to_string (), "1,1");
EXPECT_EQ ((m * p[1]).to_string (), "2,1");
EXPECT_EQ ((m * p[2]).to_string (), "2,3");
}