Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transcribing a polygon on a circle

i am currently try to inscribe diagonals of a decagon inside a circle

like this enter image description here

in c# my approach would be creating a circle

e.Graphics.DrawEllipse(myPen, 0, 0, 100, 100);

and draw lines inside using

 e.Graphics.DrawLine(myPen, 20, 5, 50, 50);

after that i would draw a decagon polygon.

currently im stuck at how to divide the circle into 10 parts/ finding the correct coordiantes of the points on the circumference of the circles because im not good in math, i want to know how would i know the next point in a circumference of the circle the size of my circle is indicated above.
and also i want also to ask a better approach for my problem.

Thank you :)

like image 951
Albert Laure Avatar asked Oct 06 '13 15:10

Albert Laure


3 Answers

Just for grits and shins, here's a generic implementation that will inscribe an X-sided polygon into the Rectangle you pass it. Note that in this approach I'm not actually calculating any absolute points. Instead, I am translating the origin, rotating the surface, and drawing the lines only with respect to the origin using a fixed length and an angle. This is repeated in a loop to achieve the end result below, and is very similar to commanding the Turtle in Logo:

Inscribed Polygon

public partial class Form1 : Form
{

    PictureBox pb = new PictureBox();
    NumericUpDown nud = new NumericUpDown();

    public Form1()
    {
        InitializeComponent();

        this.Text = "Inscribed Polygon Demo";

        TableLayoutPanel tlp = new TableLayoutPanel();
        tlp.RowCount = 2;
        tlp.RowStyles.Clear();
        tlp.RowStyles.Add(new RowStyle(SizeType.AutoSize));
        tlp.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
        tlp.ColumnCount = 2;
        tlp.ColumnStyles.Clear();
        tlp.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
        tlp.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
        tlp.Dock = DockStyle.Fill;
        this.Controls.Add(tlp);

        Label lbl = new Label();
        lbl.Text = "Number of Sides:";
        lbl.TextAlign = ContentAlignment.MiddleRight;
        tlp.Controls.Add(lbl, 0, 0);

        nud.Minimum = 3;
        nud.Maximum = 20;
        nud.AutoSize = true;
        nud.ValueChanged += new EventHandler(nud_ValueChanged);
        tlp.Controls.Add(nud, 1, 0);

        pb.Dock = DockStyle.Fill;
        pb.Paint += new PaintEventHandler(pb_Paint);
        pb.SizeChanged += new EventHandler(pb_SizeChanged);
        tlp.SetColumnSpan(pb, 2);
        tlp.Controls.Add(pb, 0, 1);
    }

    void nud_ValueChanged(object sender, EventArgs e)
    {
        pb.Refresh();
    }

    void pb_SizeChanged(object sender, EventArgs e)
    {
        pb.Refresh();
    }

    void pb_Paint(object sender, PaintEventArgs e)
    {
        // make circle centered and 90% of PictureBox size:
        int Radius = (int)((double)Math.Min(pb.ClientRectangle.Width, pb.ClientRectangle.Height) / (double)2.0 * (double).9);
        Point Center = new Point((int)((double)pb.ClientRectangle.Width / (double)2.0), (int)((double)pb.ClientRectangle.Height / (double)2.0));
        Rectangle rc = new Rectangle(Center, new Size(1, 1));
        rc.Inflate(Radius, Radius);

        InscribePolygon(e.Graphics, rc, (int)nud.Value);
    }

    private void InscribePolygon(Graphics G, Rectangle rc, int numSides)
    {
        if (numSides < 3)
            throw new Exception("Number of sides must be greater than or equal to 3!");

        float Radius = (float)((double)Math.Min(rc.Width, rc.Height) / 2.0);
        PointF Center = new PointF((float)(rc.Location.X + rc.Width / 2.0), (float)(rc.Location.Y + rc.Height / 2.0));
        RectangleF rcF = new RectangleF(Center, new SizeF(1, 1));
        rcF.Inflate(Radius, Radius);
        G.DrawEllipse(Pens.Black, rcF);

        float Sides = (float)numSides;
        float ExteriorAngle = (float)360 / Sides;
        float InteriorAngle = (Sides - (float)2) / Sides * (float)180;
        float SideLength = (float)2 * Radius * (float)Math.Sin(Math.PI / (double)Sides);
        for (int i = 1; i <= Sides; i++)
        {
            G.ResetTransform();
            G.TranslateTransform(Center.X, Center.Y);
            G.RotateTransform((i - 1) * ExteriorAngle);
            G.DrawLine(Pens.Black, new PointF(0, 0), new PointF(0, -Radius));
            G.TranslateTransform(0, -Radius);
            G.RotateTransform(180 - InteriorAngle / 2);
            G.DrawLine(Pens.Black, new PointF(0, 0), new PointF(0, -SideLength));
        }
    }

}

I got the formula for the length of the side here at Regular Polygon Calculator.

like image 133
Idle_Mind Avatar answered Nov 10 '22 14:11

Idle_Mind


One way of dealing with this is using trigonometric functions sin and cos. Pass them the desired angle, in radians, in a loop (you need a multiple of 2*π/10, i.e. a = i*π/5 for i between 0 and 9, inclusive). R*sin(a) will give you the vertical offset from the origin; R*cos(a) will give you the horizontal offset.

Note that sin and cos are in the range from -1 to 1, so you will see both positive and negative results. You will need to add an offset for the center of your circle to make the points appear at the right spots.

Once you've generated a list of points, connect point i to point i+1. When you reach the ninth point, connect it to the initial point to complete the polygon.

like image 26
Sergey Kalinichenko Avatar answered Nov 10 '22 15:11

Sergey Kalinichenko


I don't test it, but i think it is ok.

#define DegreeToRadian(d)  d * (Pi / 180)

float r = 1; // radius
float cX = 0; // centerX
float cY = 0; // centerY
int numSegment = 10;
float angleOffset = 360.0 / numSegment;
float currentAngle = 0;
for (int i = 0; i < numSegment; i++)
{
    float startAngle = DegreeToRadian(currentAngle);
    float endAngle = DegreeToRadian(fmod(currentAngle + angleOffset, 360));

    float x1 = r * cos(startAngle) + cX;
    float y1 = r * sin(startAngle) + cY;
    float x2 = r * cos(endAngle) + cX;
    float y2 = r * sin(endAngle) + cY;

    currentAngle += angleOffset;

    // [cX, cY][x1, y1][x2, y2]
}

(fmod is c++ function equals to floatNumber % floatNumber)

like image 2
MRB Avatar answered Nov 10 '22 14:11

MRB