Почему появляется разрыв между начальной и конечной точкой круга?

Есть функция:

import simple_draw as sd

sd.set_screen_size(width=1600, height=800)

def polygon(x, y, angle_of_rotation, length, facets):
    point = sd.get_point(x, y)
    for _ in range(facets):
        angle = 360 / facets
        vektor = sd.get_vector(start_point=point, angle=angle_of_rotation, length=length, width=3)
        vektor.draw()
        angle_of_rotation += angle
        point = vektor.end_point


polygon(400, 150, 0, 50, 20)


sd.pause()

Почему существует разрыв, между конечной точкой и начальной?


Ответы (1 шт):

Автор решения: insolor

Если посмотреть на класс Point из simple_draw, то можно увидеть там кучу ненужных приведений к целому, из-за которых при сложении нескольких векторов накапливается ошибка округления:

# Point support
class Point:
    """
        Класс точки экрана
    """

    def __init__(self, x=None, y=None):
        self._x = random_number(1, resolution[0]) if x is None else int(x)  # <--
        self._y = random_number(1, resolution[1]) if y is None else int(y)  # <--

    def to_screen(self):
        return int(self._x), resolution[1] - int(self._y)

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = int(value)  # <--

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        self._y = int(value)  # <--

    def __str__(self):
        return 'Point(x={}, y={})'.format(self.x, self.y)

Большая часть их не нужна, округление нужно только при приведении к экранным координатам (метод to_screen). Исправленный вариант:

# Point support
class Point:
    """
        Класс точки экрана
    """

    def __init__(self, x=None, y=None):
        self._x = random_number(1, resolution[0]) if x is None else x
        self._y = random_number(1, resolution[1]) if y is None else y

    def to_screen(self):
        return int(self._x), resolution[1] - int(self._y)

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        self._y = value

    def __str__(self):
        return 'Point(x={}, y={})'.format(self.x, self.y)

После исправления окружность почти замыкается:

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

Если еще заменить оставшиеся int на round (округление к ближайшему целому, а не к меньшему целому), то окружность замкнется практически идеально:

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

Пулл-реквест: https://github.com/suguby/simple_draw/pull/11

→ Ссылка