Вот пример кода, который показывает требуемый расчет.Представьте, что вы настоящий стол X, Y - горизонтальный с изображением, а 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 (вектор (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степень.