这里有一个示例代码,显示了所需的正确计算。想象一下真实的表格 X,Y 是 X 与图片水平,Y 向上。为了方便和更容易遵循样本,原点为 0,0,0。然后第二张图像将正确的 X,Y 想象为左上角,其中 X 轴向下,Y 向右(-90 度旋转)。不用担心稍后可以轻松调整。下面的快速示例中的注释解释了每一行的作用及其原因。
// compute from the points the table height and width
var realTableDimX = 902d;
var realTableDimY = 597d;
// the real table matrix is 0,0,0 on bottom corner
// so matrix is identity (our source)
var realTableMatrix = new Matrix3D();
// the laser is rotated 90 degree and position at the top left based compared to the realTablematrix
var laserMatrix = new Matrix3D();
// rotate and translate the laser matrix into position
// 90 degree doesnt account for the little skew (see comment outside code for explaination on how to fix that)
laserMatrix.Rotate(new Quaternion(new Vector3D(0, 0, 1), -90d));
laserMatrix.Translate(new Vector3D(0, realTableDimY, 0d));
// compute the laser dimensions (i used your points you found out)
var laserDimX = 20392d - (-16300d);
var laserDimY = 12746 - (-11409d);
// calculate the ratio to factor in to displace the point to the real value onto the laser matrix
var laserXRatio = laserDimX / realTableDimX;
var laserYRatio = laserDimY / realTableDimY;
// since matrix are 1 to 1 when you compute if you have an equal ratio of 40 in X and 40 in Y then the point at 10,10,0 on
// the real table is correcponding to the point 400,400,0 on the laser matrix. But since it's rotated 90 degree you
// will need to apply the Y ration to the X point after the transform and the X ratio to the Y point to get the actual point.
// sample point on table. Logic can be flipped with laser matrix to do it the other way
var sampleRealTablePoint = new Point3D(450, 300, 0); // roughly centered
// transform the point from one UCS to another is simply multiplying by it's current UCS (matrix it's in)
// to transform it to world UCS then multiply by the inverse of other UCS we want it in (the other matrix)
var sampleRealTablePointWorld = realTableMatrix.Transform(sampleRealTablePoint);
// convert that point into the laser matrix but first create and inverted matrix of the laser matrix
// we copy a matrix to not modify the current one when inverting it
var laserInvertedMatrix = new Matrix3D() * laserMatrix;
laserInvertedMatrix.Invert();
// get the sample point in the world of the laser matrix
var sampleRealTablePointToLaserMatrix = laserInvertedMatrix.Transform(sampleRealTablePointWorld);
// not adjust the X and Y like said earlier
var finalAdjustedPoint = new Point3D(sampleRealTablePointToLaserMatrix.X * laserXRatio, sampleRealTablePointToLaserMatrix.Y * laserYRatio, 0d);
// this is if you want the point in the world of the laser matrix and not it's offset from the 0,0,0
// the vector here is the top left corner of your laser matrix (x, y, z)
var laserWorldFinalPoint = finalAdjustedPoint + new Vector3D(-11409d, -16155d, 0d);
所以这里你有它。真实桌子上的样本中心点转换为{12203,5947,0}
使用这个代码几乎是激光矩阵的死点。
现在来说说倾斜部分。这也很简单。这一行:
laserMatrix.Rotate(new Quaternion(new Vector3D(0, 0, 1), -90d));
这就是你需要改变的一切。你想要的是始终认为左上角是原点,所以你想要做的就是想象一条向右延伸的直线(在你的激光图像上),并且你想弄清楚这个完美的 X 轴之间的角度是多少( vector(1,0,0)) 和左下点的向量,在本例中略大于 90 度(可能在 -91 到 -95 度之间)。您需要计算出 Z 轴的角度才能实现这一目标。您使用的公式是否返回 +270 度而不是 -90 度并不重要,因为它是一个矩阵,它会给出相同的结果。
这里是一种基于给定旋转轴计算两个向量之间角度的方法
public double AngleToInDegree(Vector3D v, Vector3D vector, Vector3D normal)
{
var dotNormal = Vector3D.DotProduct(normal, Vector3D.CrossProduct(v, vector));
var dotVector = Vector3D.DotProduct(v, vector);
var angle = Math.Atan2(dotNormal, dotVector);
return angle * 180d / Math.PI;
}
可用的示例是:
var angle = AngleToInDegree(new Vector3D(1,0,0), new Vector3D(0,1,0), new Vector3D(0,0,1));
这会检查完美 X 向量和完美 Y 向量相对于完美 Z 向量之间的角度,这将为您提供 90 度。