Чтобы создать правильный многоугольник из ограничивающего прямоугольника, вам необходимо вычислить длину стороны и apothem .
Длина стороны рассчитывается из радиуса (расстояние от центра до вершины)
Apothem (расстояние от центра до средней точки стороны), рассчитывается по длине стороны.
( подробнее здесь )
в следующем примере 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 сторон (вкл.)
При наличии одной и той же ограничительной рамки все многоугольники рассчитываются для вписывания в один и тот же круг, окружность.