mirror of https://github.com/KLayout/klayout.git
WIP.
This commit is contained in:
parent
55e79ef78f
commit
75b1b4dc54
|
|
@ -164,60 +164,60 @@ camera_normal (const QMatrix4x4 &camera_trans, double x, double y)
|
|||
void
|
||||
normalize_scene_trans (const QMatrix4x4 &cam_trans, QVector3D &displacement, double &scale, double ztarget)
|
||||
{
|
||||
QMatrix4x4 m;
|
||||
|
||||
// Here is the theory:
|
||||
// Let:
|
||||
// cam = ( M t ) M = 3x3 matrix, t = 3x1 translation vector, z = scalar, p = 1x3 perspective
|
||||
// ( p z )
|
||||
// and:
|
||||
// scene = ( S d ) S = s*U1 (s = scale factor, U1 = 3x3 unit matrix), d = 3x1 displacement vector
|
||||
// ( 0 1 )
|
||||
// scene = ( S d*s ) S = s*U1 (s = scale factor, U1 = 3x3 unit matrix), d = 3x1 displacement vector
|
||||
// ( 0 1 )
|
||||
// then:
|
||||
// cam * scene = ( M*s M*d+t )
|
||||
// ( p*s p*d+z ) (p*d = dot product)
|
||||
// cam * scene = ( M*s M*d*s+t )
|
||||
// ( p*s p*d*s+z ) (p*d = dot product)
|
||||
//
|
||||
// this is image invariant (only x,y results are considered) against changes of s (s->s') if
|
||||
//
|
||||
// 1.) (p*d+z)/s = (p*d'+z)/s'
|
||||
// 2.) (M*d+t)/s = (M*d'+t)/s' for [x] and [y]
|
||||
// 1.) (p*d*s+z)/s = (p*d'*s'+z)/s' (because x and y will be devided by this value)
|
||||
// 2.) (M*d*s+t)/s = (M*d'*s'+t)/s' for [x] and [y]
|
||||
//
|
||||
// Ff we seek a solution with d'[z] == b (b = ztarget), we get these equations (f:=s'/s)
|
||||
// or
|
||||
//
|
||||
// 2.) M[xx] * d'[x] + M[xy] * d'[y] - ((M*d)[x] + t[x]) * f = -t[x] - M[xz] * b
|
||||
// M[yx] * d'[x] + M[yy] * d'[y] - ((M*d)[y] + t[y]) * f = -t[y] - M[yz] * b
|
||||
// 1.) p[x] * d'[x] + p[y] * d'[y] - (p*d+z) * f = -z - p[z] * b
|
||||
// 1.) p*d+z/s = p*d'+z/s'
|
||||
// 2.) M*d+t/s = M*d'+t/s'
|
||||
//
|
||||
// If we seek a solution with d'[z] == b (b = ztarget), we get these equations (f:=1/s')
|
||||
//
|
||||
// 2.) M[xx] * d'[x] + M[xy] * d'[y] + t[x] * f = (M*d)[x] + t[x]/s - M[xz]*b
|
||||
// M[yx] * d'[x] + M[yy] * d'[y] + t[y] * f = (M*d)[y] + t[y]/s - M[yz]*b
|
||||
// 1.) p[x] * d'[x] + p[y] * d'[y] + z * f = p*d + z/s - p[z]*b
|
||||
//
|
||||
// we can solve these equations for d'[x], d'[y] and f.
|
||||
// With p[x]=M[wx], p[y]=M[wy] and z=t[w], the above equation system can be written as
|
||||
//
|
||||
// M[ix] * d'[x] + M[iy] * d'[y] - ((M*d)[i] + t[i]) * f = -t[i] - M[iz]*b i = x,y,w
|
||||
//
|
||||
// and with M,t->M (4x4 matrix) and d->(d,1) (4d vector)
|
||||
//
|
||||
// M[ix] * d'[x] + M[iy] * d'[y] - (M*d)[i] * f = -t[i] - M[iz]*b i = x,y,w
|
||||
// M[ix] * d'[x] + M[iy] * d'[y] + t[i] * f = (M*d)[i] - M[iz]*b + t[i]/s i = x,y,w
|
||||
//
|
||||
|
||||
QVector4D d4 (displacement);
|
||||
d4.setW (1.0);
|
||||
QMatrix4x4 m;
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (i != 2) {
|
||||
m (i, 0) = cam_trans (i, 0);
|
||||
m (i, 1) = cam_trans (i, 1);
|
||||
m (i, 3) = -QVector4D::dotProduct (cam_trans.row (i), d4);
|
||||
m (i, 3) = cam_trans (i, 3);
|
||||
}
|
||||
}
|
||||
|
||||
bool invertable = false;
|
||||
m = m.inverted (&invertable);
|
||||
QMatrix4x4 minv = m.inverted (&invertable);
|
||||
if (! invertable) {
|
||||
return;
|
||||
}
|
||||
|
||||
QVector4D sol = m.map (-cam_trans.column (3) - cam_trans.column (2) * ztarget);
|
||||
if (sol.w () > 0.01 /*skip weird solutions*/) {
|
||||
scale *= sol.w ();
|
||||
QVector4D rhs = cam_trans.map (QVector4D (displacement.x (), displacement.y (), displacement.z () - ztarget, 1.0 / scale));
|
||||
QVector4D sol = minv.map (rhs);
|
||||
double f = sol.w ();
|
||||
if (f > 1e-6 /*skip weird solutions*/) {
|
||||
scale = 1.0 / f;
|
||||
displacement = QVector3D (sol.x (), sol.y (), ztarget);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ D25ViewWidget::wheelEvent (QWheelEvent *event)
|
|||
// "Shift" is closeup
|
||||
|
||||
double f = event->angleDelta ().y () * (1.0 / (90 * 8));
|
||||
m_displacement += -f * cam_position ().length () * ray.second;
|
||||
m_displacement += -(f / m_scale_factor) * cam_position ().length () * ray.second;
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -212,7 +212,7 @@ D25ViewWidget::wheelEvent (QWheelEvent *event)
|
|||
QVector3D initial_displacement = m_displacement;
|
||||
QVector3D displacement = m_displacement;
|
||||
|
||||
displacement = hp * (1.0 - f) + displacement * f;
|
||||
displacement += hp * (1.0 - f) / (f * m_scale_factor);
|
||||
m_scale_factor *= f;
|
||||
|
||||
// normalize the scene translation so the scene does not "flee"
|
||||
|
|
@ -251,7 +251,7 @@ D25ViewWidget::keyReleaseEvent (QKeyEvent *event)
|
|||
QVector3D
|
||||
D25ViewWidget::hit_point_with_scene (const QVector3D &line, const QVector3D &line_dir)
|
||||
{
|
||||
QVector3D corner = QVector3D (m_bbox.left (), m_zmin, -(m_bbox.bottom () + m_bbox.height ())) * m_scale_factor + m_displacement;
|
||||
QVector3D corner = (QVector3D (m_bbox.left (), m_zmin, -(m_bbox.bottom () + m_bbox.height ())) + m_displacement) * m_scale_factor;
|
||||
QVector3D dim = QVector3D (m_bbox.width (), m_zmax - m_zmin, m_bbox.height ()) * m_scale_factor;
|
||||
|
||||
std::pair<bool, QVector3D> hp = lay::hit_point_with_cuboid (line, line_dir, corner, dim);
|
||||
|
|
@ -314,7 +314,7 @@ D25ViewWidget::mouseMoveEvent (QMouseEvent *event)
|
|||
QVector3D yv (-re * xv.z (), cos (cam_elevation () * M_PI / 180.0), re * xv.x ());
|
||||
QVector3D drag = xv * dx + yv * dy;
|
||||
|
||||
m_displacement = m_start_displacement + drag;
|
||||
m_displacement = m_start_displacement + drag / m_scale_factor;
|
||||
|
||||
update_cam_trans ();
|
||||
|
||||
|
|
@ -355,7 +355,7 @@ D25ViewWidget::cam_direction () const
|
|||
QVector3D
|
||||
D25ViewWidget::cam_position () const
|
||||
{
|
||||
double focus_dist = 4.0;
|
||||
double focus_dist = 4.0; // @@@
|
||||
return cam_direction () * -focus_dist;
|
||||
}
|
||||
|
||||
|
|
@ -374,8 +374,10 @@ D25ViewWidget::cam_elevation () const
|
|||
QMatrix4x4
|
||||
D25ViewWidget::cam_perspective () const
|
||||
{
|
||||
double focus_dist = 4.0; // @@@
|
||||
QMatrix4x4 t;
|
||||
t.perspective (60.0f, float (width ()) / float (height ()), 0.1f, 100.0f);
|
||||
t.translate (QVector3D (0.0, 0.0, -focus_dist));
|
||||
return t;
|
||||
}
|
||||
|
||||
|
|
@ -385,7 +387,6 @@ D25ViewWidget::cam_trans () const
|
|||
QMatrix4x4 t;
|
||||
t.rotate (-cam_elevation (), 1.0, 0.0, 0.0);
|
||||
t.rotate (cam_azimuth (), 0.0, 1.0, 0.0);
|
||||
t.translate (-cam_position ());
|
||||
return t;
|
||||
}
|
||||
|
||||
|
|
@ -649,9 +650,9 @@ D25ViewWidget::paintGL ()
|
|||
|
||||
QMatrix4x4 scene_trans;
|
||||
|
||||
// provide the displacement and scaling
|
||||
scene_trans.translate (m_displacement);
|
||||
// provide the displacement and scaling (in this order!)
|
||||
scene_trans.scale (m_scale_factor);
|
||||
scene_trans.translate (m_displacement);
|
||||
// this way we can use y as z coordinate when drawing
|
||||
scene_trans.scale (1.0, 1.0, -1.0);
|
||||
|
||||
|
|
|
|||
|
|
@ -176,11 +176,11 @@ TEST(6_NormalizeSceneTrans)
|
|||
cam.translate (QVector3D (0.0, 0.0, 4.0));
|
||||
|
||||
double scale = 0.1;
|
||||
QVector3D displacement (-0.5, 0.2, 2.0);
|
||||
QVector3D displacement (-5.0, 2.0, 20.0);
|
||||
|
||||
QMatrix4x4 scene1;
|
||||
scene1.translate (displacement);
|
||||
scene1.scale (scale);
|
||||
scene1.translate (displacement);
|
||||
|
||||
QVector3D v1 = (cam * scene1).map (QVector3D (1.0, -1.0, 2.0));
|
||||
v1.setZ (0);
|
||||
|
|
@ -192,8 +192,8 @@ TEST(6_NormalizeSceneTrans)
|
|||
lay::normalize_scene_trans (cam, displacement, scale);
|
||||
|
||||
QMatrix4x4 scene2;
|
||||
scene2.translate (displacement);
|
||||
scene2.scale (scale);
|
||||
scene2.translate (displacement);
|
||||
|
||||
EXPECT_EQ (tl::sprintf ("%.4f", scale), "0.0667");
|
||||
|
||||
|
|
@ -208,14 +208,14 @@ TEST(6_NormalizeSceneTrans)
|
|||
EXPECT_EQ ((u2 - v2).length () < 1e-4, true);
|
||||
EXPECT_EQ ((u3 - v3).length () < 1e-4, true);
|
||||
|
||||
lay::normalize_scene_trans (cam, displacement, scale, 1.0);
|
||||
lay::normalize_scene_trans (cam, displacement, scale, 10.0);
|
||||
|
||||
QMatrix4x4 scene3;
|
||||
scene3.translate (displacement);
|
||||
scene3.scale (scale);
|
||||
scene3.translate (displacement);
|
||||
|
||||
EXPECT_EQ (tl::sprintf ("%.4f", scale), "0.0833");
|
||||
EXPECT_EQ (tl::to_string (displacement.z ()), "1");
|
||||
EXPECT_EQ (tl::sprintf ("%.4f", scale), "0.0800");
|
||||
EXPECT_EQ (tl::to_string (displacement.z ()), "10");
|
||||
|
||||
QVector3D uu1 = (cam * scene2).map (QVector3D (1.0, -1.0, 2.0));
|
||||
uu1.setZ (0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue