/// <summary>
/// 结构:表示一个点
/// </summary>
public struct RatePoint
{
//横、纵坐标
public double x, y;
//构造函数
public RatePoint(double x, double y)
{
this.x = x;
this.y = y;
}
//该点到指定点pTarget的距离
public double DistanceTo(RatePoint 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"), ')');
}
}
/// <summary>
/// 计算点P(x,y)与X轴正方向的夹角
/// </summary>
/// <param name="x">横坐标</param>
/// <param name="y">纵坐标</param>
/// <returns>夹角弧度</returns>
private static double radPOX(double x, double y)
{
//P在(0,0)的情况
if (x == 0 && y == 0) return 0;
//P在四个坐标轴上的情况:x正、x负、y正、y负
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 / 2 * 3;
//点在第一、二、三、四象限时的情况
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;
}
/// <summary>
/// 返回点P围绕点A旋转弧度rad后的坐标
/// </summary>
/// <param name="P">待旋转点坐标</param>
/// <param name="A">旋转中心坐标</param>
/// <param name="rad">旋转弧度</param>
/// <param name="isClockwise">true:顺时针/false:逆时针</param>
/// <returns>旋转后坐标</returns>
public static RatePoint RotatePoint(RatePoint P, RatePoint A,
double rad, bool isClockwise = true)
{
//点Temp1
RatePoint Temp1 = new RatePoint(P.x - A.x, P.y - A.y);
//点Temp1到原点的长度
double lenO2Temp1 = Temp1.DistanceTo(new RatePoint(0, 0));
//∠T1OX弧度
double angT1OX = radPOX(Temp1.x, Temp1.y);
//∠T2OX弧度(T2为T1以O为圆心旋转弧度rad)
double angT2OX = angT1OX - (isClockwise ? 1 : -1) * rad;
//点Temp2
RatePoint Temp2 = new RatePoint(
lenO2Temp1 * Math.Cos(angT2OX),
lenO2Temp1 * Math.Sin(angT2OX));
//点Q
return new RatePoint(Temp2.x + A.x, Temp2.y + A.y);
}