You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java矩形绕中心旋转后内部点坐标计算结果异常排查

问题原因

坐标计算结果和预期不符,核心是三点错误:

  • 直接套用数学坐标系的旋转公式后,仅加回原矩形的中心偏移,没有考虑90度旋转后矩形宽高互换、新画布尺寸变化带来的坐标偏移,和实际用Java2D渲染图像时的变换逻辑不匹配。
  • 角度方向和图像坐标系规则未对齐:图像/屏幕坐标系默认Y轴向下为正,Java2D的rotate方法传入正角度代表顺时针旋转,和数学坐标系Y轴向上、正角度逆时针的规则不同,传值错误直接导致结果偏差。
  • 手动实现的点旋转逻辑,没有复刻rotate渲染方法里的translate((neww-w)/2, (newh-h)/2)平移动作,变换步骤和渲染流程不一致。
正确计算逻辑

要得到和Photoshop、Java2D渲染完全一致的点坐标,必须严格对齐渲染时的变换顺序,步骤如下:

  1. 根据旋转角度计算旋转后新画布的宽高:
    • 旋转90度、270度时,新宽=原高,新高=原宽
    • 任意角度通用计算:neww = 原宽 * |cosθ| + 原高 * |sinθ|,newh = 原高 * |cosθ| + 原宽 * |sinθ|
  2. 按和渲染逻辑一致的顺序变换点坐标:
    • 第一步:将原坐标系下的点平移到以原图像中心为原点的相对坐标系
    • 第二步:对相对坐标应用旋转变换
    • 第三步:将旋转后的相对坐标平移回原图像坐标系
    • 第四步:叠加新画布相对原图像的平移偏移,得到最终新画布下的点坐标
修正后的代码
public class CoordinateRotator {
    /**
     * 计算图像绕中心旋转后,原内部点在新画布中的坐标
     * @param x 原图像内点的x坐标
     * @param y 原图像内点的y坐标
     * @param w 原图像宽度
     * @param h 原图像高度
     * @param degrees 顺时针旋转角度
     * @return 旋转后新画布内的点坐标,x为数组[0]位,y为数组[1]位
     */
    public static int[] rotatePoint(int x, int y, int w, int h, double degrees) {
        double angle = Math.toRadians(degrees);
        double cos = Math.cos(angle);
        double sin = Math.sin(angle);

        // 计算新画布尺寸
        int newW = (int) Math.floor(w * Math.abs(cos) + h * Math.abs(sin));
        int newH = (int) Math.floor(h * Math.abs(cos) + w * Math.abs(sin));

        // 原图像中心
        int cx = w / 2;
        int cy = h / 2;

        // 第一步:转换为以原中心为原点的相对坐标
        double x1 = x - cx;
        double y1 = y - cy;

        // 第二步:旋转变换
        double x2 = x1 * cos - y1 * sin;
        double y2 = x1 * sin + y1 * cos;

        // 第三步:平移回原图像坐标系,叠加新画布的平移偏移
        double tx = (newW - w) / 2.0;
        double ty = (newH - h) / 2.0;
        int rx = (int) Math.round(x2 + cx + tx);
        int ry = (int) Math.round(y2 + cy + ty);

        return new int[]{rx, ry};
    }

    public static void main(String[] args) {
        // 测试案例:原宽50,高128,点(15,111),顺时针旋转90度
        int[] res = rotatePoint(15, 111, 50, 128, 90);
        // 输出17,15,和Photoshop结果完全一致
        System.out.println(res[0] + "," + res[1]);
    }
}
注意事项
  • 该方法逻辑和Java2D图像旋转方法完全对齐,计算结果和渲染后的像素位置无偏差,可直接用于碰撞盒角点坐标计算。
  • 不要随意给角度加负号,Java2D中Y轴向下,传入正角度即为顺时针旋转,和Photoshop的旋转方向一致。
  • 坐标取整用Math.round做四舍五入,避免强制类型转换直接截断小数带来的1像素误差。

内容的提问来源于stack exchange,提问作者Zizzyzizzy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 08:24:15