33

I have been trying to figure out how to write a simple program to compute the x,y points for creating a regular polygon of n sides. Can someone give me some code examples that don't use preexisting functions that draw polygons? I want to understand the process, which I assume is something like this:

  1. pick an angle to start from a radius and a center point
  2. somehow calculate the x,y position at that distance from the center(how?)
  3. divide 360 by the number of sides, move that distance and draw the next line from the first x,y point
  4. continue until the angle=360 divided by that number.

Assuming that my assumptions are correct, the main thing is to understand how to compute the x,y points.

Prefer answers in a visual basic (or even old style Microsoft/Atari/Commodore BASIC) or a human readable set of steps in English. If you have to answer with a math formula, do it in a computer language so I can read it, even in C or C++ I can figure it out, but I don't know how to read mathematical notation. The language I'm using is a Visual Basic-like language that has almost no graphics primitives other than line drawing.

alphablender
  • 2,168
  • 5
  • 27
  • 42

6 Answers6

55

Let's assume you want to draw an N-sided polygon of radius r, centred at (0,0). Then the n vertices are given by:

x[n] = r * cos(2*pi*n/N)
y[n] = r * sin(2*pi*n/N)

where 0 <= n < N. Note that cos and sin here are working in radians, not degrees (this is pretty common in most programming languages).

If you want a different centre, then just add the coordinates of the centre point to each (x[n], y[n]). If you want a different orientation, you just need to add a constant angle. So the general form is:

x[n] = r * cos(2*pi*n/N + theta) + x_centre
y[n] = r * sin(2*pi*n/N + theta) + y_centre
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • Thank you for this, but what would the texture coordinates be? – Quintin Balsdon Mar 21 '13 at 15:57
  • 1
    @QuintinBalsdon: What texture coordinates? – Oliver Charlesworth Mar 21 '13 at 15:59
  • Hi I have asked the question here: http://stackoverflow.com/questions/15552521/how-to-determine-uv-texture-coordinates-for-n-sided-polygon Basically it boils down to this: In an OpenGL|ES situation, if this was my points for my vertices, in what order must I order these points for UV texture mapping. – Quintin Balsdon Mar 21 '13 at 20:18
  • How to do this without knowing the radius? For example I might not want a symmetrical polygon, but rather one defined by width and height (width being the object's max width and height being the object's max height)? – Gustav Oct 29 '14 at 15:44
  • 1
    @Gustav: Depends what you mean by "width" and "height". A naive approach is simply `x[n] = width * ...; y[n] = height * ...;`. – Oliver Charlesworth Oct 29 '14 at 17:05
  • @OliverCharlesworth With width and height I mean the width and height of the grey bounding box shown in this picture: [link](http://i.imgur.com/xbG9xtG.png?1) I'm asking this because I'm working on a project in which I get data about shapes in that format and need to display them on canvas (currently using kinetic.js). I get data for the number of sides, width and height of the bounding box, possible rotation and x- and y-position of the bounding box in a canvas. Thanks for your help. – Gustav Oct 29 '14 at 21:54
9
angle = start_angle
angle_increment = 360 / n_sides
for n_sides:
    x = x_centre + radius * cos(angle)
    y = y_centre + radius * sin(angle)
    angle += angle_increment

in practice, when drawing lines instead of just calculating the corner points, you also need to "join up" the polygon by repeating the first point.

also, if sin() and cos() work in radians rather than degrees, you want 2 * PI instead of 360.

andrew cooke
  • 45,717
  • 10
  • 93
  • 143
2

Here is a full c++ program that prints out the points of a regular polygon. In this case,p is the number of sides,r is the radius of the polygon and d is the direction or angle of the first point from the center. Maybe this will help.

//g++ ck.cpp -o ck && ./ck
#include <stdio.h>
#include <math.h>

int p=3; //number of sides
double r=1000,d=3/4.0;

int main()
{
 int i=0;
 double x,y,t;
 while(i<p)
 {
  t=2*M_PI*((double)i/p+d);
  x=cos(t)*r;
  y=sin(t)*r;
  printf("x%i:%f y%i:%f\n",i,x,i,y);
  i++;
 }
}
2

The "for n_sides:" answer is the easiest. For the guy who suggested that you could simplify the calculations by using complex numbers, nearly all math libraries have table-based cos() and sin() routines with efficient interpolation so there's no need to delve into relatively obscure solutions. Usually a regular n-gon can be initialized and the hardware scaling of OpenGL used to scale / transform it for any particular instance.

If you want to be hardcore about it, pre-generate all the n-gons you need and load them into vertex buffers.

As an aside, here's the above solution in Lua. It just prints out the coordinates, but you're of course free to return the coordinates in an array / table. The coordinates returned can be used to initialize an OpenGL GL_LINE_LOOP mesh primitive.

require 'math'

-- computes coordinates for n-sided, regular polygon of given radius and start angle
-- all values are in radians

function polypoints(sides, radius, start)
    local x_center = 0.0
    local y_center = 0.0
    local angle = start
    local angle_increment = 2 * math.pi / sides
    local x=0.0
    local y=0.0

    print(string.format("coordinates for a %d sided regular polygon of radius %d\nVertex",sides,radius),"X"," ","Y")
    for i=1,sides do
        x = x_center + radius * math.cos(angle)
        y = y_center + radius * math.sin(angle)
        print(string.format("%d\t%f\t%f",i,x,y))
        angle = angle + angle_increment
    end
end

-- Generate a regular hexagon inscribed in unit circle 
polypoints(6, 1.0, 0.0)
eris0xff
  • 133
  • 9
2

If you want to make it faster at the cost of some error accumulation, use a (complex) primitive nth root of unity and take the powers of it (either using built-in complex number support in your language or coding the multiplication by hand). In C:

complex double omega=cexp(2*M_PI*I/n), z;
for (i=0, z=1; i<n; i++, z*=omega) {
    /* do something with z */
}
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • That looks interesting, but how do you get x,y out of z? – alphablender Aug 28 '11 at 01:22
  • I'm not familiar with the complex number function in c, is there any difference between omega=2*value_of_pi*i/n and cexp=(2*M_PI*I/n)? Looks like you are assigning a pointer to z the value of omega. What do you mean by real and imaginary part? What would an expression that gave me the x,y points (which is what this whole question is about) look like? – alphablender Sep 04 '11 at 03:47
  • `z` ends up containing (on successive iterations) the powers of `omega`, where `omega` is a primitive `n`th root of unity, obtained by the complex exponential function `cexp`. – R.. GitHub STOP HELPING ICE Sep 04 '11 at 03:49
  • Well, thanks for attempting to explain, I don't really understand most of what you said. What would the code that returns x and y points from your for-loop look like? – alphablender Sep 04 '11 at 03:56
  • By the way if you want to understand this answer, lookup complex numbers and roots of unity on the web. Wikipedia is probably a good place to start, or else math tutorials for self-teaching. – R.. GitHub STOP HELPING ICE Sep 04 '11 at 04:00
  • ok, thanks! I'll be looking up creal() and cimag() first, and I'll backtrack from there! – alphablender Sep 04 '11 at 04:26
  • BTW CORDIC would be a useful keyword for looking up related techniques. – R.. GitHub STOP HELPING ICE Mar 08 '18 at 00:03
1

I know you asked for an answer in Visual Basic, however here is a solution in JavaScript.

CrazyTim
  • 6,695
  • 6
  • 34
  • 55