11

一連の線を 90 度回転させようとしました (一緒にポリラインを形成します)。各行には、(x1, y1) と (x2, y2) などの 2 つの頂点が含まれます。私が現在やろうとしているのは、中心点 |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])
4

2 に答える 2

24

点 (x1,y1) と (x2,y2) の間の線分の中心点 (cx,cy) の座標は次のとおりです。

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

つまり、x 座標値と y 座標値の 2 つのペアの平均または算術平均です。

複数セグメントの線分またはポリラインの場合、その論理中心点の x 座標と y 座標は、すべての点の x 値と y 値の対応する平均にすぎません。平均は、値の合計をそれらの数で割ったものです。

2D 点(x,y)を原点(0,0) を中心に θ ラジアン回転する一般式は次のとおりです。

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

別の中心 (cx、cy) を中心に回転を実行するには、ポイントの x と y の値を調整する必要があります。最初に、ポイントの座標から目的の回転中心の座標を減算します。これにより、移動の効果があります (既知の幾何学では翻訳として)、数学的には次のように表されます。

    tx = x - cx
    ty = y - cy

次に、この中間点を必要な角度だけ回転させ、最後に回転点の x 値と y 値を各座標の x と y に加算します。幾何学的に言えば、次の一連の操作です。

この概念を拡張して、ポリライン全体を任意の点 (独自の論理中心など) を中心に回転できるようにすることができます。説明されている計算を、ポリライン内の各線分の各点に適用するだけです。

この計算の実装を簡素化するために、3 つの計算セットすべての数値結果を組み合わせて、それらすべてを同時に実行する一対の数式で表すことができます。したがって、新しい点 (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])
于 2013-02-12T21:40:24.347 に答える
2

あなたの中心点は次のようになります。

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

長さの半分を取り(x2 - x1) / 2、ラインが中央に到達し始める場所に追加するためです。

演習として、次の 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
于 2013-02-12T21:27:17.113 に答える