• 椭圆的曲线模拟


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

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




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

    转载请注明出处。


  • 相关阅读:
    【Demo 0025】注册/反注册窗体类RegisterClassEx/UnregisterClass
    【Demo 0028】获取窗体信息
    【Demo 0021】窗体创建过程
    FLTK编译安装方法 (转)
    图形学名词解释2(转帖)
    五种开源协议的比较(BSD,Apache,GPL,LGPL,MIT) [网上整理]
    无法定位程序输入点XXXXX于动态链接库qtcore.dll
    图形学名词解释1(转贴)
    几何建模研究领域介绍(名词解释&& 转帖)
    C++ hash_map详细介绍[转]
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7604880.html
Copyright © 2020-2023  润新知