using System;
using System.Collections.Generic;
using System.Text;
using CommonLang.IO;
using CommonLang.ByteOrder;
using CommonLang;

namespace CommonLang.Vector
{
	public interface IPosBase
	{
		float X { get; }
		float Y { get; }
	}

	public interface IVector2 : IPosBase
	{
		void SetX(float value);
		void SetY(float value);
		void AddX(float value);
		void AddY(float value);
	}
	public interface IRoundObject : IVector2
	{
		//float X { get; set; }
		//float Y { get; set; }
		/// <summary>
		/// 半径
		/// </summary>
		float RadiusSize { get; }
	}
	public interface IPositionObject : IPosBase
	{
		/// <summary>
		/// 方向
		/// </summary>
		float Direction { get; }
		/// <summary>
		/// 半径
		/// </summary>
		float RadiusSize { get; }
	}

	/// <summary>
	/// 2D向量
	/// </summary>
	public class Vector2 : IVector2, ICloneable
	{
		private float x;
		private float y;
		public float X { get { return this.x; } }
		public float Y { get { return this.y; } }

		public void SetX(float value)
		{
			this.x = value;
		}

		public void SetY(float value)
		{
			this.y = value;
		}

		public void AddX(float value)
		{
			this.x += value;
		}

		public void AddY(float value)
		{
			this.y += value;
		}

		public Vector2()
		{
			this.x = 0;
			this.y = 0;
		}
		public Vector2(float _x, float _y)
		{
			this.x = _x;
			this.y = _y;
		}

		public object Clone()
		{
			return new Vector2(x, y);
		}

		public override bool Equals(object obj)
		{
			if (obj is Vector2)
			{
				Vector2 v = (Vector2)obj;
				return X == v.X && Y == v.Y;
			}
			return false;
		}
		public bool Equals(Vector2 v)
		{
			return v.x == x && v.y == y;
		}
		public static bool Equals(Vector2 a, Vector2 b)
		{
			if (a != null && b != null)
			{
				return a.x == b.x && a.y == b.y;
			}
			return a == b;
		}

		public override int GetHashCode()
		{
			return X.GetHashCode() ^ Y.GetHashCode();
		}

		public override string ToString()
		{
			return X + ", " + Y;
		}

		public string ToString(bool rounded)
		{
			if (rounded)
			{
				return (int)Math.Round(X) + ", " + (int)Math.Round(Y);
			}
			else
			{
				return ToString();
			}
		}


		public static Vector2 operator *(Vector2 value1, float value2)
		{
			value1.SetX(value1.X * value2);
			value1.SetY(value1.Y * value2);
			return value1;
		}
		#region IExternalizable 成员

		public void WriteExternal(IOutputStream output)
		{
			output.PutF32(x);
			output.PutF32(y);
		}

		public void ReadExternal(IInputStream input)
		{
			this.x = input.GetF32();
			this.y = input.GetF32();
		}
		#endregion

	}
	/// <summary>
	/// 2D向量
	/// </summary>
	public struct TVector2 : IVector2
	{
		public static readonly TVector2 Zero = new TVector2(0, 0);

		private float x;
		private float y;
		public float X { get { return this.x; } }
		public float Y { get { return this.y; } }
		public void SetX(float value)
		{
			this.x = value;
		}

		public void SetY(float value)
		{
			this.y = value;
		}

		public void AddX(float value)
		{
			this.x += value;
		}

		public void AddY(float value)
		{
			this.y += value;
		}

		public TVector2(float _x, float _y)
		{
			this.x = _x;
			this.y = _y;
		}

		public override bool Equals(object obj)
		{
			if (obj is Vector2)
			{
				Vector2 v = (Vector2)obj;
				return X == v.X && Y == v.Y;
			}
			return false;
		}
		public bool Equals(IVector2 v)
		{
			return v.X == X && v.Y == Y;
		}

		public override int GetHashCode()
		{
			return X.GetHashCode() ^ Y.GetHashCode();
		}

		public override string ToString()
		{
			return X + ", " + Y;
		}

		public string ToString(bool rounded)
		{
			if (rounded)
			{
				return (int)Math.Round(X) + ", " + (int)Math.Round(Y);
			}
			else
			{
				return ToString();
			}
		}

		#region IExternalizable 成员

		public void WriteExternal(IOutputStream output)
		{
			output.PutF32(x);
			output.PutF32(y);
		}

		public void ReadExternal(IInputStream input)
		{
			this.x = input.GetF32();
			this.y = input.GetF32();
		}

		#endregion




		public float Magnitude
		{
			get
			{
				return (float)Math.Sqrt(X * X + Y * Y);
			}
		}

		public void Normalize()
		{
			float magnitude = Magnitude;
			this.x = X / magnitude;
			this.y = Y / magnitude;
		}

		public TVector2 GetNormalized()
		{
			float magnitude = Magnitude;

			return new TVector2(X / magnitude, Y / magnitude);
		}

		public float DotProduct(TVector2 vector)
		{
			return this.X * vector.X + this.Y * vector.Y;
		}

		public float DistanceTo(TVector2 vector)
		{
			return (float)Math.Sqrt(Math.Pow(vector.X - this.X, 2) + Math.Pow(vector.Y - this.Y, 2));
		}

		public static TVector2 operator +(TVector2 a, TVector2 b)
		{
			return new TVector2(a.X + b.X, a.Y + b.Y);
		}

		public static TVector2 operator -(TVector2 a)
		{
			return new TVector2(-a.X, -a.Y);
		}

		public static TVector2 operator -(TVector2 a, TVector2 b)
		{
			return new TVector2(a.X - b.X, a.Y - b.Y);
		}

		public static TVector2 operator *(TVector2 a, float b)
		{
			return new TVector2(a.X * b, a.Y * b);
		}

		public static TVector2 operator *(TVector2 a, int b)
		{
			return new TVector2(a.X * b, a.Y * b);
		}

		public static TVector2 operator *(TVector2 a, double b)
		{
			return new TVector2((float)(a.X * b), (float)(a.Y * b));
		}
	}

	/// <summary>
	/// 2D极坐标向量
	/// </summary>
	public class Polar2 : ICloneable
	{
		public float direction;
		public float distance;

		public Polar2()
		{
		}

		public Polar2(float _direction, float _distance)
		{
			this.direction = _direction;
			this.distance = _distance;
		}

		public bool Equals(Polar2 v)
		{
			return v.direction == this.direction && v.distance == this.distance;
		}

		public object Clone()
		{
			return new Polar2(direction, distance);
		}

		#region IExternalizable 成员

		public void WriteExternal(IOutputStream output)
		{
			output.PutF32(direction);
			output.PutF32(distance);
		}

		public void ReadExternal(IInputStream input)
		{
			this.direction = input.GetF32();
			this.distance = input.GetF32();
		}

		#endregion
	}
	public struct TPolar2
	{
		public float direction;
		public float distance;

		public TPolar2(float _direction, float _distance)
		{
			this.direction = _direction;
			this.distance = _distance;
		}

		public bool Equals(TPolar2 v)
		{
			return v.direction == this.direction && v.distance == this.distance;
		}

		#region IExternalizable 成员

		public void WriteExternal(IOutputStream output)
		{
			output.PutF32(direction);
			output.PutF32(distance);
		}

		public void ReadExternal(IInputStream input)
		{
			this.direction = input.GetF32();
			this.distance = input.GetF32();
		}

		#endregion
	}


	public class Line2 : ICloneable
	{
		readonly public Vector2 p = new Vector2();
		readonly public Vector2 q = new Vector2();

		public Line2()
		{
		}

		public Line2(float x0, float y0, float x1, float y1)
		{
			p.SetX(x0);
			p.SetY(y0);
			q.SetX(x1);
			q.SetY(y1);
		}

		public float getMinX()
		{
			return Math.Min(p.X, q.X);
		}

		public float getMaxX()
		{
			return Math.Max(p.X, q.X);
		}

		public float getMinY()
		{
			return Math.Min(p.Y, q.Y);
		}

		public float getMaxY()
		{
			return Math.Max(p.Y, q.Y);
		}

		public object Clone()
		{
			return new Line2(p.X, p.Y, q.X, q.Y);
		}

		#region IExternalizable 成员

		public void WriteExternal(IOutputStream output)
		{
			output.PutF32(p.X);
			output.PutF32(p.Y);
			output.PutF32(q.X);
			output.PutF32(q.Y);
		}

		public void ReadExternal(IInputStream input)
		{
			p.SetX(input.GetF32());
			p.SetY(input.GetF32());
			q.SetX(input.GetF32());
			q.SetY(input.GetF32());
		}

		#endregion
	}
	public struct TLine2
	{
		public TVector2 p;
		public TVector2 q;

		public TLine2(float x0, float y0, float x1, float y1)
		{
			p = new TVector2();
			q = new TVector2();

			p.SetX(x0);
			p.SetY(y0);
			q.SetX(x1);
			q.SetY(y1);
		}

		public float getMinX()
		{
			return Math.Min(p.X, q.X);
		}

		public float getMaxX()
		{
			return Math.Max(p.X, q.X);
		}

		public float getMinY()
		{
			return Math.Min(p.Y, q.Y);
		}

		public float getMaxY()
		{
			return Math.Max(p.Y, q.Y);
		}

		#region IExternalizable 成员

		public void WriteExternal(IOutputStream output)
		{
			output.PutF32(p.X);
			output.PutF32(p.Y);
			output.PutF32(q.X);
			output.PutF32(q.Y);
		}

		public void ReadExternal(IInputStream input)
		{
			p.SetX(input.GetF32());
			p.SetY(input.GetF32());
			q.SetX(input.GetF32());
			q.SetY(input.GetF32());
		}

		#endregion
	}


	public static class MathVector
	{


		/**
         * 移动指定偏移
         * @param v
         * @param dx x距离
         * @param dy y距离
         */
		public static void move(IVector2 v, float dx, float dy)
		{
			v.AddX(dx);
			v.AddY(dy);
		}

		/**
         * 通过极坐标来移动
         * @param v
         * @param degree 弧度
         * @param distance 距离
         */
		public static void movePolar(IVector2 v, float degree, float distance)
		{
			float dx = (float)(Math.Cos(degree) * distance);
			float dy = (float)(Math.Sin(degree) * distance);
			move(v, dx, dy);
		}

		public static void movePolar(ref float x, ref float y, float degree, float distance)
		{
			x += (float)(Math.Cos(degree) * distance);
			y += (float)(Math.Sin(degree) * distance);
		}

		public static void movePolarExt(ref Vector2 pos, float degree, float distance)
		{
			pos.AddX((float)(Math.Cos(degree) * distance));
			pos.AddY((float)(Math.Sin(degree) * distance));
		}

		public static void movePolarExt(ref TVector2 pos, float degree, float distance)
		{
			pos.AddX((float)(Math.Cos(degree) * distance));
			pos.AddY((float)(Math.Sin(degree) * distance));
		}

		/**
         * 通过极坐标来移动
         * @param v
         * @param degree 弧度
         * @param speed  速度 (单位距离/秒)
         * @param interval_ms 毫秒时间
         */
		public static void movePolar(IVector2 v, float degree, float speed, float interval_ms)
		{
			float distance = getDistanceSpeedTime(speed, interval_ms);
			movePolar(v, degree, distance);
		}

		public static void movePolar(ref float x, ref float y, float degree, float speed, float interval_ms)
		{
			float distance = getDistanceSpeedTime(speed, interval_ms);
			movePolar(ref x, ref y, degree, distance);
		}

		public static void movePolar(ref Vector2 pos, float degree, float speed, float interval_ms)
		{
			float distance = getDistanceSpeedTime(speed, interval_ms);
			movePolarExt(ref pos, degree, distance);
		}


		/**
         * 向目标移动
         * @param v
         * @param x 目标x
         * @param y 目标y
         * @return 是否到达目的地
         */
		public static bool moveTo(IVector2 v, float dx, float dy, float distance)
		{
			float ddx = dx - v.X;
			float ddy = dy - v.Y;
			if (Math.Abs(ddx) < distance && Math.Abs(ddy) < distance)
			{
				v.SetX(dx);
				v.SetY(dy);
				return true;
			}
			else
			{
				float angle = (float)Math.Atan2(ddy, ddx);
				movePolar(v, angle, distance);
				return false;
			}
		}
		public static bool moveTo(ref float x, ref float y, float dx, float dy, float distance)
		{
			float ddx = dx - x;
			float ddy = dy - y;
			if (Math.Abs(ddx) < distance && Math.Abs(ddy) < distance)
			{
				x = (dx);
				y = (dy);
				return true;
			}
			else
			{
				float angle = (float)Math.Atan2(ddy, ddx);
				movePolar(ref x, ref y, angle, distance);
				return false;
			}
		}

		public static bool moveToX(IVector2 v, float x, float distance)
		{
			float ddx = x - v.X;
			if (Math.Abs(ddx) < distance)
			{
				v.SetX(x);
				return true;
			}
			else
			{
				if (ddx > 0)
				{
					v.AddX(distance);
				}
				else
				{
					v.AddX(-distance);
				}
				return false;
			}
		}
		public static bool moveToY(IVector2 v, float y, float distance)
		{
			float ddy = y - v.Y;
			if (Math.Abs(ddy) < distance)
			{
				v.SetY(y);
				return true;
			}
			else
			{
				if (ddy > 0)
				{
					v.AddY(distance);
				}
				else
				{
					v.AddY(-distance);
				}
				return false;
			}
		}

		public static void scale(IVector2 v, float scale)
		{
			v.SetX(v.X * scale);
			v.SetY(v.Y * scale);
		}
		public static void scale(IVector2 v, float scale_x, float scale_y)
		{
			v.SetX(v.X * scale_x);
			v.SetY(v.Y * scale_y);
		}
		public static void scale(ref float x, ref float y, float scale_x, float scale_y)
		{
			x = (x * scale_x);
			y = (y * scale_y);
		}

		public static void rotate(IVector2 v, float degree)
		{
			float cos_v = (float)Math.Cos(degree);
			float sin_v = (float)Math.Sin(degree);
			float x = (v.X) * cos_v - (v.Y) * sin_v;
			float y = (v.Y) * cos_v + (v.X) * sin_v;
			v.SetX(x);
			v.SetY(y);
		}
		public static void rotate(IVector2 v, IVector2 p0, float degree)
		{
			float dx = v.X - p0.X;
			float dy = v.Y - p0.Y;
			float cos_v = (float)Math.Cos(degree);
			float sin_v = (float)Math.Sin(degree);
			float x = p0.X + dx * cos_v - dy * sin_v;
			float y = p0.Y + dy * cos_v + dx * sin_v;
			v.SetX(x);
			v.SetY(y);
		}
		public static void rotate(IVector2 v, float px, float py, float degree)
		{
			float dx = v.X - px;
			float dy = v.Y - py;
			float cos_v = (float)Math.Cos(degree);
			float sin_v = (float)Math.Sin(degree);
			float x = px + dx * cos_v - dy * sin_v;
			float y = py + dy * cos_v + dx * sin_v;
			v.SetX(x);
			v.SetY(y);
		}
		public static void rotate(ref float x, ref float y, float px, float py, float degree)
		{
			float dx = x - px;
			float dy = y - py;
			float cos_v = (float)Math.Cos(degree);
			float sin_v = (float)Math.Sin(degree);
			float rx = px + dx * cos_v - dy * sin_v;
			float ry = py + dy * cos_v + dx * sin_v;
			x = (rx);
			y = (ry);
		}

		public static float getDirection(float d)
		{
			if (d > 0)
			{
				return 1;
			}
			if (d < 0)
			{
				return -1;
			}
			return 0;
		}

		/**
         * 得到速度和时间产生的距离
         * @param speed 速度 (单位距离/秒)
         * @param interval_ms 毫秒时间
         * @return
         */
		public static float getDistanceSpeedTime(float speed, float interval_ms)
		{
			float rate = interval_ms / 1000f;
			return speed * rate;
		}

		public static float getDistance(float x1, float y1, float x2, float y2)
		{
			float r1 = x1 - x2;
			float r2 = y1 - y2;
			return (float)Math.Sqrt(r1 * r1 + r2 * r2);
		}
		public static float getDistanceSquare(float x1, float y1, float x2, float y2)
		{
			float r1 = x1 - x2;
			float r2 = y1 - y2;
			return r1 * r1 + r2 * r2;
		}
		public static float getDistance(IVector2 v1, IVector2 v2)
		{
			float r1 = v1.X - v2.X;
			float r2 = v1.Y - v2.Y;
			return (float)Math.Sqrt(r1 * r1 + r2 * r2);
		}
		public static float getDistanceSquare(IVector2 v1, IVector2 v2)
		{
			float r1 = v1.X - v2.X;
			float r2 = v1.Y - v2.Y;
			return (r1 * r1 + r2 * r2);
		}
		/// <summary>
		/// 得到弧度
		/// </summary>
		/// <param name="dx">x向量</param>
		/// <param name="dy">y向量</param>
		/// <returns></returns>
		public static float getDegree(float dx, float dy)
		{
			return (float)Math.Atan2(dy, dx);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="x1"></param>
		/// <param name="y1"></param>
		/// <param name="x2"></param>
		/// <param name="y2"></param>
		/// <returns></returns>
		public static float getDegree(float x1, float y1, float x2, float y2)
		{
			return (float)Math.Atan2(y2 - y1, x2 - x1);
		}

		/**
         * 得到弧度
         * @param v 向量
         * @return
         */
		public static float getDegree(IVector2 v)
		{
			return (float)Math.Atan2(v.Y, v.X);
		}
		public static float getDegree(IVector2 a, IVector2 b)
		{
			return (float)Math.Atan2(b.Y - a.Y, b.X - a.X);
		}


		/**
         * 将2个向量相加得到一个新的向量
         * @param a
         * @param b
         * @return
         */
		public static Vector2 vectorAdd(IVector2 a, IVector2 b)
		{
			Vector2 v = new Vector2();
			v.SetX(a.X + b.X);
			v.SetY(a.Y + b.Y);
			return v;
		}

		/**
         * 将2个向量相减得到一个新的向量
         * @param a
         * @param b
         * @return
         */
		public static Vector2 vectorSub(IVector2 a, IVector2 b)
		{
			Vector2 v = new Vector2();
			v.SetX(a.X - b.X);
			v.SetY(a.Y - b.Y);
			return v;
		}

		/**
         * 将一个向量加上新的向量,得到一个新的向量
         * @param a
         * @param degree
         * @param distance
         * @return
         */
		public static Vector2 vectorAdd(IVector2 a, float degree, float distance)
		{
			Vector2 v = new Vector2();
			v.SetX(a.X);
			v.SetY(a.Y);
			movePolar(v, degree, distance);
			return v;
		}

		/**
         * 把一个向量向自己本身的方向相加,得到一个新的向量
         * @param a
         * @param distance
         * @return
         */
		public static Vector2 vectorAdd(IVector2 a, float distance)
		{
			Vector2 v = new Vector2();
			v.SetX(a.X);
			v.SetY(a.Y);
			movePolar(v, getDegree(v), distance);
			return v;
		}

		/**
         * 将一个向量缩放一定比率后,得到一个新的向量
         * @param a
         * @param scale
         * @return
         */
		public static Vector2 vectorScale(IVector2 a, float scale)
		{
			Vector2 v = new Vector2();
			v.SetX(a.X * scale);
			v.SetY(a.Y * scale);
			return v;
		}


		public static float vectorDot(IVector2 v1, IVector2 v2)
		{
			return v1.X * v2.X + v1.Y * v2.Y;
		}
		public static float vectorDot(float x1, float y1, float x2, float y2)
		{
			return x1 * x2 + y1 * y2;
		}

		/// <summary>
		/// 挤压移动单位,某个单位在集合中移动,碰撞并挤开其他单位
		/// </summary>
		/// <param name="vectors"></param>
		/// <param name="obj"></param>
		/// <param name="angle"></param>
		/// <param name="distance"></param>
		/// <param name="depth"></param>
		/// <param name="max_depth"></param>
		public static void moveImpact(ICollection<IRoundObject> vectors, IRoundObject obj, float angle, float distance, int depth, int max_depth)
		{
			float dx = (float)(Math.Cos(angle) * distance);
			float dy = (float)(Math.Sin(angle) * distance);
			obj.AddX(dx);
			obj.AddY(dy);
			if (depth < max_depth)
			{
				foreach (IRoundObject o in vectors)
				{
					if (!o.Equals(obj))
					{
						float dr = MathVector.getDistance(o, obj) - o.RadiusSize - obj.RadiusSize;
						if (dr < 0)
						{
							float ta = MathVector.getDegree(obj.X, obj.Y, o.X, o.Y);
							moveImpact(vectors, o, ta, -dr, depth + 1, max_depth);
						}
					}
				}
			}
		}
	}

	public static class VectorGroupHelper
	{
		public static void GetCenterOf<T>(ICollection<T> vectors, out float cx, out float cy) where T : IVector2
		{
			if (vectors.Count == 0)
			{
				cx = 0;
				cy = 0;
			}
			else
			{
				float min_x = float.MaxValue;
				float max_x = float.MinValue;
				float min_y = float.MaxValue;
				float max_y = float.MinValue;
				foreach (T a in vectors)
				{
					min_x = Math.Min(min_x, a.X);
					max_x = Math.Max(max_x, a.X);
					min_y = Math.Min(min_y, a.Y);
					max_y = Math.Max(max_y, a.Y);
				}
				cx = min_x + (max_x - min_x) / 2f;
				cy = min_y + (max_y - min_y) / 2f;
			}
		}

		public static void MoveImpactInner<T>(ICollection<T> vectors, T obj, float spacing_size, float angle, float distance, int depth, int max_depth) where T : IVector2
		{
			float dx = (float)(Math.Cos(angle) * distance);
			float dy = (float)(Math.Sin(angle) * distance);
			obj.AddX(dx);
			obj.AddY(dy);
			if (depth < max_depth)
			{
				float dr2 = spacing_size * 2;
				foreach (T o in vectors)
				{
					if (!o.Equals(obj))
					{
						float dr = MathVector.getDistance(o, obj) - dr2;
						if (dr < 0)
						{
							float ta = MathVector.getDegree(obj.X, obj.Y, o.X, o.Y);
							MoveImpactInner(vectors, o, spacing_size, ta, -dr, depth + 1, max_depth);
						}
					}
				}
			}
		}

		/// <summary>
		/// 随机调整每个点,
		/// 使得距离都最小保持在spacing_size
		/// </summary>
		public static void DistributeSpacingSizeRandom<T>(IVector2 center, ICollection<T> vectors, float spacing_size, Random random) where T : IVector2
		{
			foreach (T o in vectors)
			{
				MoveImpactInner<T>(vectors, o, spacing_size, (float)(random.NextDouble() * CMath.PI_MUL_2), 0, 0, 1);
			}
		}
		/// <summary>
		/// 按正方形调整每个点,
		/// 使得距离都最小保持在spacing_size
		/// </summary>
		public static void DistributeSpacingSizeSquare<T>(IVector2 center, ICollection<T> vectors, float spacing_size) where T : IVector2
		{
			float cx = center.X;
			float cy = center.Y;
			int row_count = (int)Math.Round(Math.Sqrt(vectors.Count));
			//GetCenterOf(vectors, out cx, out cy);
			float sx = cx - (row_count - 1) * spacing_size / 2;
			float sy = cy - (vectors.Count / row_count - 1) * spacing_size / 2;
			int i = 0;
			foreach (T o in vectors)
			{
				int x = i % row_count;
				int y = i / row_count;
				o.SetX(sx + x * spacing_size);
				o.SetY(sy + y * spacing_size);
				i++;
			}
		}
		/// <summary>
		/// 按圆形调整每个点,
		/// 使得距离都最小保持在spacing_size
		/// </summary>
		public static void DistributeSpacingSizeRound<T>(IVector2 center, ICollection<T> vectors, float spacing_size) where T : IVector2
		{
			float cx = center.X;
			float cy = center.Y;
			int count = vectors.Count;
			T[] array = new T[count];
			vectors.CopyTo(array, 0);
			int cycle = 0;
			int i = 0;
			while (i < count)
			{
				if (i == 0)
				{
					array[i].SetX(cx);
					array[i].SetY(cy);
					i++;
				}
				else
				{
					float cr = spacing_size * cycle;
					float clen = cr * 2 * CMath.PI_F;
					int ccount = (int)(clen / spacing_size);
					float cangle = CMath.PI_MUL_2 / ccount;
					for (int j = 0; (j < ccount) && (i < count); j++)
					{
						float da = cangle * j;
						array[i].SetX(cx + (float)Math.Cos(da) * cr);
						array[i].SetY(cy + (float)Math.Sin(da) * cr);
						i++;
					}
				}
				cycle++;
			}
		}
		/// <summary>
		/// 按环形调整每个点,
		/// 使得距离都最小保持在spacing_size
		/// </summary>
		public static void DistributeSpacingSizeCycle<T>(IVector2 center, ICollection<T> vectors, float spacing_size) where T : IVector2
		{
			float cx = center.X;
			float cy = center.Y;
			int count = vectors.Count;
			float total_len = count * spacing_size;
			float total_r = total_len / CMath.PI_F / 2f;
			float sangle = CMath.PI_MUL_2 / count;
			int i = 0;
			foreach (T o in vectors)
			{
				float da = sangle * i;
				o.SetX(cx + (float)Math.Cos(da) * total_r);
				o.SetY(cy + (float)Math.Sin(da) * total_r);
				i++;
			}
		}
		/// <summary>
		/// 按蜂窝状调整每个点,
		/// 使得距离都最小保持在spacing_size
		/// </summary>
		public static void DistributeSpacingSizeBeehive<T>(IVector2 center, ICollection<T> vectors, float spacing_size) where T : IVector2
		{
			float cx = center.X;
			float cy = center.Y;
			int count = vectors.Count;
			T[] array = new T[count];
			vectors.CopyTo(array, 0);
			int cycle = 0;
			int i = 0;
			float d_angle = CMath.PI_MUL_2 / 6;
			while (i < count)
			{
				if (i == 0)
				{
					array[i].SetX(cx);
					array[i].SetY(cy);
					i++;
				}
				else
				{
					float c_r = spacing_size * cycle;
					for (int j = 0; (j < 6) && (i < count); j++)
					{
						float s_angle = d_angle * j;
						float s_x = cx + (float)Math.Cos(s_angle) * c_r;
						float s_y = cy + (float)Math.Sin(s_angle) * c_r;
						float b_angle = s_angle + d_angle * 2;
						for (int aj = 0; (aj < cycle) && (i < count); aj++)
						{
							float blen = aj * spacing_size;
							array[i].SetX(s_x + (float)Math.Cos(b_angle) * blen);
							array[i].SetY(s_y + (float)Math.Sin(b_angle) * blen);
							i++;
						}
					}
				}
				cycle++;
			}
		}

		/// <summary>
		/// 直线
		/// 使得距离都最小保持在spacing_size
		/// </summary>
		public static void DistributeSpacingSizeLine<T>(IVector2 center, ICollection<T> vectors, float spacing_size) where T : IVector2
		{
			int count = vectors.Count / 2;
			float statX = center.X - spacing_size * count;
			float startY = center.Y - spacing_size * count;
			if (vectors.Count % 2 != 0)
			{
				statX += spacing_size / 2;
				startY = spacing_size / 2;
			}

			int i = 0;
			foreach (T o in vectors)
			{
				o.SetX(statX + i * spacing_size);
				o.SetY(startY + i * spacing_size);
				i++;
			}
		}
	}
}