核心概念

  1. 坐标系

    • 笛卡尔坐标系:点用 (x, y) 表示
    • 极坐标系:点用 (r, θ) 表示(r=距离,θ=角度)
  2. 角度与弧度

    • Java 的 Math 类使用弧度制(Radians)
    • 转换公式:
      double radians = Math.toRadians(degrees); // 角度 → 弧度
      double degrees = Math.toDegrees(radians); // 弧度 → 角度
      

操作步骤详解

1. 距离计算
  • 两点间欧氏距离

    double distance(double x1, double y1, double x2, double y2) {
        double dx = x2 - x1;
        double dy = y2 - y1;
        return Math.sqrt(dx * dx + dy * dy); // 或 Math.hypot(dx, dy)
    }
    
  • 点到直线的距离
    直线方程:Ax + By + C = 0

    double pointToLineDistance(double x, double y, double A, double B, double C) {
        return Math.abs(A * x + B * y + C) / Math.sqrt(A * A + B * B);
    }
    
2. 角度计算
  • 向量夹角(0°~360°)

    double angleBetweenPoints(double x1, double y1, double x2, double y2) {
        double dx = x2 - x1;
        double dy = y2 - y1;
        double angleRad = Math.atan2(dy, dx); // [-π, π]
        double angleDeg = Math.toDegrees(angleRad);
        return (angleDeg < 0) ? angleDeg + 360 : angleDeg; // 转 [0°, 360°)
    }
    
  • 两向量夹角(锐角/钝角)

    double angleBetweenVectors(double ux, double uy, double vx, double vy) {
        double dot = ux * vx + uy * vy;
        double magU = Math.hypot(ux, uy);
        double magV = Math.hypot(vx, vy);
        return Math.toDegrees(Math.acos(dot / (magU * magV)));
    }
    
3. 坐标转换
  • 笛卡尔坐标 → 极坐标

    double[] toPolar(double x, double y) {
        double r = Math.hypot(x, y);
        double theta = Math.toDegrees(Math.atan2(y, x));
        return new double[]{r, theta};
    }
    
  • 极坐标 → 笛卡尔坐标

    double[] toCartesian(double r, double theta) {
        double rad = Math.toRadians(theta);
        double x = r * Math.cos(rad);
        double y = r * Math.sin(rad);
        return new double[]{x, y};
    }
    
  • 点绕原点旋转

    double[] rotatePoint(double x, double y, double angleDeg) {
        double rad = Math.toRadians(angleDeg);
        double cos = Math.cos(rad);
        double sin = Math.sin(rad);
        double newX = x * cos - y * sin;
        double newY = x * sin + y * cos;
        return new double[]{newX, newY};
    }
    
  • 点绕任意点旋转

    double[] rotateAroundPoint(double x, double y, double cx, double cy, double angleDeg) {
        // 平移到旋转中心
        double translatedX = x - cx;
        double translatedY = y - cy;
    
        // 旋转
        double[] rotated = rotatePoint(translatedX, translatedY, angleDeg);
    
        // 平移回原坐标系
        return new double[]{
            rotated[0] + cx,
            rotated[1] + cy
        };
    }
    

常见错误与解决方案

  1. 角度/弧度混淆

    • 错误:直接使用角度调用 Math.sin(30)(应为弧度)
    • 修复
      double sinValue = Math.sin(Math.toRadians(30));
      
  2. 浮点数精度问题

    • 错误if (distance == 0)(浮点数不能直接比较)
    • 修复
      if (Math.abs(distance) < 1e-6) // 使用误差容限
      
  3. 象限处理错误

    • 错误:用 Math.atan(dy/dx) 计算角度(丢失象限信息)
    • 修复:使用 Math.atan2(dy, dx) 自动处理象限。

注意事项

  1. 坐标系方向

    • 屏幕坐标系中 Y 轴向下为正,数学坐标系中 Y 轴向上为正,需注意转换。
  2. 性能敏感场景

    • 避免重复计算三角函数:
      // 低效
      for (int i = 0; i < n; i++) {
          x = r * Math.cos(Math.toRadians(angle));
      }
      
      // 高效
      double rad = Math.toRadians(angle);
      double cos = Math.cos(rad);
      for (int i = 0; i < n; i++) {
          x = r * cos;
      }
      
  3. 大数计算溢出

    • 使用 Math.hypot(x, y) 替代 Math.sqrt(x*x + y*y) 避免中间结果溢出。

使用技巧

  1. 标准化向量

    double[] normalize(double x, double y) {
        double mag = Math.hypot(x, y);
        return new double[]{x / mag, y / mag}; // 单位向量
    }
    
  2. 角度差值(最小旋转角)

    double angleDiff(double a, double b) {
        double diff = (b - a + 360) % 360;
        return diff > 180 ? diff - 360 : diff;
    }
    
  3. 使用 Point2D 类简化代码

    import java.awt.geom.Point2D;
    
    Point2D p1 = new Point2D.Double(3, 4);
    double dist = p1.distance(0, 0); // 计算到原点的距离
    

最佳实践与性能优化

  1. 减少对象创建

    • 在循环中避免创建新对象(如 new Point2D),改用基本类型变量。
  2. 查表法优化三角函数

    • 对固定角度步长(如游戏开发):
      double[] cosTable = new double[360];
      for (int deg = 0; deg < 360; deg++) {
          cosTable[deg] = Math.cos(Math.toRadians(deg));
      }
      
  3. 空间换时间

    • 预计算常用值(如 Math.PI/180):
      static final double DEG_TO_RAD = Math.PI / 180.0;
      
  4. 第三方库

    • 复杂场景使用专业库:
      • Apache Commons Geometry:提供向量、旋转等高级功能。
      • JTS Topology Suite:处理地理空间计算。

总结示例

// 计算两点距离与角度
Point2D p1 = new Point2D.Double(1, 1);
Point2D p2 = new Point2D.Double(4, 5);

double dist = p1.distance(p2); // 5.0
double angle = Math.toDegrees(Math.atan2(
    p2.getY() - p1.getY(), 
    p2.getX() - p1.getX()
)); // 53.13°

// 将p2绕p1旋转90度
Point2D rotated = new Point2D.Double();
rotated.setLocation(
    p1.getX() + (p2.getX()-p1.getX())*Math.cos(Math.PI/2) 
               - (p2.getY()-p1.getY())*Math.sin(Math.PI/2),
    p1.getY() + (p2.getX()-p1.getX())*Math.sin(Math.PI/2) 
               + (p2.getY()-p1.getY())*Math.cos(Math.PI/2)
); // 结果: (1, 5)

通过结合标准库函数与数学原理,可高效实现几何计算。重点注意坐标系转换弧度角度转换浮点精度处理,复杂场景推荐使用专业几何库。