1. 基础数学原理
对于两个向量 v₁ 和 v₂,我们要找到旋转矩阵 R 和缩放因子 s,使得:
v₂ = s × R × v₁
2. Java实现
public class VectorTransform {
private double[][] rotationMatrix;
private double scaleFactor;
public VectorTransform(double[] sourceVector, double[] targetVector) {
if (sourceVector.length != targetVector.length) {
throw new IllegalArgumentException("Vectors must have same dimension");
}
calculateTransform(sourceVector, targetVector);
}
private void calculateTransform(double[] v1, double[] v2) {
int n = v1.length;
// 计算缩放因子 (向量模长的比值)
double normV1 = norm(v1);
double normV2 = norm(v2);
if (normV1 == 0) {
throw new IllegalArgumentException("Source vector cannot be zero vector");
}
this.scaleFactor = normV2 / normV1;
// 计算旋转矩阵
if (n == 2) {
calculateRotation2D(v1, v2);
} else if (n == 3) {
calculateRotation3D(v1, v2);
} else {
calculateRotationND(v1, v2);
}
}
// 计算二维旋转
private void calculateRotation2D(double[] v1, double[] v2) {
double[] u1 = normalize(v1);
double[] u2 = normalize(v2);
double cosTheta = dot(u1, u2);
double sinTheta = u1[0] * u2[1] - u1[1] * u2[0]; // 2D叉积
rotationMatrix = new double[][]{
{cosTheta, -sinTheta},
{sinTheta, cosTheta}
};
}
// 计算三维旋转 (使用罗德里格斯旋转公式)
private void calculateRotation3D(double[] v1, double[] v2) {
double[] u1 = normalize(v1);
double[] u2 = normalize(v2);
double[] axis = cross(u1, u2);
double axisNorm = norm(axis);
if (axisNorm < 1e-10) {
// 向量平行或反平行
if (dot(u1, u2) > 0) {
// 平行 - 单位矩阵
rotationMatrix = new double[][]{
{1, 0, 0},
{0, 1, 0},
{0, 0, 1}
};
} else {
// 反平行 - 180度旋转 (任意轴)
rotationMatrix = new double[][]{
{-1, 0, 0},
{0, -1, 0},
{0, 0, -1}
};
}
} else {
double[] unitAxis = normalize(axis);
double cosTheta = dot(u1, u2);
double sinTheta = axisNorm;
// 罗德里格斯旋转公式
double x = unitAxis[0], y = unitAxis[1], z = unitAxis[2];
double c = cosTheta;
double s = sinTheta;
double t = 1 - c;
rotationMatrix = new double[][]{
{t*x*x + c, t*x*y - s*z, t*x*z + s*y},
{t*x*y + s*z, t*y*y + c, t*y*z - s*x},
{t*x*z - s*y, t*y*z + s*x, t*z*z + c}
};
}
}
// 计算N维旋转 (使用Householder变换)
private void calculateRotationND(double[] v1, double[] v2) {
int n = v1.length;
double[] u = normalize(v1);
double[] v = normalize(v2);
double[] w = subtract(u, v);
double wNorm = norm(w);
if (wNorm < 1e-10) {
// 向量相同 - 单位矩阵
rotationMatrix = identityMatrix(n);
return;
}
w = normalize(w);
// Householder 反射矩阵: H = I - 2wwᵀ
rotationMatrix = identityMatrix(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
rotationMatrix[i][j] -= 2 * w[i] * w[j];
}
}
}
// 应用变换到新向量
public double[] transform(double[] vector) {
if (vector.length != rotationMatrix.length) {
throw new IllegalArgumentException("Vector dimension mismatch");
}
double[] rotated = multiply(rotationMatrix, vector);
return multiply(rotated, scaleFactor);
}
// 获取变换参数
public double[][] getRotationMatrix() {
return copyMatrix(rotationMatrix);
}
public double getScaleFactor() {
return scaleFactor;
}
// 工具方法
public double norm(double[] v) {
return Math.sqrt(dot(v, v));
}
public double[] normalize(double[] v) {
double n = norm(v);
if (n == 0) return v;
return multiply(v, 1.0 / n);
}
private double dot(double[] a, double[] b) {
double result = 0;
for (int i = 0; i < a.length; i++) {
result += a[i] * b[i];
}
return result;
}
private double[] cross(double[] a, double[] b) {
if (a.length != 3 || b.length != 3) {
throw new IllegalArgumentException("Cross product only for 3D vectors");
}
return new double[]{
a[1]*b[2] - a[2]*b[1],
a[2]*b[0] - a[0]*b[2],
a[0]*b[1] - a[1]*b[0]
};
}
private double[] subtract(double[] a, double[] b) {
double[] result = new double[a.length];
for (int i = 0; i < a.length; i++) {
result[i] = a[i] - b[i];
}
return result;
}
private double[] multiply(double[] v, double scalar) {
double[] result = new double[v.length];
for (int i = 0; i < v.length; i++) {
result[i] = v[i] * scalar;
}
return result;
}
private double[] multiply(double[][] matrix, double[] vector) {
int n = matrix.length;
double[] result = new double[n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
result[i] += matrix[i][j] * vector[j];
}
}
return result;
}
private double[][] identityMatrix(int n) {
double[][] I = new double[n][n];
for (int i = 0; i < n; i++) {
I[i][i] = 1;
}
return I;
}
private double[][] copyMatrix(double[][] matrix) {
double[][] copy = new double[matrix.length][];
for (int i = 0; i < matrix.length; i++) {
copy[i] = matrix[i].clone();
}
return copy;
}
}3. 使用示例
public class VectorTransformExample {
public static void main(String[] args) {
// 示例1: 2D向量变换
double[] source2D = {1, 0}; // 原始向量
double[] target2D = {0, 2}; // 目标向量
VectorTransform transform2D = new VectorTransform(source2D, target2D);
// 对新向量应用相同的变换
double[] newVector2D = {2, 1};
double[] transformed2D = transform2D.transform(newVector2D);
System.out.println("2D Transform:");
System.out.println("Scale factor: " + transform2D.getScaleFactor());
System.out.println("Original: " + Arrays.toString(newVector2D));
System.out.println("Transformed: " + Arrays.toString(transformed2D));
// 示例2: 3D向量变换
double[] source3D = {1, 0, 0};
double[] target3D = {0, 1, 0};
VectorTransform transform3D = new VectorTransform(source3D, target3D);
double[] newVector3D = {1, 1, 1};
double[] transformed3D = transform3D.transform(newVector3D);
System.out.println("\n3D Transform:");
System.out.println("Scale factor: " + transform3D.getScaleFactor());
System.out.println("Original: " + Arrays.toString(newVector3D));
System.out.println("Transformed: " + Arrays.toString(transformed3D));
}
}4. 高级版本(支持变换组合)
public class AdvancedVectorTransform {
private double[][] transformationMatrix;
public AdvancedVectorTransform(double[] sourceVector, double[] targetVector) {
// 直接计算完整的仿射变换矩阵
this.transformationMatrix = calculateTransformationMatrix(sourceVector, targetVector);
}
private double[][] calculateTransformationMatrix(double[] v1, double[] v2) {
int n = v1.length;
double[][] matrix = new double[n][n];
// 这里可以使用更复杂的算法,如SVD分解
// 简化为缩放和旋转的组合
VectorTransform basicTransform = new VectorTransform(v1, v2);
double scale = basicTransform.getScaleFactor();
double[][] rotation = basicTransform.getRotationMatrix();
// 组合缩放和旋转
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
matrix[i][j] = scale * rotation[i][j];
}
}
return matrix;
}
public double[] transform(double[] vector) {
return multiply(transformationMatrix, vector);
}
// 矩阵乘法工具方法
private double[] multiply(double[][] matrix, double[] vector) {
int n = matrix.length;
double[] result = new double[n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
result[i] += matrix[i][j] * vector[j];
}
}
return result;
}
}