Math 投影-将三维转换为二维

Math 投影-将三维转换为二维,math,graph,matrix,projection,Math,Graph,Matrix,Projection,我有问题或者,我不知道如何将具有x、y、z值的3d点转换为2d点, 我必须画投影,我有点的x,y,z值,但我不知道如何将它们转换成2d,这样我就可以将它们移动到我的轴上 我一直在查看wiki和google,但是我不太确定应该使用哪些矩阵转换来获得想要的结果。我强烈建议使用现有的图形包来完成这项工作,而不是尝试编写自己的库。我不知道您使用的是哪种语言,但OpenGL是一种开源图形引擎,可用于3D渲染,具有跨语言可比性,因此它可能是一个起点 如果您坚持手工操作,那么在问题的答案中有很好的示例代码。

我有问题或者,我不知道如何将具有x、y、z值的3d点转换为2d点, 我必须画投影,我有点的x,y,z值,但我不知道如何将它们转换成2d,这样我就可以将它们移动到我的轴上


我一直在查看wiki和google,但是我不太确定应该使用哪些矩阵转换来获得想要的结果。

我强烈建议使用现有的图形包来完成这项工作,而不是尝试编写自己的库。我不知道您使用的是哪种语言,但OpenGL是一种开源图形引擎,可用于3D渲染,具有跨语言可比性,因此它可能是一个起点


如果您坚持手工操作,那么在问题的答案中有很好的示例代码。

首先,让我们假设查看场景的摄影机位于原点的中心,并查看
-z
方向。 然后:

  • 透视投影如下所示:
    x'=x/z

    y'=y/z

  • 正交投影由以下公式给出:
    x'=x

    y'=y

    (即,仅丢弃z组件)

现在您已经应用了上述步骤,您可能会获得一个点,该点位于
(x',y')=(-28.4,+134.5)
。现在,您需要根据屏幕分辨率、相机“缩放因子”和纵横比对它们进行缩放和居中:例如,您可能需要乘以
zoom
,然后将
screen\u center
添加到
x
y
组件中(注意:大多数图形渲染系统的
y
方向朝下,因此您可能需要为
y
组件交换符号)。您可能仍然会得到负坐标的像素或其坐标大于画布大小的像素。只需丢弃它们:这意味着它们位于视锥体之外


最后,您可能想知道,如果您的相机没有指向
-z
或没有居中于原点,该怎么办。对于后者,很简单:只需将相机坐标减去所有3D点的分量,然后再做其他事情。对于相机旋转,实际上也很简单:您只需要在进行任何其他操作之前,以与摄影机旋转方向相反的方式旋转点。这只意味着您需要将所有3D坐标乘以摄影机旋转矩阵的转置。此步骤背后的思想是,移动摄影机与反向移动点完全相同(旋转矩阵的逆矩阵恰好是同一矩阵的转置).

如果你想在三维空间中旋转形状,你只需要考虑相机角度。如果你对线性代数和三角学有深入的了解,这是值得付出额外努力的,因为它使你的程序更加灵活,但如果你在数学方面不太擅长,我推荐以下解决方案

要将3D图像投影到2D平面中,您需要做的是创建和映射方程

(x,y,z) -> (x',y')
可以通过定义从三维点到二维点的三个映射来实现这一点

(1,0,0) -> (  1,  0)
(0,1,0) -> (  0,  1)
(0,0,1) -> (-.7,-.7)
我使用(-.7,-.7)表示z访问,因为该点距离原点大约1个单位,并且位于x和y访问的中间

得到这三个点后,就有足够的信息来计算任意点x,y,z

(x,y,z) -> (1*x - .7*z, 1*y - .7*z)
在计算机图形学中,网格的原点不在屏幕的中心,而是在左上角。为了使用我们在程序中刚刚生成的方程式,我们必须定义一个偏移量来将原点移动到屏幕的中心。我们将此偏移点称为(Ox,Oy)

随着偏移量的增加,我们的方程如下

(x,y,z) -> (Ox + 1*x - .7*z, Oy + 1*y - .7*z)

我找到了一种将3D投影到等轴测的方法

我假设等轴测视图有一个角度,当然还有一个像这样的3D点

Dim IsometricViewAngle As Integer = 30
Dim RowPoint As New Point3D(dx,dy,dz)
哪些dx、dy和dz是您的自定义值。 然后我必须为X和Y的增量和减量计算一个
Delta
值,如

Dim XDelta = Math.Cos(IsometricViewAngle * Math.PI / 180)
Dim YDelta = Math.Sin(IsometricViewAngle * Math.PI / 180)
Dim ZDelta = 0.5
好了,现在我要把3D点投影到2D点上:

Dim X As Double = (RowPoint.X * XDelta) + (RowPoint.Y * YDelta)
Dim Y As Double = (RowPoint.X * XDelta) + (RowPoint.Z * ZDelta)
Dim ProjectedPoint As New Point(X,Y)
最后的结果在RadDiagram中效果最好。 关于/

这对我来说很有用:(在vb中)。 f_节点是平面节点,a_节点是经过alpha、beta和gamma变换后的3d节点。(x、y、z)是一个点。关于

    ca = Cos(alpha)
    sa = Sin(alpha)
    cb = Cos(beta)
    sb = Sin(beta)
    cg = Cos(gamma)
    sg = Sin(gamma)
    q(1) = cg * (cb * X - sb * (sa * Y + ca * z)) - sg * (ca * Y - sa * z)
    q(2) = sg * (cb * X - sb * (sa * Y + ca * z)) + cg * (ca * Y - sa * z)
    q(3) = sb * X + cb * (sa * Y + ca * z)

    f_nodes(i, 1) = q(1)
    f_nodes(i, 2) = q(2)

    a_nodes(i, 1) = q(1)
    a_nodes(i, 2) = q(2)
    a_nodes(i, 3) = q(3)

你知道你想把它们投射到哪个平面上吗?这个平面是如何给出的(以什么形式)嗯,我不知道平面,但是我有函数,所以我从min-max开始,以x-y计算z点,然后我必须在轴上设置这些点,我在上面画过,我甚至不知道如何开始这样做,我看了几部关于绘制点的电影,但是我必须绘制函数,所以我必须做一些如何连接这些点,我发现它与矩阵有关,但不确定我应该应用什么矩阵变换。你可能会发现有用的:和它相关的任何东西。汉克斯,去读这个问题,但是我必须自己写,如果3D值太大,比如
2565452
等,我可以用画布。你可以分割X、Y和Z按
Dim ScaleValue作为Ineger=10000