zoukankan      html  css  js  c++  java
  • 椭圆的曲线模拟

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

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




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

    转载请注明出处。


  • 相关阅读:
    494 Target Sum 目标和
    493 Reverse Pairs 翻转对
    492 Construct the Rectangle 构建矩形
    491 Increasing Subsequences 递增子序列
    488 Zuma Game 祖玛游戏
    486 Predict the Winner 预测赢家
    485 Max Consecutive Ones 最大连续1的个数
    483 Smallest Good Base
    Django Form组件
    Django Auth组件
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7604880.html
Copyright © 2011-2022 走看看