【问题标题】:Rotate line around center point given two vertices给定两个顶点围绕中心点旋转线
【发布时间】:2013-01-28 07:44:27
【问题描述】:

我一直在尝试将一堆线旋转 90 度(它们一起形成一条折线)。每行包含两个顶点,例如 (x1, y1) 和 (x2, y2)。我目前正在尝试做的是围绕线的中心点旋转,给定中心点 |x1 - x2|和 |y1 - y2|。出于某种原因(我不是很精通数学)我无法让线条正确旋转。

有人可以验证这里的数学是正确的吗?我认为这可能是正确的,但是,当我将线的顶点设置为新的旋转顶点时,下一行可能不会从上一行抓取新的 (x2, y2) 顶点,从而导致线旋转不正确.

这是我写的:

def rotate_lines(self, deg=-90):
    # Convert from degrees to radians
    theta = math.radians(deg)

    for pl in self.polylines:
        self.curr_pl = pl
        for line in pl.lines:
            # Get the vertices of the line
            # (px, py) = first vertex
            # (ox, oy) = second vertex
            px, ox = line.get_xdata()
            py, oy = line.get_ydata()

            # Get the center of the line
            cx = math.fabs(px-ox)
            cy = math.fabs(py-oy)

            # Rotate line around center point
            p1x = cx - ((px-cx) * math.cos(theta)) - ((py-cy) * math.sin(theta))
            p1y = cy - ((px-cx) * math.sin(theta)) + ((py-cy) * math.cos(theta))

            p2x = cx - ((ox-cx) * math.cos(theta)) - ((oy-cy) * math.sin(theta))
            p2y = cy - ((ox-cx) * math.sin(theta)) + ((oy-cy) * math.cos(theta))

            self.curr_pl.set_line(line, [p1x, p2x], [p1y, p2y])

【问题讨论】:

  • p2y 公式对于第二个减号是错误的。
  • 很好,谢谢。是一个错字!
  • 您使用的是什么图形/几何模块?
  • @martineau Matplotlib 当时,我相信。

标签: python rotation trigonometry


【解决方案1】:

点(x1,y1)和(x2,y2)之间的线段的中心点(cx,cy)坐标为:

    cx = (x1 + x2) / 2
    cy = (y1 + y2) / 2

换句话说,它只是两对 x 和 y 坐标值的平均值或算术平均值。

对于多段线或折线,其逻辑中心点的 x 和 y 坐标只是所有点的 x 和 y 值的相应平均值。平均值只是值的总和除以它们的数量。

rotate a 2D point (x,y) θ 弧度原点周围 (0,0) 的一般公式为:

    x′ = x * cos(θ) - y * sin(θ)
    y′ = x * sin(θ) + y * cos(θ)

要围绕不同的中心(cx, cy)执行旋转,需要通过首先从该点的坐标中减去所需旋转中心的坐标来调整该点的 x 和 y 值,其效果为移动(在几何学中称为translating)它在数学上表示如下:

    tx = x - cx
    ty = y - cy

然后将该中间点旋转所需的角度,最后将旋转点的 x 和 y 值返回添加到每个坐标的 x 和 y。在几何术语中,它是以下操作序列:Tʀᴀɴsʟᴀᴛᴇ ─► Rᴏᴛᴀᴛᴇ ─► Uɴᴛʀᴀɴsʟᴀᴛᴇ。

这个概念可以扩展到允许围绕任意点旋转整条折线——例如它自己的逻辑中心——只需将描述的数学应用于其中每个线段的每个点。

为了简化这种计算的实现,所有三组计算的数值结果可以用一对同时执行它们的数学公式组合和表达。所以一个新的点 (x′,y′) 可以通过旋转一个现有的点 (x,y) 得到一个新的点 (x',y'), θ 弧度围绕点 (cx, cy) 使用:

    x′ = (  (x - cx) * cos(θ) + (y - cy) * sin(θ) ) + cx
    y′ = ( -(x - cx) * sin(θ) + (y - cy) * cos(θ) ) + cy

将此数学/几何概念融入您的函数会产生以下结果:

from math import sin, cos, radians

def rotate_lines(self, deg=-90):
    """ Rotate self.polylines the given angle about their centers. """
    theta = radians(deg)  # Convert angle from degrees to radians
    cosang, sinang = cos(theta), sin(theta)

    for pl in self.polylines:
        # Find logical center (avg x and avg y) of entire polyline
        n = len(pl.lines)*2  # Total number of points in polyline
        cx = sum(sum(line.get_xdata()) for line in pl.lines) / n
        cy = sum(sum(line.get_ydata()) for line in pl.lines) / n

        for line in pl.lines:
            # Retrieve vertices of the line
            x1, x2 = line.get_xdata()
            y1, y2 = line.get_ydata()

            # Rotate each around whole polyline's center point
            tx1, ty1 = x1-cx, y1-cy
            p1x = ( tx1*cosang + ty1*sinang) + cx
            p1y = (-tx1*sinang + ty1*cosang) + cy
            tx2, ty2 = x2-cx, y2-cy
            p2x = ( tx2*cosang + ty2*sinang) + cx
            p2y = (-tx2*sinang + ty2*cosang) + cy

            # Replace vertices with updated values
            pl.set_line(line, [p1x, p2x], [p1y, p2y])

【讨论】:

  • 您的代码有误 - 您需要将平均 length 添加到初始坐标。
  • @martineau:取点 (1, 1) 和 (4, 4),您的算法将在 (1.5, 1.5) 处给出一个中心。
  • 投票支持翻译/旋转。 :D
  • 所以不是围绕折线中每条线的中心旋转,而是应该围绕整个折线的“中心”点旋转?
  • 是的,如果这是您希望它旋转的点——它可以是您想要的任何点。我还更正了答案第一部分的数学运算并将其添加回来。
【解决方案2】:

你的中心点将是:

centerX = (x2 - x1) / 2 + x1
centerY = (y2 - y1) / 2 + y1

因为您将长度的一半 (x2 - x1) / 2 添加到您的行开始到中间的位置。

作为练习,取两行:

line1 = (0, 0) -> (5, 5)
then: |x1 - x2| = 5, when the center x value is at 2.5.

line2 = (2, 2) -> (7, 7)
then: |x1 - x2| = 5, which can't be right because that's the center for
the line that's parallel to it but shifted downwards and to the left

【讨论】:

  • 谢谢,这似乎解决了轮换问题;但是,我仍然必须将每条线正确连接在一起(它们目前单独旋转到位)。尽管如此,这解决了我最关心的问题。谢谢。
  • @adchilds:如果您想一次旋转所有线(我假设折线有点像多边形?)那么您需要找到折线的质心并旋转所有围绕该中心的线的点。
  • @sdasdadas: (x2 - x1) / 2 + x1 就是 (x1 + x2)/2
猜你喜欢
  • 1970-01-01
  • 2013-05-20
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多