ヘッダー
C# サンプル集
 

多角形を描画する

2020/12/20

→ Visual Basic のサンプルに切り替える

 

このページで紹介するサンプルは Windowsフォームアプリケーションを前提にしています。

サンプルの pictureBox1_Paint は PictureBox の Paint イベントの発生時に呼び出される前提です。そうなるようにするにはたとえば、プロパティーウィンドウでPaintイベントをダブルクリックします。

描画するタイミングについては下記にサンプルを参照してください。

ボタンをクリックしたら図形を描画する

マウス操作で図形を描画する

 

 

赤い五角形

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    //五角形の頂点の座標
    Point p1 = new Point(105, 10);
    Point p2 = new Point(10, 79);
    Point p3 = new Point(46, 191);
    Point p4 = new Point(164, 191);
    Point p5 = new Point(200, 79);

    //頂点を結んでできるパス(≒図形)を定義
    var polygon = new System.Drawing.Drawing2D.GraphicsPath();
    polygon.AddPolygon(new Point[] {p1, p2, p3, p4, p5});

    //パスを描画
    e.Graphics.DrawPath(Pens.Red, polygon);
}

実行結果

五角形

 

 

青く塗りつぶした六角形

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    //六角形の頂点の座標
    Point p1 = new Point(97, 10);
    Point p2 = new Point(10, 60);
    Point p3 = new Point(10, 160);
    Point p4 = new Point(97, 210);
    Point p5 = new Point(184, 160);
    Point p6 = new Point(184, 60);

    //頂点を結んでできるパス(≒図形)を定義
    var polygon = new System.Drawing.Drawing2D.GraphicsPath();
    polygon.AddPolygon(new Point[] {p1, p2, p3, p4, p5, p6});

    //パスを描画
    e.Graphics.FillPath(Brushes.Blue, polygon);
}

実行結果

六角形

 

 

太い黒い枠線の七角形

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    //七角形の頂点の座標
    Point p1 = new Point(107, 10);
    Point p2 = new Point(29, 48);
    Point p3 = new Point(10, 132);
    Point p4 = new Point(64, 200);
    Point p5 = new Point(150, 200);
    Point p6 = new Point(204, 132);
    Point p7 = new Point(185, 48);

    //頂点を結んでできるパス(≒図形)を定義
    var polygon = new System.Drawing.Drawing2D.GraphicsPath();
    polygon.AddPolygon(new Point[] {p1, p2, p3, p4, p5, p6, p7});

    //パスを描画
    Pen pen = new Pen(Color.Black, 8); //太さ8の黒いペン
    e.Graphics.DrawPath(pen, polygon);
}

実行結果

七角形

 

 

線形のグラデーションで塗りつぶされた八角形

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    //八角形の頂点の座標
    Point p1 = new Point(110, 10);
    Point p2 = new Point(39, 39);
    Point p3 = new Point(10, 110);
    Point p4 = new Point(39, 181);
    Point p5 = new Point(110, 210);
    Point p6 = new Point(181, 181);
    Point p7 = new Point(210, 110);
    Point p8 = new Point(181, 39);

    //頂点を結んでできるパス(≒図形)を定義
    var polygon = new System.Drawing.Drawing2D.GraphicsPath();
    polygon.AddPolygon(new Point[] {p1, p2, p3, p4, p5, p6, p7, p8});

    //頂点1(p1)を青、頂点4(p4)を赤として、徐々に変化する色で塗りつぶすブラシを作成
    var gradientBrush = new System.Drawing.Drawing2D.LinearGradientBrush(
        p1,
        p4,
        Color.Blue, Color.Red);


    //塗りつぶした八角形を描画
    e.Graphics.FillPath(gradientBrush, polygon);
}

実行結果

八角形

 

 

正n角形

この例の DrawPolygon メソッドは引数で指定した n角形を描画します。

このサンプルでは 12 を指定して12角形を描画します。

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    //サイズ100の正12角形を描画します。
    DrawPolygon(12, 100, e.Graphics);
}

/// <summary>
/// 正多角形を描画します。
/// </summary>
/// <param name="index">角の数。六角形の場合6。</param>
/// <param name="size">大きさ。この多角形の外接円の半径。</param>
/// <param name="g">この図形を描画するGraphicsオブジェクト。Paintイベント内でe.Graphicsなどで取得できます。</param>
private void DrawPolygon(int index, int size, Graphics g)
{
    //▼各頂点の座標を算出
    //原点を中心としたときの各頂点の座標を算出します。

    //中心角(360度)をn等分したときの1角あたりの角度(単位はラジアン)
    double degree = (Math.PI * 2) / index;

    var points = new List<Point>();

    for (int i = 0; i < index; i++)
    {
        //点0から点iの角度(角 点1-O-点iの角度)に180度加えたもの。単位はラジアン。
        //180度 = Math.PIラジアン
        //180度加えなくても良いのですが、学校数学とy軸の方向が逆になっているので、180度加えることで、
        //学校数学でなじんだような配置になります。
        double thisDegree = degree * i + Math.PI;

        //点iのx座標
        double x = Math.Sin(thisDegree) * size;

        //点iのy座標
        double y = Math.Cos(thisDegree) * size;

        //この点を記憶しておく
        points.Add(new Point((int)x, (int)y));
    }

    //▼全体が見えるように平行移動させる
    //原点を中心とした座標だと第1象限~第4象限のすべてが使用されますが、
    //コンピューターは既定では第1象限しか描画・表示しないのですべての点が第1象限に収まるように
    //図形を平行移動させます。

    //TranslateTransformを使うと一撃で平行移動できます。
    //第4象限まで見えるように平行移動させる。(既定では第1象限しか表示されていない。)
    //g.TranslateTransform(size, size); //←これで移動すると一撃です。

    //あえて、すべての頂点の座標を再計算して第1象限に平行移動するには下記のようにします。
    int offsetX = Math.Abs(points.Aggregate((min, p) => min.X < p.X ? min : p).X);
    int offsetY = Math.Abs(points.Aggregate((min, p) => min.Y < p.Y ? min : p).Y);
    offsetX += 10; //上側に余白として 10ピクセルの隙間を空けます。
    offsetY += 10; //左側に余白として 10ピクセルの隙間を空けます。

    for (int i = 0; i < points.Count; i++)
    {
        points[i] = new Point(points[i].X + offsetX, points[i].Y + offsetY);
        //System.Diagnostics.Debug.Print(points[i].ToString()); //算出後の座標を出力します。
    }
       
    //▼描画
    //背景色黒
    g.Clear(Color.Black);

    //座標を配列化して間を線で結ぶ。
    g.DrawPolygon(Pens.Green, points.ToArray());
}

実行結果

正12角形