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;
    }
}
最后修改:2025 年 11 月 10 日
如果觉得我的文章对你有用,请随意赞赏