当前位置: 代码迷 >> C# >> C# 在面板panel中画N个圆,并且圆与圆之间互不相交
  详细解决方案

C# 在面板panel中画N个圆,并且圆与圆之间互不相交

热度:9   发布时间:2016-05-05 03:35:35.0
C# 在面板panel中画N个圆,而且圆与圆之间互不相交
在面板上画圆,圆的大小,位置都是随机的,怎么样才能保证每次新添加的圆与之前全部的圆都不相交呢?求知道的大牛们帮帮忙,小弟想了许久也不知该如何解决这个问题
------解决思路----------------------
记录下每个圆心的位置,和半径 。  

再用你新画的这个圆心计算出和其圆心的距离,如果这个距离小于两个圆的半径相加,则有重合部分。
------解决思路----------------------
圆心之间的直线距离大于两个圆的半径之和
------解决思路----------------------
如果圆的半径是已知的(假设为R),基本上流程可能是:

将区域中所有可能的点进行随机次序排序,然后遍历,找到第一个点,使得它与任何圆(如果半径是r)之间的距离(计算两点中间的距离需要几何知识)都不小于 R+r。如果全都不满足,那就没有所谓的“随机位置”了。

这个程序肯定会非常非常地慢。它没有什么优化的处理方法,完全是暴利简单地判断。
------解决思路----------------------
先给个示例代码
        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            var list = new List<Rectangle>();
            var rand = new Random();
            var g = e.Graphics;
            int N = 100; //圆的个数

            for (int i = 0; i < 1000; i++) //限定最多试探次数,以免出现死循环
            {
                var x = rand.Next(0, panel1.Width);
                var y = rand.Next(0, panel1.Height);
                var r = rand.Next(4, 20);
                var rct = new Rectangle(x, y, 2*r, 2*r);

                if (list.IndexOf(rct) < 0) //已经画过的就不画了
                {
                    var rs = list.Where(t => t.IntersectsWith(rct)).ToArray();//这是关键:检查圆控制矩形是否相交
                    if (rs.Length > 0) continue;
                    list.Add(rct);
                    g.DrawEllipse(Pens.Red, rct);
                    if (--N == 0) break;
                }
            }
        }

使用了比较简陋的判别方法:
画园时需要一个控制矩形,所以只要这些控制矩形不想交,那么圆就不会相交(至多相切)
而 C# 已经提供了判别矩形是否相交的方法 IntersectsWith,所以速度不会慢
当然,这个算法会使一些本可以画的地方画不上,但由于都是随机的,所以无碍大局。当圆很多很密时就看出来了
精准一点的还是要通过圆的方程进行判断,计算量要大些,也不一定就慢