Skip to content

Hexagon

(16진법의 경우 Hexadecimal 항목 참조)

기하학에서 육각형은 변이 여섯 개인 도형이다.

정육각형의 한 각의 크기는 120°이므로 테셀레이션이 가능하다. 정육각형의 내각의 합은 720°이다.

Sample design

Black-hexagon-border-emblems-set-white-background-styled-borders-91979160.png

코드로 정육각형 그리는 방법

하나의 원이 있다고 가정하고, 원을 여섯 개의 호(Arc)로 정확히 나누면 각 내각은 60도 이다.

Hexagon-01.jpg

12시방향의 첫 번째 점은 (0, r)로 가정한다. 시계 방향으로 점을 찍을 때, 두 번째 점의 좌표는 \((\frac{\sqrt{3}}{2}r, 0.5r)\) 이다.

Hexagon-02.jpg

계산 방식은 다음과 같다:

  1. 60도 이동한 위치는 xy 평면 상의 위치로 이동시켜서, 삼각 함수 (Trigonometric functions) 계산을 편히 하기 위해 직각(90º) - 60º = 30º로, 사용할 수 있다.
  2. x축 으로 \(cos(30^{\circ}) = \frac{\sqrt{3}}{2}\)이므로 \(\frac{x}{r} = \frac{\sqrt{3}}{2}\), \(x = \frac{\sqrt{3}}{2}r\)
  3. y축 으로 \(sin(30^{\circ}) = \frac{1}{2}\) 이므로 \(\frac{y}{r} = \frac{1}{2}\), \(y = \frac{1}{2}r\)

X축과 Y축으로 Flip 하면 전체 꼭지점이 도출된다.

Godot

using Godot;
using System;
using System.Collections.Generic;

[Tool]
public class HexagonTile : Node2D
{
    private static float COS30 = (float)Math.Sqrt(3f) / 2f;
    private static float SIN30 = 0.5f;

    private float _radius = 48f;

    [Export]
    public float radius {
        get => _radius;
        set
        {
            this._radius = value;
            this.UpdatePoints();
            this.Update();
        }
    }

    private Vector2 _offset = new Vector2(0, 0);

    [Export]
    private Vector2 offset
    {
        get => _offset;
        set
        {
            this._offset = value;
            this.UpdatePoints();
            this.Update();
        }
    }

    private Color _lineColor = new Color(1f, 1f, 1f, 1f);

    [Export]
    private Color lineColor
    {
        get => _lineColor;
        set
        {
            this._lineColor = value;
            this.Update();
        }
    }

    private Color _fillColor = new Color(0f, 0f, 0f, 0f);

    [Export]
    private Color fillColor
    {
        get => _fillColor;
        set
        {
            this._fillColor = value;
            this.Update();
        }
    }

    private float _lineWidth = 1f;

    [Export]
    private float lineWidth
    {
        get => _lineWidth;
        set
        {
            this._lineWidth = value;
            this.UpdatePoints();
            this.Update();
        }
    }

    private bool _antialiased = true;

    [Export]
    private bool antialiased
    {
        get => _antialiased;
        set
        {
            this._antialiased = value;
            this.Update();
        }
    }

    private List<Vector2> _points = new List<Vector2>();

    static public List<Vector2> MakeHexagonPoints(Vector2 center, float radius)
    {
        var r = radius;
        var x = COS30 * radius;
        var y = SIN30 * radius;
        var cx = center.x;
        var cy = center.y;

        var points = new List<Vector2>();
        points.Clear();
        points.Add(new Vector2(cx + x, cy));
        points.Add(new Vector2(cx + x, cy + y));
        points.Add(new Vector2(cx + 0, cy + r));
        points.Add(new Vector2(cx - x, cy + y));
        points.Add(new Vector2(cx - x, cy - y));
        points.Add(new Vector2(cx + 0, cy - r));
        points.Add(new Vector2(cx + x, cy - y));
        points.Add(new Vector2(cx + x, cy));
        return points;
    }

    public void UpdatePoints()
    {
        this._points = MakeHexagonPoints(this._offset, this._radius);
    }

    public override void _Draw()
    {
        if (this._points.Count == 0) {
            this.UpdatePoints();
        }

        var fillColors = new Color[] { this._fillColor };
        DrawPolygon(this._points.ToArray(), fillColors);

        if (this._lineWidth > 0) {
            DrawPolyline(
                this._points.ToArray(),
                this._lineColor,
                this._lineWidth,
                this._antialiased);
        }
    }
}

DrawPolyline 함수의 꼭지점 연결 부분이 부자연스럽다면 Godot:CanvasItem#draw_polyline 항목의 "Line Connection 이슈" 항목을 참조.

pygame

def draw_ngon(Surface, color, n, radius, position):
    pi2 = 2 * 3.14

    for i in range(0, n):
        pygame.draw.line(Surface, color, position, (cos(i / n * pi2) * radius + position[0], sin(i / n * pi2) * radius + position[1]))

    return pygame.draw.lines(Surface,
          color,
          True,
          [(cos(i / n * pi2) * radius + position[0], sin(i / n * pi2) * radius + position[1]) for i in range(0, n)])

See also

Favorite site