圆内的随机点

Random points inside a circle

所以我在 Windows 表单应用程序中得到了一个圆圈,并且必须在这个圆圈中放置 20 个随机点。我的想法是将圆圈分成 4 个部分,使其更加平衡。我的问题是这些点都是围绕中间生成的,我不知道如何解决这个问题...

    Graphics g;
    Pen p;
    Random r = new Random();
    int[] KegelX = new int[20];
    int[] KegelY = new int[20];
    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void button1_Click(object sender, EventArgs e)
    {
        Kegelplatzierung();
        p = new Pen(Color.Black);
        g = this.CreateGraphics();
        g.DrawEllipse(p, new Rectangle(50, 50, 400, 400));
        for (int i = 0; i < 20; i++)
        {
            g.DrawEllipse(p, new Rectangle(KegelX[i], KegelY[i], 1, 1));
        }
        p.Dispose();
        g.Dispose();
    }

    private void Kegelplatzierung() {
        for (int i = 0; i < 5; i++)
        {
            bool Kriterium = false;
            while (!Kriterium)
            {
                KegelX[i] = r.Next(50, 250);
                KegelY[i] = r.Next(50, 250);
                if (Math.Sqrt((250 - KegelX[i]) ^ 2 + (KegelY[i] - 250) ^ 2) < 200)
                {
                    Kriterium = true;
                }
            }
        }
        for (int i = 5; i < 10; i++)
        {
            bool Kriterium = false;
            while (!Kriterium)
            {
                KegelX[i] = r.Next(250, 450);
                KegelY[i] = r.Next(50, 250);
                if (Math.Sqrt((KegelX[i] - 250) ^ 2 + (KegelY[i] - 250) ^ 2) < 200)
                {
                    Kriterium = true;
                }
            }
        }
        for (int i = 10; i < 15; i++)
        {
            bool Kriterium = false;
            while (!Kriterium)
            {
                KegelX[i] = r.Next(50, 250);
                KegelY[i] = r.Next(250, 450);
                if (Math.Sqrt((250 - KegelX[i]) ^ 2 + (250 - KegelY[i]) ^ 2) < 200)
                {
                    Kriterium = true;
                }
            }
        }
        for (int i = 15; i < 20; i++)
        {
            bool Kriterium = false;
            while (!Kriterium)
            {
                KegelX[i] = r.Next(250, 450);
                KegelY[i] = r.Next(250, 450);
                if (Math.Sqrt((KegelX[i] - 250) ^ 2 + (250 - KegelY[i]) ^ 2) < 200)
                {
                    Kriterium = true;
                }
            }
        }

    }

示例:http://puu.sh/gB6Dg/e81f8c3486.png http://puu.sh/gB6Ec/306f61424c.png

感谢帮助!

在给定半径的圆内生成一组随机点...

 private void button1_Click(object sender, EventArgs e)
            {
                int radius = 100;
                var p = new Pen(Color.Black);
                var g = this.CreateGraphics();
                g.DrawEllipse(p, 0,0,radius*2, radius*2);
                var pointGen = new RandomPointGenerator();
                var randomPoints = pointGen.GetPointsInACircle(radius, 20);
                p.Color = Color.Red;
                foreach (var point in randomPoints)
                {

                    g.DrawEllipse(p, point.X + radius, point.Y+radius, 2, 2);
                }
            }



public class RandomPointGenerator
    {
        private Random _randy = new Random();
        public List<Point> GetPointsInACircle(int radius, int numberOfPoints)
        {
            List<Point> points = new List<Point>();
            for (int pointIndex = 0; pointIndex < numberOfPoints; pointIndex++)
            {
                int distance = _randy.Next(radius);
                double angleInRadians = _randy.Next(360)/(2 * Math.PI) ;

                int x = (int)(distance * Math.Cos(angleInRadians));
                int y = (int)(distance * Math.Sin(angleInRadians));
                Point randomPoint = new Point(x, y);
                points.Add(randomPoint);
            }
            return points;
        }
    }

您可以通过为每个点选择随机半径和角度来实现。

为了避免将角度分量明显量化为径向辐条,我使用 (double)rand.Next() / int.MaxValue 获取 0 到 1 之间的随机数并将其乘以 2π。

为了避免点在圆心附近聚成一团,我使用 Chris A. 的公式(在 Generate a random point within a circle (uniformly))生成半径:

Random rand = new Random();

private List<Point> GetRandomPoints(double rMax, int nPoints)
{
    var randPoints = new List<Point>();
    for (int i = 0; i < nPoints; i++)
    {
        var r = Math.Sqrt((double)rand.Next() / int.MaxValue) * rMax;
        var theta = (double)rand.Next() / int.MaxValue * 2 * Math.PI;
        randPoints.Add(new Point((int)(r * Math.Cos(theta)), (int)(r * Math.Sin(theta))));
    }
    return randPoints;
}

private void button1_Click(object sender, EventArgs e)
{
    using (Graphics g = this.CreateGraphics())
    {
        using (Pen p = new Pen(Color.Black))
        {
            var left = 50;
            var top = 50;
            var r = 200;
            g.DrawEllipse(p, new Rectangle(left, top, r * 2, r * 2));

            int nPoints = 20;
            var randomPoints = GetRandomPoints(r - 1, nPoints);

            for (int i = 0; i < nPoints; i++)
            {
                g.DrawEllipse(p, new Rectangle(randomPoints[i].X + left + r, randomPoints[i].Y + top + r, 1, 1));
            }
        }
    }
}

要确保对象被干净地处理,您可以使用 using 构造 - 它确保您不会不小心忘记。

通常最好将诸如圆的半径之类的东西分配给一个变量,因为这样您就可以轻松地在一个地方更改它,并且如果您使用有意义的变量名称,代码将更易于阅读。

这是一个输出示例,但半径设置为 100 并生成 200 个点:

这将按照您的计划进行。但是请注意,仅当您确实需要它来平衡非常几个点时,才需要四个象限之间的对称性。对于更大的数字,没有必要,您可以将代码减少到一半左右..!

private void panel2_Paint(object sender, PaintEventArgs e)
{
    int dotsPerQuadrant = 666;
    Random R = new Random();
    Size s1x1 = new System.Drawing.Size(2, 2);
    int radius = 200;
    int rad2 = radius / 2;
    int off = 20;
    Rectangle bounds = new Rectangle(off, off, radius, radius);
    GraphicsPath gp = new GraphicsPath();
    gp.AddEllipse(bounds);
    Rectangle rectQ1 = new Rectangle(off, off, rad2, rad2);
    Rectangle rectQ2 = new Rectangle(off + rad2, off, rad2, rad2);
    Rectangle rectQ3 = new Rectangle(off, off + rad2, rad2, rad2);
    Rectangle rectQ4 = new Rectangle(off + rad2, off + rad2, rad2, rad2);
    List<Rectangle> quadrants = new List<Rectangle> { rectQ1, rectQ2, rectQ3, rectQ4 };
    e.Graphics.Clear(Color.AntiqueWhite);
    e.Graphics.DrawEllipse(Pens.Black, bounds);

    foreach (Rectangle rect in quadrants)
    {
        int count = 0;
        do
        {
            Point p = new Point(rect.X + R.Next(rad2), rect.Y + R.Next(rad2));
            if (gp.IsVisible(p))
            {
                e.Graphics.FillEllipse(Brushes.Red, new Rectangle(p, s1x1));
                count++;
            }
        } while (count < dotsPerQuadrant);
    }

}

这是结果。圆点均匀分布在整个圆圈上,不在中间聚集:

直接代码,无象限;

private void panel2_Paint(object sender, PaintEventArgs e)
{
    int dotstoDraw = 666*4;
    Random R = new Random();
    Size s1x1 = new System.Drawing.Size(2, 2);
    int radius = 200;
    int off = 20;
    Rectangle bounds = new Rectangle(off, off, radius, radius);
    GraphicsPath gp = new GraphicsPath();
    gp.AddEllipse(bounds);

    e.Graphics.Clear(Color.AntiqueWhite);
    e.Graphics.DrawEllipse(Pens.Black, bounds);

    int count = 0;
    do
    {
        Point p = new Point(off + R.Next(radius), off + R.Next(radius));
        if (gp.IsVisible(p))
        {
            e.Graphics.FillEllipse(Brushes.Red, new Rectangle(p, s1x1));
            count++;
        }
    } while (count < dotstoDraw);
 }

问题是在 C# 中,^ 是逻辑异或运算符。您需要改用 Math.Pow。所以...

if (Math.Sqrt(Math.Pow(250 - KegelX[i], 2) + Math.Pow(KegelY[i] - 250, 2)) < 200)

等等。