Как мне создать пятиугольник и шестиугольник, используя create_line в python tkinter canvas?

#python #python-3.x #tkinter #geometry #tkinter-canvas

#python #python-3.x #tkinter #геометрия #tkinter-canvas

Вопрос:

Вот код, который у меня есть для рисования треугольника и квадрата в python tkinter canvas с использованием create_lines, как бы я использовал create_lines для создания пятиугольника и шестиугольника?

Примечание: Для пятиугольника и шестиугольника длина и ширина относятся к общей площади квадратной формы, в пределах которой содержится фигура, а не к ширине и длине сторон.

     self.x, self.y = 50, 50

def triangle(self):
    width = self.width.get()
    length = self.length.get()
    color = self.color_select.get()

    self.canvas.create_line(self.x, self.y, (self.x   (int(length) / 2)), (self.y   int(length)), fill = color)

    self.canvas.create_line(self.x, self.y, (self.x - (int(length) / 2)), (self.y   int(length)), fill = color)

    self.canvas.create_line((self.x - (int(length) / 2)), (self.y   int(length)), (self.x   (int(length) / 2)), (self.y   int(length)), fill = color)

    self.x  = 50

def square(self):
    width = self.width.get()
    length = self.length.get()
    color = self.color_select.get()

    self.canvas.create_line(self.x, self.y, self.x   int(width), self.y, fill = color)

    self.canvas.create_line(self.x, self.y, self.x, self.y   int(length), fill = color)
    self.y  = int(length)

    self.canvas.create_line(self.x, self.y, self.x   int(width), self.y, fill = color)
    self.x  = int(width)

    self.canvas.create_line(self.x, self.y, self.x, self.y - int(length), fill = color)
    self.y -= int(length)

    self.x  = 50

def pentagon(self):
    width = self.width.get()
    length = self.length.get()
    color = self.color_select.get()

def hexagon(self):
    width = self.width.get()
    length = self.length.get()
    color = self.color_select.get()
  

Комментарии:

1. вам придется использовать math.sin() , math.cos() или math.tan() для вычисления некоторых расстояний.

2. добавляя к ответу furas , используйте create_polygon и создайте один объект на холсте, вместо того, чтобы заполнять его несколькими строками

Ответ №1:

Чтобы создать правильный многоугольник из ограничивающей рамки, вам нужно вычислить длину стороны и вершину.
Длина стороны рассчитывается исходя из радиуса (расстояния от центра до вершины)
Апофема (расстояние от центра до средней точки стороны) вычисляется исходя из длины стороны.
(подробнее здесь)

в следующем примере bbox центрирован по центру созданного многоугольника; вы можете смещать его по своему усмотрению, чтобы соответствовать вашей предпочтительной точке привязки.

При наличии одинаковой ограничивающей рамки все многоугольники рассчитываются так, чтобы быть вписанными в один и тот же круг — окружность, которая является пределом многоугольника, когда количество сторон стремится к бесконечности, см. Изображение ниже.

 import tkinter as tk
import math


WIDTH, HEIGHT = 500, 500


class Point:
    """convenience for point arithmetic"""
    def __init__(self, x, y):
        self.x, self.y = x, y
    def __add__(self, other):
        return Point(self.x   other.x, self.y   other.y)
    def __iter__(self):
        yield self.x
        yield self.y


class RegularPolygon:

    def __init__(self, num_sides, bbox_side, x, y):   # x, y are bbox center canvas coordinates
        self.bbox_side = bbox_side
        self.num_sides = num_sides
        self.side_length = None
        self.apothem = None
        self._calc_side_length()
        self.points = [Point(x - self.side_length // 2, y - self.apothem)]
        self._make_points()
        self.lines = []
        self._make_lines()

    def _calc_side_length(self):
        """Side length given the radius (circumradius):
        i/e the distance from the center to a vertex
        """
        self.side_length = 2 * (self.bbox_side // 2) * math.sin(math.pi / self.num_sides)

        # Apothem, i/e distance from the center of the polygon 
        # to the midpoint of any side, given the side length 
        self.apothem = self.side_length / (2 * math.tan(math.pi / self.num_sides))

    def _make_points(self):
        _angle = 2 * math.pi / self.num_sides
        for pdx in range(self.num_sides):
            angle = _angle * pdx
            _x = math.cos(angle) * self.side_length
            _y = math.sin(angle) * self.side_length
            self.points.append(self.points[-1]   Point(_x, _y))

    def _make_lines(self):
        for p0, p1 in zip(self.points[:-1], self.points[1:]):
            self.lines.append((*p0, *p1))

    def draw(self, canvas):
        for line in self.lines:
            canvas.create_line(line)
        # alternatively, use canvas.create_polygon(points coordinates) instead


root = tk.Tk()

canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg="cyan")
canvas.pack()

CENTER = Point(WIDTH // 2, HEIGHT // 2)

for n_sides in range(3, 12):
    p = RegularPolygon(n_sides, 300, *CENTER)
    p.draw(canvas)


root.mainloop()  
  

Рисование правильных полигонов с 3 по 12 сторон (вкл.)

введите описание изображения здесь

При наличии одинаковой ограничивающей рамки все полигоны рассчитываются так, чтобы быть вписанными в один и тот же круг, circumcircle.

введите описание изображения здесь