【问题标题】:Draw a box at an angle画一个有角度的盒子
【发布时间】:2018-11-20 02:12:50
【问题描述】:

如何更改下面的代码,使 drawRect 也接受 angle 参数?

(x, y) 代表质心。据我所知,我想确定四个角的坐标,然后将它们全部围绕(x, y) 旋转那么多度,保持相同的距离。

# draw a line from a to b
def line(a, b):
  # [code omitted]

def drawRect(x, y, w, h):
    a = (x - w / 2, y - h / 2)
    b = (x + w / 2, y - h / 2)
    c = (x + w / 2, y + h / 2)
    d = (x - w / 2, y + h / 2)
    line(a, b)
    line(b, c)
    line(c, d)
    line(d, a)

【问题讨论】:

  • 感谢您纠正我的回答,非常感谢。

标签: python graphics drawing trigonometry


【解决方案1】:

另一种可能的解决方案(也未测试):

from math import cos, sin, pi
def drawRect(x, y, w, h, angle):
    x_vec = (cos(angle), sin(angle))
    y_vec = (cos(angle+pi/2.0), sin(angle+pi/2.0))
    a = (x - x_vec[0]*w/2 - y_vec[0]*h/2, y - x_vec[1]*w/2 - y_vec[1]*h/2)
    b = (x + x_vec[0]*w/2 + y_vec[0]*h/2, y - x_vec[1]*w/2 - y_vec[1]*h/2)
    c = (x + x_vec[0]*w/2 + y_vec[0]*h/2, y + x_vec[1]*w/2 + y_vec[1]*h/2)
    d = (x - x_vec[0]*w/2 - y_vec[0]*h/2, y + x_vec[1]*w/2 + y_vec[1]*h/2)
    line(a, b)
    line(b, c)
    line(c, d)
    line(d, a)

【讨论】:

  • 这似乎是正确的,并且比我的解决方案更优雅。我忘了考虑角度对高度和宽度的影响。
  • 奇怪,我只是从中得到正确的角度......也许我做错了什么
  • 不确定你的意思。你期待的是没有直角的矩形吗?
【解决方案2】:

您需要分解问题。绘制矩形和旋转矩形的点可以是单独的函数。通过将旋转变成一个类可以避免冗余计算。

class rotate:
    def __init__(self, degrees):
        angle = math.radians(degrees)
        self.sin = math.sin(angle)
        self.cos = math.cos(angle)

    def pt(self, x, y):
        return x * self.cos + y * self.sin, y * self.cos - x * self.sin

def drawRect(x, y, w, h, degrees):
    rot = rotate(degrees)
    x1, y1 = rot.pt(-w / 2, -h / 2)
    a = x + x1, y + y1
    x2, y2 = rot.pt( w / 2, -h / 2)
    b = x + x2, y + y2
    x3, y3 = rot.pt( w / 2,  h / 2)
    c = x + x3, y + y3
    x4, y4 = rot.pt(-w / 2,  h / 2)
    d = x + x4, y + y4
    line(a, b)
    line(b, c)
    line(c, d)
    line(d, a)

【讨论】:

  • 这会正确旋转矩形,但会将它们从原始位置移开
  • 它在旋转这些点,但它在旋转它们围绕的什么点?
  • @ʞɔıu 原点是 (0,0)。这就是我在 xy 旋转后添加它们的原因。
【解决方案3】:

我会使用numpy,因为它允许更方便的数组计算,在本例中是矩阵计算。

import numpy as np

首先你可以定义一个旋转函数,它接受一个以度为单位的角度并返回相应的旋转矩阵:

def rot(phi):
  phi = np.deg2rad(phi)
  return np.array([[np.cos(phi), -np.sin(phi)], [np.sin(phi), np.cos(phi)]])

然后您可以将旋转添加到您的函数中,例如:

def drawRect(x, y, w, h, angle):
    a = np.array((-w / 2, -h / 2))
    b = np.array((w / 2, -h / 2))
    c = np.array((w / 2, h / 2))
    d = np.array((-w / 2, h / 2))
    if angle != 0:
        a = np.matmul(rot(angle), a)
        b = np.matmul(rot(angle), b)
        c = np.matmul(rot(angle), c)
        d = np.matmul(rot(angle), d)
    a += [x, y]
    b += [x, y]
    c += [x, y]
    d += [x, y]
    line(a, b)
    line(b, c)
    line(c, d)
    line(d, a)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-20
    • 2016-11-14
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多