Вращающиеся прямоугольники вокруг точки с помощью matplotlib - PullRequest
0 голосов
/ 26 февраля 2020

Я хотел повернуть Rectangles с matplotlib, но обычный патч всегда вращается вокруг нижнего левого угла Rectangle. Есть ли способ описать более общие преобразования? Например, я хочу повернуть вокруг средней точки на более короткой стороне прямоугольника, чтобы результат выглядел как движение стрелки часов.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

height = 0.1
width = 1
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.set_xlim([-width * 1.2, width * 1.2])
ax.set_ylim([-width * 1.2, width * 1.2])

ax.plot(0, 0,  color='r', marker='o', markersize=10)
for deg in range(0, 360, 45):
    rec = Rectangle((0, 0), width=width, height=height, 
                    angle=deg, color=str(deg / 360), alpha=0.9)
    ax.add_patch(rec)

Original

Ответы [ 2 ]

2 голосов
/ 26 февраля 2020

То же, что и другой ответ, только без подклассов и использования личных атрибутов.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D

height = 0.1
width = 1
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.set_xlim([-width * 1.2, width * 1.2])
ax.set_ylim([-width * 1.2, width * 1.2])
ax.plot(0, 0,  color='r', marker='o', markersize=10)
point_of_rotation = np.array([0, height/2])          # A
# point_of_rotation = np.array([width/2, height/2])  # B
# point_of_rotation = np.array([width/3, height/2])  # C
# point_of_rotation = np.array([width/3, 2*height])  # D

for deg in range(0, 360, 45):
    rec = plt.Rectangle(-point_of_rotation, width=width, height=height, 
                        color=str(deg / 360), alpha=0.9,
                        transform=Affine2D().rotate_deg_around(*(0,0), deg)+ax.transData)
    ax.add_patch(rec)
plt.show()
0 голосов
/ 26 февраля 2020

Я создал пользовательский класс Rectangle, который в качестве дополнительного аргумента имеет relative point of rotation - относительное среднее значение, измеренное в кадре, определенном исходными нижними левыми координатами прямоугольника (x0, y0) и angle.

*. 1006 *rec = RotatingRectangle((0, 0), width=1, height=0.1, rel_point_of_rot=(0, 0.05), angle=45)

создает прямоугольник, в котором относительная точка (0, 0.05) [средняя точка левой стороны] смещена к центру (0, 0) и вокруг нее выполняется вращение 45 deg балл.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

class RotatingRectangle(Rectangle):
    def __init__(self, xy, width, height, rel_point_of_rot, **kwargs):
        super().__init__(xy, width, height, **kwargs)
        self.rel_point_of_rot = rel_point_of_rot
        self.xy_center = self.get_xy()
        self.set_angle(self.angle)

    def _apply_rotation(self):
        angle_rad = self.angle * np.pi / 180
        m_trans = np.array([[np.cos(angle_rad), -np.sin(angle_rad)],
                            [np.sin(angle_rad), np.cos(angle_rad)]])
        shift = -m_trans @ self.rel_point_of_rot
        self.set_xy(self.xy_center + shift)

    def set_angle(self, angle):
        self.angle = angle
        self._apply_rotation()

    def set_rel_point_of_rot(self, rel_point_of_rot):
        self.rel_point_of_rot = rel_point_of_rot
        self._apply_rotation()

    def set_xy_center(self, xy):
        self.xy_center = xy
        self._apply_rotation()

height = 0.1
width = 1
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.set_xlim([-width * 1.2, width * 1.2])
ax.set_ylim([-width * 1.2, width * 1.2])
ax.plot(0, 0,  color='r', marker='o', markersize=10)
point_of_rotation = np.array([0, height/2])          # A
# point_of_rotation = np.array([width/2, height/2])  # B
# point_of_rotation = np.array([width/3, height/2])  # C
# point_of_rotation = np.array([width/3, 2*height])  # D

for deg in range(0, 360, 45):
    rec = RotatingRectangle((0, 0), width=width, height=height, 
                            rel_point_of_rot=point_of_rotation,
                            angle=deg, color=str(deg / 360), alpha=0.9)
    ax.add_patch(rec)

rectangles rectangles rectangles rectangles

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...