C#实现点绕任意中心旋转的坐标计算方法

许南星
许南星
发布时间:2026-10-13 | 4人浏览过
原创

介绍C#中计算点绕任意中心旋转后坐标的算法实现,包含坐标平移、三角函数应用及完整代码示例。

算法原理

计算点 P(x1, y1) 绕点 A(a, b) 旋转弧度 θ 得到点 Q(x2, y2) 的核心思路是坐标变换:

  1. 平移:将旋转中心 A 移至原点 (0,0),此时点 P 变为相对坐标 (x1-a, y1-b)。
  2. 旋转:基于极坐标思想,计算点到原点的距离 r 及当前与 X 轴正向夹角 α。旋转后新的角度为 α ± θ(顺时针或逆时针),进而求出新直角坐标。
  3. 还原:将旋转后的相对坐标加上中心点 A 的偏移量,还原到全局坐标系。

图示展示了这一几何变换过程:

C# 代码实现

首先定义表示二维点的 struct,包含坐标存储、距离计算及格式化输出功能。

using System;

// 表示一个点
struct Point
{
    public double x, y;

    //构造函数
    public Point(double x, double y)
    {
        this.x = x;
        this.y = y;
    }

    //该点到指定点pTarget的距离
    public double DistanceTo(Point p)
    {
        return Math.Sqrt((p.x - x) * (p.x - x) + (p.y - y) * (p.y - y));
    }

    //重写ToString方法
    public override string ToString()
    {
        return string.Concat("Point (",
            this.x.ToString("#0.000"), ',',
            this.y.ToString("#0.000"), ')');
    }
}

为了实现精确的角度计算,需要处理点在不同象限及坐标轴上的特殊情况。直接使用 Math.Atan(y/x) 无法区分不同象限,因此引入自定义的弧度计算辅助方法。

// 计算点P(x,y)与X轴正方向的夹角
private static double radPOX(double x, double y)
{
    if (x == 0 && y == 0) return 0;
    if (y == 0 && x > 0) return 0;
    if (y == 0 && x < 0) return Math.PI;
    if (x == 0 && y > 0) return Math.PI / 2;
    if (x == 0 && y < 0) return Math.PI * 3 / 2;
    
    if (x > 0 && y > 0) return Math.Atan(y / x); // 第一象限
    if (x < 0 && y > 0) return Math.PI - Math.Atan(y / -x); // 第二象限
    if (x < 0 && y < 0) return Math.PI + Math.Atan(-y / -x); // 第三象限
    if (x > 0 && y < 0) return Math.PI * 2 - Math.Atan(-y / x); // 第四象限
    return 0;
}

核心旋转方法 RotatePoint 结合了上述平移与角度计算逻辑。默认参数 isClockwise=true 表示顺时针旋转;若设为 false 则为逆时针。

// 返回点P围绕点A旋转弧度rad后的坐标
private static Point RotatePoint(Point P, Point A,
    double rad, bool isClockwise = true)
{
    // 1. 平移:P 相对于 A 的坐标
    Point Temp1 = new Point(P.x - A.x, P.y - A.y);
    
    // 2. 计算极径和极角
    double lenO2Temp1 = Temp1.DistanceTo(new Point(0, 0));
    double angT1OX = radPOX(Temp1.x, Temp1.y);
    
    // 3. 计算旋转后的角度:顺时针减,逆时针加
    // 注意:isClockwise ? 1 : -1 决定了符号方向
    double angT2OX = angT1OX - (isClockwise ? 1 : -1) * rad;
    
    // 4. 还原到绝对坐标系
    Point Temp2 = new Point(
        lenO2Temp1 * Math.Cos(angT2OX),
        lenO2Temp1 * Math.Sin(angT2OX));
        
    return new Point(Temp2.x + A.x, Temp2.y + A.y);
}

测试用例与运行结果

以下 Main 方法演示了两种场景: 1. 点 P(5, -5) 绕原点 (0,0) 逆时针每次旋转 π/4。 2. 点 P(5, -5) 绕中心点 (2.5, 2.5) 顺时针每次旋转 π/4。

static void Main(string[] args)
{
    // 准备数据
    Point A = new Point(0, 0);
    Point B = new Point(3, 4);
    Console.WriteLine("Length of AB: " + A.DistanceTo(B));
    
    Point P = new Point(5, -5);
    Console.WriteLine("Original Point: " + P.ToString() + '\n');
    
    // 绕原点(0,0)逆时针旋转
    Console.WriteLine("Rotating around (0,0) counter-clockwise:");
    for(int i=1; i<=8; i++)
    {
        Console.WriteLine(RotatePoint(P, new Point(0, 0), Math.PI / 4 * i, false));
    }
    
    Console.WriteLine();
    // 绕点(2.5,2.5)顺时针旋转
    Console.WriteLine("Rotating around (2.5,2.5) clockwise:");
    for(int i=1; i<=8; i++)
    {
        Console.WriteLine(RotatePoint(P, new Point(2.5, 2.5), Math.PI / 4 * i, true));
    }
    
    Console.ReadLine();
}

运行程序后可观察到坐标随旋转角度周期性变化。例如绕原点逆时针旋转 360度(8个π/4)后,点将回到初始位置。围绕非原点中心旋转时,轨迹为一个以 (2.5, 2.5) 为圆心的圆弧。

以上就是C#实现点绕任意中心旋转的坐标计算的详细内容,更多关于C#几何编程的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表