椭圆的曲线模拟

圆的模拟只要使用正多边形就可以实现,主要代码如下

  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轴对象就可以求出。然后这些点按椭圆的中心进行偏移,得到的就是最终的模拟点。模拟的结果如下图




随着模拟角度的减小,模拟出的结果越接近椭圆。由于模拟的点已经知道了,所以模拟的线段只要将相邻的两点连接起来就可以得到了,这时如果需要这些线段做一些业务处理也就可以直接使用了。

转载请注明出处。


posted @ 2017-07-21 17:31  _学而时习之  阅读(556)  评论(0编辑  收藏  举报