10

I have to write a program in Python that reads the value n and draws a polygon of n sides on the screen. I can use either the turtle graphics module or graphics.py module.

I know how to draw a polygon when n = the number of points you input and then click n times on the screen, but I'm having some trouble getting an idea on how to transform a number of sides into a polygon.

Here's the code I have for the polygon with n number of points:

def newPolygon(self,cmd):
    p = eval(input("how many points"))
    print("click",p,"times")
    num = []
    for i in range(p):
        vertices = self.win.getMouse()
        num.append(vertices)

    poly = Polygon(num)
    poly.setFill(self.color)
    poly.draw(self.win)

    self.figs.append(poly)

This isn't the whole code to the program(which is 384 lines). This is just the part of the program where the draw polygon function is where self.figs = [ ] , a list of drawn figures.

Goose LaMoose
  • 121
  • 1
  • 2
  • 8
  • You should use `int(input(...))` - "`eval` is evil" – jonrsharpe May 01 '14 at 16:15
  • 2
    Hint: turtle is probably the easier approach, since then you can draw a polygon by doing "move forward, then turn by X degrees" N times. The only hard part is finding out what X should be. – Kevin May 01 '14 at 16:16
  • @Kevin It always sounded more complicated and unintentional to me to have a pen with orientation and relative movements. In this case it might actually help a bit. – danijar May 01 '14 at 16:19
  • @Kevin I don't know how I would calculate the angles. I'm not supposed to ask the user for an input of degrees. – Goose LaMoose May 01 '14 at 16:21
  • 1
    In that case, [this](http://www.mathsisfun.com/geometry/interior-angles-polygons.html) article may be useful to you. – Kevin May 01 '14 at 16:22

2 Answers2

11

I'm assuming what you would like is a way of generating equal sided polygon coordinates which you can feed to your drawing program. I'm not sure which library you are using, so I'm going to stick to lists of pairs of values:

import math


def polygon(sides, radius=1, rotation=0, translation=None):
    one_segment = math.pi * 2 / sides

    points = [
        (math.sin(one_segment * i + rotation) * radius,
         math.cos(one_segment * i + rotation) * radius)
        for i in range(sides)]

    if translation:
        points = [[sum(pair) for pair in zip(point, translation)]
                  for point in points]

    return points

There's a fair bit going on in there, so I'll talk through it. The basic approach is to sweep out a circle, and put n equally spaced points on it. These will be the points of our polygon, starting at the 12 'o' clock position.

The first thing to do is work out the angle (in radians) of each wedge from the center outwards. The total number of radians in a circle is 2 pi, so our value is 2 pi / n per segment.

After that a bit of basic trig gives us our points (https://en.wikipedia.org/wiki/Trigonometry#Extending_the_definitions). At this point we scale by our desired radius, and have the opportunity to offset the rotation by a fixed amount too.

After that we translate the values by a certain amount, because you probably want your polygon in the center of the screen, not in the corner.

A few examples

print polygon(5)    # A unit pentagon

# [(0.0, 1.0), (0.9510565162951535, 0.30901699437494745), (0.5877852522924732, -0.8090169943749473), (-0.587785252292473, -0.8090169943749476), (-0.9510565162951536, 0.30901699437494723)]

print polygon(4, 100) # A square, point up, 100 from the center to the points

# [(0.0, 100.0), (100.0, 6.123233995736766e-15), (1.2246467991473532e-14, -100.0), (-100.0, -1.8369701987210297e-14)]

print polygon(4, 2, math.pi / 4, [10, 10])  # A flat square centered on 10, 10

# [[11.414213562373096, 11.414213562373096], [11.414213562373096, 8.585786437626904], [8.585786437626904, 8.585786437626904], [8.585786437626904, 11.414213562373094]]

As you can see, these are all floats, so you may need to squish these to integers before you can use them.

Jon Betts
  • 3,053
  • 1
  • 14
  • 12
  • Simple and elegant. Thanks! – Itay Jun 28 '17 at 23:26
  • does this function works correctly? does it realy do `generating equal sided polygon coordinates `? I am checking Euqlidean distance (by `math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)` and it shows mi different length for different segments – Chiefir Jan 17 '19 at 10:45
  • I've given it a quick check and I think so. It's important to ensure your x1 and x2 are from consecutive points. All points are equally distant from the center, but not each other if you cut across the polygon. There is of course some floating point noise. – Jon Betts Mar 14 '19 at 17:09
1

I don't know if this will help but to define a polygon using number of sides and length then I would use my code:

import turtle as t

def polygon(n,l):
    f = (n - 2) * 180/n
    for i in range(n):
        t.forward(l)
        t.right(180 - f)

polygon()

In this case, n would be number of sides and l would be length of sides.

This took me quite a while as I am only 13 and am not advanced but this was a fun project!

Mr. T
  • 11,960
  • 10
  • 32
  • 54
jonah
  • 21
  • 4