圆上的位置控制

时间:2018-06-25 16:03:25

标签: c# winforms math drawing trigonometry

我试图将面板(在本例中为9个)散布在我绘制的圆上。

我正在使用c#winforms。

我已经尝试了许多代码变体,但是没有得到想要的东西,开始感到困惑。

最终我想要这样的东西: Manually spread panels

我不确定如何使用角度将面板的中心放在圆上的相应点上。 这是我的代码:

public partial class Form1 : Form
{
    List<Panel> plist = new List<Panel>();
    Rectangle circ_rect = new Rectangle();
    const int Num_Screens = 9;
    const int margin = 15;

    public Form1()
    {
        InitializeComponent();
        WindowState = FormWindowState.Maximized;
    }

    private void Generate_Panels()
    {
        for (int i = 0; i < 9; i++)
        {
            Panel p = new Panel();
            p.BackColor = Color.LightSkyBlue;
            p.Size = new Size(250, 150);
            p.BorderStyle = BorderStyle.FixedSingle;
            p.Name = "panel_" + ((i + 1).ToString());
            plist.Add(p);
        }
    }

    private void Generate_Circle()
    {
        //Create panels
        Generate_Panels();

        //Set circle coord
        Point circ_center = new Point(Width / 2, Height / 2);
        Size circ_Size = new Size(Height - margin, Height - margin);
        circ_center = new Point((circ_center.X - (circ_Size.Width  / 2)), 
                                (circ_center.Y - (circ_Size.Height / 2)));
        circ_rect = new Rectangle(circ_center, circ_Size);

        float radius = circ_Size.Width / 2;
        float angle = 0.0f;
        Point loc = Point.Empty;
        Point rect_center = Point.Empty;

        for (int i = 0; i < plist.Count; i++)
        {
            rect_center = new Point((plist[i].Width / 2), (plist[i].Height / 2));
            angle = 360 * ((i + 1f) / 9);
            loc.X = (int)(radius * Math.Cos(angle * Math.PI / 180)) + circ_center.X;
            loc.Y = (int)(radius * Math.Sin(angle * Math.PI / 180)) + circ_center.Y;

            plist[i].Location = new Point(loc.X - (plist[i].Width  / 2) + circ_rect.X,
                                          loc.Y - (plist[i].Height / 2) + circ_rect.Y);

            this.Controls.Add(plist[i]);
        }
    }

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        e.Graphics.DrawEllipse(Pens.Red, circ_rect);
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        Generate_Circle();

    }
}

1 个答案:

答案 0 :(得分:0)

在直角坐标系中,以r作为中心为(0,0)的圆的半径,我们可以根据角度计算圆上a的坐标:

  • x = r * cos(degree)y = r * sin(degree)

在C#SinCos方法中,接受弧度,因此我们应使用以下公式将度转换为弧度。

  • radians = Math.PI * degree / 180.0

下一步是将笛卡尔坐标系值转换为形式坐标值:

  • panel.X = x + center.X - panel.Width/2
  • panel.Y = center.Y - y - panel.Height/2

下一步是计算角度。您可以手动设置角度,也可以通过将角度设置为起始角度(如90)并向该角度添加一个值(如40、360 / count)作为步长来计算角度。

enter image description here

示例

public partial class Form1 : Form {
    Rectangle circle;
    List<Panel> panels;
    List<int> angles;
    public Form1() {
        InitializeComponent();
        ResizeRedraw = true;
        angles = Enumerable.Range(0, 9).Select(x => 90 + x * 40).ToList();
        panels = Enumerable.Range(0, 9).Select(x => new Panel() {
            Size = new Size(100, 40),
            BackColor = Color.LightSkyBlue
        }).ToList();
        this.Controls.AddRange(panels.ToArray());
    }
    protected override void OnLayout(LayoutEventArgs levent) {
        base.OnLayout(levent);
        int padding = 50;
        int radius = Math.Min(ClientSize.Width, ClientSize.Height) / 2 - padding;
        Point center = new Point(ClientSize.Width / 2, ClientSize.Height / 2);
        circle = new Rectangle(center.X - radius, center.Y - radius,
             2 * radius, 2 * radius);
        for (int i = 0; i < 9; i++) {
            var x = (int)(radius * Math.Cos(Math.PI * angles[i] / 180.0)) + center.X;
            var y = center.Y - (int)(radius * Math.Sin(Math.PI * angles[i] / 180.0));
            panels[i].Left = x - (panels[i].Width / 2);
            panels[i].Top = y - (panels[i].Height / 2);
        }
    }
    protected override void OnPaint(PaintEventArgs e) {
        base.OnPaint(e);
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        e.Graphics.DrawEllipse(Pens.Red, circle);
    }
}