圆的模拟只要使用正多边形就可以实现,主要代码如下
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轴对象就可以求出。然后这些点按椭圆的中心进行偏移,得到的就是最终的模拟点。模拟的结果如下图
随着模拟角度的减小,模拟出的结果越接近椭圆。由于模拟的点已经知道了,所以模拟的线段只要将相邻的两点连接起来就可以得到了,这时如果需要这些线段做一些业务处理也就可以直接使用了。
转载请注明出处。