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:
- pick an angle to start from a radius and a center point
- somehow calculate the x,y position at that distance from the center(how?)
- divide 360 by the number of sides, move that distance and draw the next line from the first x,y point
- 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.
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
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
.
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++;
}
}
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)
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 */
}
I know you asked for an answer in Visual Basic, however here is a solution in JavaScript.
精彩评论