将平面上的 3D 坐标转置到新的 2D 坐标系

Transpose 3D coordinates on a plane to a new 2D coordinate system

我一直致力于一个个人项目,以生成方程 x^2 + y^2 + z^2 = S 的整数解的图像,其中 'S' 是任何整数。

换句话说,我正在寻找所有 3D 点 [x,y,z],其中 x、y 和 z 都是完全平方整数并且 x + y + z = S

例如S=2809会有解:

在开始我的问题之前,这里有一些上下文的小切线:

一般方程 x + y + z = S 的所有解都位于由以下定义的二维平面上:

这是 x + y + z = 50 的所有解(不仅仅是方点)的图表,以说明该方程的所有解将位于由上面定义的 ABC 界定的同一平面上。请注意,下面三角形的尖端是:[50, 0, 0]、[0, 50, 0] 和 [0, 0, 50]

回到我的问题: 找到平方解点后,我想将3D解点转置成基于ABC平面的2D坐标,A为(0,0),B为max'x'值,C为max'y' 值。然后我希望将这些解决方案输出到一个图像文件。

我的线性代数知识匮乏,一直找不到基于3个非共线点将3D坐标转为2D平面坐标的方法

我的代码目前在 python 中,但是 algorithmic/mathematical 答案同样好!

非常感谢任何帮助!

据我所知,您已经可以找到您的 (x, y, z) 个点,您的问题是关于如何将它们投影到平面上。

请参阅 projection matrix 以了解如何将 3d 世界投影到您选择的图像平面上。

具体来说,您必须将 (x, y, z) 坐标表示为 homogeneous coordinates,将它们称为 (x, y, z, 1),并将它们乘以与正交的相关相机矩阵您需要施放它们的平面。

这将产生形式为 (x', y', f) 的二维齐次坐标,您可以通过 (x_projected, y_projected) = (x'/f, y'/f).

从中获得投影坐标

OpenCV是你的朋友。

回顾:

  1. 输入:n(x, y, z)
  2. 使用 opencv 获得大小为 (4, 3) 的投影(相机)矩阵 M 或使用任何工具自行计算。
  3. 将最后一个维度 1 添加到所有点以将它们作为 3d 齐次坐标:n(x, y, z, 1)
  4. 将所有点乘以矩阵得到投影点作为二维齐次坐标:M * (x, y, z, 1)^T = (x', y', f)
  5. 通过(x, y) = (x'/f, y'/f)
  6. 获得n实际二维投影坐标(相对于M矩阵定义的相机中心)

奖励:您可以将所有 (x, y, z, 1) 点作为列堆叠到 (4, n) 矩阵中,P,整个乘法过程将是 R = M * P,一个结果形状为 (3, n) 的矩阵 R,其列是生成的齐次坐标。

我认为 Gulzar 的回答是正确的,但更多的是围绕渲染(即相机和齐次坐标)。然而,我确实想出了如何做我想做的事。

import ast
import math
import matplotlib.pyplot as plt

def dot_3d(a, b):
    return (a[0]*b[0])+ (a[1]*b[1]) + (a[2]*b[2])

def minus_3d(a, b):
    return [a[0] - b[0], a[1] - b[1], a[2] - b[2]]

def midpoint_3d(a, b):
    return [(a[0] + b[0])/2, (a[1] + b[1])/2, (a[2] + b[2])/2]

def normalize_3d(vec):
    magnitude = math.sqrt(vec[0]**2 + vec[1]**2 + vec[2]**2)
    return [vec[0]/magnitude, vec[1]/magnitude, vec[2]/magnitude]

X = 2809

A = [X, 0, 0]
B = [0, X, 0]
C = [0, 0, X]

S = set([])
for a in range(X+1):
    if int(math.sqrt(a))**2 == a:
        for b in range(X+1):
            if int(math.sqrt(b))**2 == b:
                for c in range(X+1):
                    if int(math.sqrt(c))**2 == c and a + b + c == X:
                        S.add(str([a, b, c]))
S = list(S)

origin = A
normal = normalize_3d([X/3, X/3, X/3])
ax1 = normalize_3d(minus_3d(B, A))
ax2 = normalize_3d(minus_3d(C, midpoint_3d(A, B)))

answers = []

for point_str in S:
    point = ast.literal_eval(point_str)
    x = dot_3d(ax1, minus_3d(point, origin))
    y = dot_3d(ax2, minus_3d(point, origin))
    answers.append([x, y])

plt.scatter([p[0] for p in answers], [p[1] for p in answers])
plt.xlabel('x')
plt.ylabel('y')
plt.show()

绘制的起始 3D 坐标:

A​​BC 平面上的“投影”坐标: