Math behind creating a hexagon??

I am working on a program that draws a hexagonal grid to the screen.

Here is an image of basically how you'd draw an accurate hexagon if you were doing it on paper: http://en.wikipedia.org/wiki/File:Regular_Hexagon_Inscribed_in_a_Circle_240px.gif

Based off this, I know my arguments to my Hexagon function will need to be center X and Y coordinates and radius.

My question is how do I find the 6 corner points of the hexagon mathematically in C++?? Once I do that, I figure I can just draw lines between the points and I'll have my hexagons.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct Point{
  int X,Y;
  Point(int X, int Y) :X(X),Y(Y) {}
  Point() :X(0),Y(0) {}
  void Draw(ALLEGRO_COLOR clr){ al_put_pixel(X,Y,clr); }
};

void DrawHexagon(float centerX, float centerY, float radius, ALLEGRO_COLOR clr)
{
  Point pt1, pt2, pt3, pt4, pt5, pt6;

  //Calculate the 6 points of the hexagon!!! ??

  pt1.X = centerX + radius; pt1.Y = centerY;  //Right-center point

  //Draw lines between points
  al_draw_line(pt1.X, pt1.Y, pt2.X, pt2.Y, clr);
  al_draw_line(pt2.X, pt2.Y, pt3.X, pt3.Y, clr);
  al_draw_line(pt3.X, pt3.Y, pt4.X, pt4.Y, clr);
  al_draw_line(pt4.X, pt4.Y, pt5.X, pt5.Y, clr);
  al_draw_line(pt5.X, pt5.Y, pt6.X, pt6.Y, clr);
  al_draw_line(pt6.X, pt6.Y, pt1.X, pt1.Y, clr);
}
Last edited on
I think this is a mathematic question.

pt1.X = centerX + radius*cos(theta)
pt1.Y = centerY + radius*sin(theta)

use an iteration for theta = 0 to 2*PI increased by PI / 3

you should see math.c library also

http://www.cplusplus.com/reference/cmath/
oh god that's complicated. :p And yes, definitely a math question.

I'll let u know if I get it figured out for all points. Any other suggestions are welcome as well.
That's roughly how I would have explained it.

However, all the values can be derived from considering the geometry of an equilateral triangle. Think of a hexagon as made up of six such triangles.

If you can find the three x,y coordinates which make up one equilateral triangle, the remaining points can be found by considering the symmetry of the figure.

Say the base of the equilateral triangle is equal to the radius of the circle, the vertical height will be the radius * sqrt(3)/2. For example, if the radius = 100 units, the height will be 86.6 units.

If you sketch out a diagram using these proportions, the required coordinates shouldn't be hard to figure out.

I should add that the advantage of using the method suggested by karakale is that it can be generalised to draw say a seven-sided figure, or one with 193 sides, or whatever, and ends up being much simpler in those cases.
Last edited on
Thanks to both of you for pointing me in the right direction :)

Also got help from these two:
http://www.mathsisfun.com/sine-cosine-tangent.html
http://www.rdwarf.com/lerickson/hex/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
struct Point{
	int X,Y;
	Point(int X, int Y) :X(X),Y(Y) {}
	Point() :X(0),Y(0) {}
	void Draw(ALLEGRO_COLOR clr){ al_put_pixel(X,Y,clr); }
};

struct HEXAGON{
	int centerX, centerY, Radius;
	HEXAGON(int centerX, int centerY, int Radius) :centerX(centerX), centerY(centerY), Radius(Radius) {}
	HEXAGON() :centerX(15), centerY(15), Radius(16) {}
	void Draw(ALLEGRO_COLOR clr)
	{
		float uX = centerX - Radius;
		float uY = centerY - Radius;
		Point pt1(uX,uY), pt2(uX,uY), pt3(uX,uY), pt4(uX,uY), pt5(uX,uY), pt6(uX,uY);

		float const PI = 3.14159265;
		float A, B, C;
		A = Radius/2;
		C = A / sin(30*PI/180);
		B = C * cos(30*PI/180);

		pt1.X += 0; pt1.Y += B;
		pt2.X += A; pt2.Y += 0;
		pt3.X += A+C; pt3.Y += 0;
		pt4.X += 2*C; pt4.Y += B;
		pt5.X += A+C; pt5.Y += 2*B;
		pt6.X += A; pt6.Y += 2*B;

		al_draw_line(pt1.X,pt1.Y,pt2.X,pt2.Y,clr, 1.0F);
		al_draw_line(pt2.X,pt2.Y,pt3.X,pt3.Y,clr, 1.0F);
		al_draw_line(pt3.X,pt3.Y,pt4.X,pt4.Y,clr, 1.0F);
		al_draw_line(pt4.X,pt4.Y,pt5.X,pt5.Y,clr, 1.0F);
		al_draw_line(pt5.X,pt5.Y,pt6.X,pt6.Y,clr, 1.0F);
		al_draw_line(pt6.X,pt6.Y,pt1.X,pt1.Y,clr, 1.0F);
	}
};
I tested the above algorithm, it seems pretty good, though I found it was somewhat off-centre in the vertical direction. I wasn't sure whether that was deliberate or not.

Below, the first point is (centerX+Radius, centerY).
All the other points are simply that point rotated anti-clockwise around the centre. The number of sides nsides is chosen as 6, but could be any value greater than 1.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    void Draw(ALLEGRO_COLOR clr)
    {
        float const PI = 3.14159265;

        const int nsides = 6;

        Point pts[nsides];
        float angle = 0;
        float incr = 2.0 * PI / nsides;

        for (int i=0; i<nsides; i++)
        {
            pts[i].X = Radius * cos(angle) + centerX;
            pts[i].Y = Radius * sin(angle) + centerY;
            angle += incr;
        }

        for (int i=0; i<nsides; i++)
        {
            int j = (i+1) % nsides;
            al_draw_line(pts[i].X, pts[i].Y, pts[j].X, pts[j].Y,clr, 1.0F);
        }
    }


Actually, the array of points isn't needed. You can simply find the coordinates and draw a line from the previous to current coordinate.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    void Draw(ALLEGRO_COLOR clr)
    {
        float const PI = 3.14159265;
        const int nsides = 6;

        float angle = 0.0f;
        float incr = 2.0 * PI / nsides;

        int newX = Radius * cos(angle) + centerX;
        int newY = Radius * sin(angle) + centerY;

        for (int i=0; i<nsides; i++)
        {
            int oldX = newX;
            int oldY = newY;
            angle += incr;
            newX = Radius * cos(angle) + centerX;
            newY = Radius * sin(angle) + centerY;
            al_draw_line(oldX, oldY, newX, newY, clr, 1.0F);
        }
    }
Last edited on
Topic archived. No new replies allowed.