将平面上的三维坐标转换为新的二维坐标系

2024-09-21 01:13:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在做一个个人项目,制作方程x^2+y^2+z^2=S的整数解的图像,其中“S”是任意整数

换句话说,我在寻找所有的三维点[x,y,z],其中x,y,z都是完美的平方整数,x+y+z=S

例如,S=2809将具有以下解决方案:

  • [14412961369]
  • [1447291936]
  • [0,02809]
  • 。。。加上上述所有排列(即144+729+1936=1936+729+144)

在我回答我的问题之前,这里有一个关于某些上下文的小切线:

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

  • A=[S,0,0]
  • B=[0,S,0]
  • C=[0,0,S]

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

ABC plane

回到我的问题: 在找到正方形的解算点之后,我想根据ABC平面将3D解算点转换为2D坐标,A为(0,0),B为最大“x”值,C为最大“y”值。然后我希望将这些解决方案输出到一个图像文件中

我的线性代数知识很贫乏,我一直无法找到一种基于3个非共线点将三维坐标转换为二维平面坐标的方法

我的代码目前是用python编写的,但算法/数学答案也一样好

非常感谢您的帮助


Tags: 项目图像定义图表整数解决方案平面公式
2条回答

在我看来,你已经可以找到你的(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添加到所有点,以将它们作为三维齐次坐标:n(x, y, z, 1)
  4. 将所有点乘以矩阵,以获得投影点作为二维齐次坐标:M * (x, y, z, 1)^T=(x', y', f)
  5. 通过(x, y)=(x'/f, y'/f)获取n实际二维投影坐标(相对于M矩阵定义的摄影机中心)

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

我认为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()

开始绘制三维坐标图: enter image description here

ABC平面上的“投影”坐标: enter image description here

相关问题 更多 >

    热门问题