圆的模拟只要使用正多边形就可以实现,主要代码如下
private void TestCirlce(Graphics g)
{
int n = 36;
var x0 = 500f;
var y0 = 400f;
var r = 50f;
List<PointF> list = SimulateCircle(x0, y0, r, n);
GraphicsPath path = new GraphicsPath();
path.AddPolygon(list.ToArray());
g.DrawPath(Pens.Black, path);
g.DrawEllipse(Pens.Red, new RectangleF(x0 - r, y0 - r, r * 2, r * 2));
}
private List<PointF> SimulateCircle(float x0, float y0, float r, int simulateSideCount)
{
List<PointF> list = new List<PointF>();
for (int i = 0; i < simulateSideCount; i++)
{
var p = CalculateCirlePoint(x0, y0, r, 360 / simulateSideCount * i);
list.Add(p);
}
return list;
}
private PointF CalculateCirlePoint(float x0, float y0, float r, float angle)
{
PointF p = new PointF();
p.X = (float)(x0 + r * Math.Cos(angle * 3.14 / 180));
p.Y = (float)(y0 + r * Math.Sin(angle * 3.14 / 180));
return p;
}
一般圆只要12边的正多边形模拟就差不多可以了,如果觉得不够,可以使用更多的边,比如24边。
基于这样的想法,椭圆也采用类似的方法实现,但由于椭圆上的点不能像圆上的点一样,直接用三角函数求得,所以需要使用方程法来解。
我们知道,椭圆的中心在(0,0)点的时候,其标准方程为 (x*x)/(a*a)+(y*y)/(b*b)=1,而经过(0,0)点的直线方程为y=kx,所以将这两个方程联立,就可以解出x和y.
由于中心在(0,0)的椭圆关于X轴和Y轴都对象,所以我们只要求出椭圆在第一象上的点,第二、三、四象上的点也就随之求出来了。由于椭圆与X轴和Y轴的交点直接由a和b就可以计算出来,所以只要计算非X轴和Y轴的椭圆交点就可以了。代码实现如下
private void TestEllispse(Graphics g)
{
var x0 = 500f;
var y0 = 400f;
var a = 300f;
var b = 200f;
var k = 0f;
var angleStep = 5;
var xList = new List<float>();
var yList = new List<float>();
var x = 0f;
var y = 0f;
for (int angle = angleStep; angle < 90; angle += angleStep)
{
k = (float)Math.Tan(angle * 3.14 / 180);
var a_2 = a * a;
var b_2 = b * b;
var k_2 = k * k;
x = (float)Math.Sqrt(a_2 * b_2 / (b_2 + k_2 * a_2));
y = k * x;
xList.Add(x);
yList.Add(y);
}
var list = new List<PointF>();
list.Add(new PointF(x0 + a, y0));
//第1象限,X>0,Y>0
for (int i = 0; i < xList.Count; i++)
{
list.Add(new PointF(x0 + xList[i], y0 + yList[i]));
}
list.Add(new PointF(x0, y0 + b));
//第2象限,X<0,Y>0
for (int i = xList.Count - 1; i >= 0; i--)
{
list.Add(new PointF(x0 - xList[i], y0 + yList[i]));
}
list.Add(new PointF(x0 - a, y0));
//第3象限,X<0,Y<0
for (int i = 0; i < xList.Count; i++)
{
list.Add(new PointF(x0 - xList[i], y0 - yList[i]));
}
list.Add(new PointF(x0, y0 - b));
//第4象限,X>0,Y<0
for (int i = xList.Count - 1; i >= 0; i--)
{
list.Add(new PointF(x0 + xList[i], y0 - yList[i]));
}
GraphicsPath path = new GraphicsPath();
path.AddPolygon(list.ToArray());
g.DrawPath(Pens.Black, path);
Debug.WriteLine(string.Join(",", list));
}
注意:先求出指定角度下,第1象限上的X和Y,其他象线通过X轴对称和Y轴对象就可以求出。然后这些点按椭圆的中心进行偏移,得到的就是最终的模拟点。模拟的结果如下图
随着模拟角度的减小,模拟出的结果越接近椭圆。由于模拟的点已经知道了,所以模拟的线段只要将相邻的两点连接起来就可以得到了,这时如果需要这些线段做一些业务处理也就可以直接使用了。
转载请注明出处。