7

私は現在、円の中に十角形の対角線を内接しようとしています

このようなここに画像の説明を入力

C#では、私のアプローチは円を作成することです

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

を使用して内側に線を引きます

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

その後、十角形のポリゴンを描きます。

現在、円を10の部分に分割する方法/円の円周上の点の正しい座標を見つける方法に行き詰まっています。数学が苦手なので、円の円周の次の点をどのように知ることができるか知りたいです私の円のサイズは上に示されています。
また、私の問題に対するより良いアプローチも求めたいと思います。

ありがとうございました :)

4

3 に答える 3

6

これに対処する 1 つの方法は、三角関数sinとを使用することcosです。希望する角度をラジアン単位でループに渡します ( の倍数2*π/10、つまり0 から 9 までの範囲が必要です) a = i*π/5。原点からの垂直オフセットが得られます。水平オフセットが得られます。iR*sin(a)R*cos(a)

sinとは からまでcosの範囲にあることに注意してください。したがって、正と負の両方の結果が表示されます。ポイントが正しい場所に表示されるようにするには、円の中心にオフセットを追加する必要があります。-11

ポイントのリストを生成したら、ポイント ツー ポイントを接続iしますi+1。9 番目の点に到達したら、最初の点に接続して多角形を完成させます。

于 2013-10-06T15:43:55.190 に答える
6

グリットとスネのために、X 側のポリゴンを渡す Rectangle に内接する一般的な実装を次に示します。このアプローチでは、実際には絶対ポイントを計算していないことに注意してください。代わりに、原点を移動し、サーフェスを回転させ、固定長と角度を使用して原点に対してのみ線を描画しています。これは、以下の最終結果を達成するためにループで繰り返されます。これは、ロゴでタートルにコマンドを実行するのと非常によく似ています。

内接多角形

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));
        }
    }

}

辺の長さの計算式はこちらの正多角形電卓で取得しました。

于 2013-10-06T22:01:54.027 に答える
2

私はそれをテストしていませんが、大丈夫だと思います。

#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 は floatNumber % floatNumber に等しい C++ 関数です)

于 2013-10-06T17:04:01.983 に答える