3つの3次元ポイントを軸とする2次元に変換するには


3つの3次元ベクトルA,B,Cがあり、ABを2次元空間のx軸に、ACを2次元空間のy軸にそれぞれ当てはめるような座標変換をするにはどうすればいいでしょうか。

[![3つの3次元ベクトルから新しい3次元系に変換](https://i.stack.imgur.com/J4X5x.png)](https://i.stack.imgur.com/J4X5x.png)  
素人考えでは下記のような操作ができればと思っているのですが、具体的なプログラムが組めません…。

  1. ABが新しい3次元系のx軸になるように回転する
  2. ACが新しい3次元系のxy平面上にくるように回転する
  3. ACが新しい3次元系のy軸にくるようカメラ？のz座標を調整する

よろしくお願いいたします。




takoika
さんの回答を参考に、[グラム・シュミットの正規直交化法](https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%A9%E3%83%A0%E3%83%BB%E3%82%B7%E3%83%A5%E3%83%9F%E3%83%83%E3%83%88%E3%81%AE%E6%AD%A3%E8%A6%8F%E7%9B%B4%E4%BA%A4%E5%8C%96%E6%B3%95)を使ってベクトルを変換できました。  
プログラムとテストケース、図を載せておきます。

[![動作確認用](https://i.stack.imgur.com/fL8qk.png)](https://i.stack.imgur.com/fL8qk.png)

[code]

    >>> import numpy as np
    >>> def transform(a, b, c, p):
    ...     v1 = b - a
    ...     v2 = c - a
    ...     u1 = v1
    ...     u1 = u1 / np.linalg.norm(u1)
    ...     u2 = v2 - (np.dot(u1, v2) / np.dot(u1, u1)) * u1
    ...     u2 = u2 / np.linalg.norm(u2)
    ...     u3 = np.cross(u1, u2)
    ...     u3 = u3 / np.linalg.norm(u3)
    ...     rot = np.array([u1, u2, u3])
    ...     return np.dot(rot, p - a)
    ... 
    >>> A = np.array((2, 0, 0))
    >>> B = np.array((2, 2, 0))
    >>> C = np.array((2, 2, 2))
    >>> p1 = np.array((0, 1, 0))
    >>> transform(A, B, C, p1)[:2]
    array([ 1.,  0.])
    >>> p2 = np.array((0, 1, 1))
    >>> transform(A, B, C, p2)[:2]
    array([ 1.,  1.])
    >>> p3 = np.array((0, 0, 1))
    >>> transform(A, B, C, p3)[:2]
    array([ 0.,  1.])
    >>> p4 = np.array((3, 0, 1))
    >>> transform(A, B, C, p4)[:2]
    array([ 0.,  1.])
    
[/code]

