Как нарисовать прямоугольник вокруг двух точек - PullRequest
4 голосов
/ 25 мая 2020

Я использую pygame и математический модуль, чтобы попытаться нарисовать прямоугольник вокруг двух точек. Вот что я имею в виду:

Rectangle-controlled-by-two-points

Расстояние от точек до концов прямоугольников указывается как атрибут класса. Я много пытался добиться этого, и показанный угол, вероятно, является единственным рабочим углом. Вот мой класс для прямоугольника:

def Pol(x, y):
    """Converts rectangular coordinates into polar ones"""
    if x == 0: # This might be the source of my problems, but without it, it raises ZeroDivisionErrors at certain places
        if y >= 0:
            return [y, 90]
        else:
            return [-y, 270]
    r     = math.sqrt(x**2+y**2)
    angle = (math.degrees(math.atan((y/x))))%360
    return [r, angle]

class Path(pygame.sprite.Sprite):
    def __init__(self, start, end, color, width, **options):
        self.__dict__.update(options)
        self.start = start
        self.end = end
        self.color=color
        # Call the parent class (Sprite) constructor
        super().__init__()

        # Pass in the color of the blob, and its x and y position, width and height
        # Set the background color and make it transparent
        self.width = width

        # Draw the path
        self.redraw()

        # Fetch the rectangle object that has the dimensions of the image.
        self.rect = self.image.get_rect()
        self.rect.x, self.rect.y = (self.start[0]-self.width//2+self.ix,
                                    self.start[1]-self.width//2+self.iy)
        if self.inversed:
            self.rect.y-=(math.ceil(self.image.get_rect()[3]/2)-self.iy)

    def redraw(self):
        dis, angle = Pol(self.end[0]-self.start[0], self.end[1]-self.start[1])
        dis += self.width
        _image = pygame.Surface([dis, self.width])
        _image.fill([255, 255, 255])
        _image.set_colorkey([255, 255, 255])
        pygame.draw.rect(_image, self.color, pygame.Rect(0, 0, dis, self.width))
        nangle = (180-angle)%360
        self.inversed = nangle>=180
        self.image = pygame.transform.rotate(_image, nangle)
        i1 = _image.get_rect()
        i2 = self.image.get_rect()
        ix = i2[2]-i1[2]
        iy = i2[3]-i1[2]
        self.ix = ix//2
        self.iy = iy//2

Итак, я передаю ему несколько пунктов, и он берет на себя всю тяжелую работу и рисование. На изображении я пропустил (100, 100) and (200, 200). Затем я попробовал его с (300, 300) and (200, 200), и он сработал частично:

failed test

Код приведен выше, вы можете попробовать его с другими значениями , но вы увидите, что это быстро становится проблемным c. Подводя итог, у меня вопрос: есть ли надежный способ нарисовать прямоугольник по двум точкам? Я пробовал:

  • с рисованием толстых линий, но линии pygame разбиваются под определенными углами и имеют горизонтальные окончания
  • тестирование и повторение снова и снова со значениями, ничего Я пробовал работать
  • , меняя обратный оператор if. По идее должно получиться уже назад

1 Ответ

5 голосов
/ 25 мая 2020

Проблема заключается в функции math.atan(), которая возвращает угол в диапазоне [-pi / 2, + pi / 2].
Используйте math.atan2() (см. math ), которая возвращает угол в диапазоне [-pi, + pi]. Следовательно, эта функция сразу дает правильный угол, и вам не нужно никаких поправок:

angle = (math.degrees(math.atan((y/x))))%360

angle = math.degrees(math.atan2(y, x))

См. Также В чем разница между atan и atan2 в C ++?

...