変換行列を段階的に計算する解決策を見つけたと思います。
// some example points:
QPointF p1(1.0, 2.0);
QPointF p2(2.0, 2.5);
QPointF p3(1.5, 4.0);
QPointF p4(3.0, 5.0);
// define the affine transformation which will position p1, p2, p3 correctly:
QTransform trans;
trans.translate(p1.x(), p1.y());
trans.scale(p2.x() - p1.x(), p3.y() - p1.y());
trans.shear((p3.x() - p1.x()) / trans.m11(), (p2.y() - p1.y()) / trans.m22());
これまで、trans は平行四辺形変換を記述していました。このパラレログラム内で、次のステップで (比較的) p4 を見つけます。これは、トランスの反転を伴わない直接式を使用して実行できると思います。
// relative position of the 4th point in the transformed coordinate system:
qreal px = trans.inverted().map(p4).x();
qreal py = trans.inverted().map(p4).y();
// this defines the perspective distortion:
qreal y = 1 + (py - 1) / px;
qreal x = 1 + (px - 1) / py;
値x
とy
を説明するのは困難です。そのうちの 1 つだけ (もう 1 つを に設定1
) を指定すると、これは only の相対的なスケーリングを定義しますp4
。しかし、x と y の両方の透視変換の組み合わせ、x と y の意味は難しいです。試行錯誤で数式を見つけました。
// and thus the perspective matrix:
QTransform persp(1/y, 0, 1/y-1,
0, 1/x, 1/x-1,
0, 0, 1);
// premultiply the perspective matrix to the affine transformation:
trans = persp * trans;
いくつかのテストでは、これが正しい結果につながることが示されました。ただし、2 つの点が等しい場合や、そのうちの 1 つが他の 2 つの点の間の線分上にある場合などの特殊なケースはテストしていません。このような状況では、このソリューションは壊れる可能性があると思います。
したがって、ポイント座標, ... ,が与えられた場合、マトリックス値m11
, m12
...の直接式を検索します。m33
p1.x()
p1.y()
p4.x()
p4.y()