如何计算 z 轴上的位置

Posted

技术标签:

【中文标题】如何计算 z 轴上的位置【英文标题】:How to calculate positions on a z-axis 【发布时间】:2016-08-26 13:11:45 【问题描述】:

我在上面的画布上画了一个简单的三坐标图;

我定义了一些常量来使用

var width = window.innerWidth * 0.5 , height = window.innerWidth * 0.5;
var cx = width / 2, cy = height / 2, cz = height / 2, blcx = 0, blcy = height, brcz = height, brcx = width, brcy = height;

var ySegment = height / 30;
var xSegment = width / 30; 
var xSegmentRatio = xSegment / width; 
var ySegmentRatio = ySegment / height;

cx 和 cy 和 cz 都指向画布的中心。 blcx 表示左下角-x,brcy 表示右下角-y 等。我意识到这有点骇人听闻,因为这是第一次尝试这样做,但如果你忍受对我来说,这里有一个我想要掌握的真实概念。

然后像这样画红线:

(function() 
    var gridCx   = cx,       gridCy   = cy,        gridCz = cz;
    var gridBlCx = blcx,     gridBlCy = brcy;
    for (var i = cx; i < width; i++) 
        gridCx += xSegment;
        gridBlCx += ySegment;
        gridCzx -= gridCzx * (xSegmentRatio / ySegmentRatio);
        ctx.beginPath();
        ctx.moveTo(gridCx, cy);
        ctx.lineTo(gridBlCx, height);
        ctx.strokeStyle="#FF0000";
        ctx.stroke();
    
)();

我试过了:

gridCzx -= gridCzx * xSegmentRatio;
gridCzy += gridCzy * ySegmentRatio;
ctx.beginPath();
ctx.moveTo(gridCzx, gridCzy);
ctx.lineTo(width, gridCzy);
ctx.strokeStyle = "#ff0000";
ctx.stroke();

得到了这个:

但我意识到我遗漏了一些基本的数学概念。感谢您提供的任何见解! 我的基本问题是:如何在 z 轴上选择一个与中心有一定距离的点?

【问题讨论】:

您的问题是什么?另外,请解释代码背后的直觉。我无法理解它。对变量的解释对开始会有很大帮助。 当然,我更新了操作。这里的直觉是我想定义三个轴,x/y/z,并且由于 html5 画布没有 z 轴,我需要找到一种方法来计算我在给定的 z 轴上绘制的一个点离中心有一段距离。我尝试做的第一件事是在 z/y 平面上绘制一个网格。 查看canvas内置的skew transformations 我的问题是如何在距离中心一定距离的情况下选择 z 轴上的点? 使用transformation matrix 来倾斜绘图,还可以在未变换空间中找到任何变换点。这是一个很好的transformation matrix tool 【参考方案1】:

将 3 维转化为 2 维

轴告诉我们如何移动

要在第一个维度 x 中找到一个点,请沿 x 轴从左到右移动。要在第二维 y 中找到一个点,您必须整合第一维和第二维,即从左到右的第一个 x,一旦你有了它,然后沿着屏幕向下的 y 轴第二个。

对于每个维度,您都依赖于前一个维度的定位。它还依赖于轴,x 和 y 轴彼此成 90 度,但它们可能在 45 或 120 度,这对于查找点的 2D 坐标没有任何区别。首先沿 X 轴,然后 Y 沿 y 轴。

向量函数

由于显示仅为 2D,因此轴可以表示为 2D 矢量。向量的长度告诉轴的比例。因此,对于 x 轴,如果我将轴定义为 2D(显示坐标)向量 (2,0),那么我说它在 x 坐标中的每个单位都经过 2 和 0。如果我想在 x 坐标 10 处,我将它乘以轴以获得屏幕位置。

因此代码...

function screenCoord(x,y)  // creates a coordinate in screen space
                            // screen space is always in pixels
                            // screen space always has the origin (0,0) at the top left
    return 
       x : x,
       y : y,
    


function screenVector(x,y) // a vector in screen space it points in a direction
                            // and its is in pixels 
    return                 // basically identical to the last function 
       x : x,
       y : y,
    

所以让我们定义我将 (2,0) 放大 2 倍的 X 轴

var xAxis = screenVector(2,0);

现在 x 位置说 10

var xPos = 10

要找到它的位置,我们需要沿 x 轴获取屏幕坐标。我们通过将 xAxis 乘以 xPos 来做到这一点。为了更容易,我们可以创建一个向量乘法函数

function multiply(vector, value)
     var x = vector.x * value; // multiply the vector x by value
     var y = vector.y * value; // multiply the vector y by value
     return screenCoord(x,y)

现在求xPos的第一维位置

var screenPos = multiply(xAxis, xPos); // returns the screen position of x = 10

现在要做第二个维度,我们将其添加到前面。让我们定义一个函数来将一个向量添加到另一个向量中

function add(vector1, vector2) // adds two vectors returning a new one
     var x = vector1.x + vector2.x;
     var y = vector1.y + vector2.y;
     return screenCoord(x,y);

现在让我们创建 y 轴

var yAxis = new screenVector(0,2); // y goes down the screen and has no x change

和y位置

var posY = 10;

现在让我们从 x 开始

var screenPosX = multiply(xAxis,posX); // get the x position on the screen
var screenPosY = multiply(yAxis,posY); // get the y position on the screen

现在我们将两个坐标的结果相加

var screenXY = add(screenPosX,screenPosY);

我们在屏幕上有一个坐标 x = 10 和 y = 10(在这种情况下,它位于 20 向下的像素位置 20。

第三维

现在不用花太多时间来猜测第 3 个 z 维度会发生什么。对于 x 沿 x 轴,然后 y 沿 y 轴,然后 z 沿 z 轴

所以定义z轴

var yAxis = new screenVector(1,-1); // z axis along the diagonal from bottom left to top right

现在是 z 坐标

var posZ = 10;

所以要找到我们的 3d 位置,x 沿其轴,然后沿其添加 y,然后沿其轴添加 z

var screenPosX = multiply(xAxis,posX); // get the x position on the screen
var screenPosY = multiply(yAxis,posY); // get the y position on the screen
var screenPosZ = multiply(zAxis,posZ); // get the z position on the screen

需要把它们加在一起

var screenXY = add(screenPosX,screenPosY);

然后是z

var screenXYZ = add(screenPosXY,screenPosZ);

然后你就知道如何从一组坐标转换到另一组坐标了。它被称为变换

起源

我们缺少最后一点信息。起源。这是屏幕上坐标 0,0,0 (x,y,z) 所在的位置。它是变换的最后一部分,位于屏幕坐标 (x,y) 中

var origin = screenCoords(100,500); // set the origin at 100 pixels across 500 down

从最后的计算我们得到屏幕空间中的screenXYZ坐标,我们需要添加原点

screenXYZ = add(screenXYZ ,origin);

现在您可以在二维屏幕上从原点开始在坐标 (10,10,10) (x,y,z) 处绘制像素。

矩阵

希望对您有所帮助,如果您了解您刚刚学习了如何使用 3D 转换矩阵。它将 x、y、z 轴作为一组三个 2D 方向和原点坐标。矩阵执行相同的功能步骤,只是它在一个简单的数组中执行,这使得它更有效,并且遵循一些矩阵规则允许非常复杂的转换。例如,如果你想旋转,你需要做的就是改变轴的方向并且你已经旋转了对象。改变比例只需改变轴的长度,移动物体只需改变原点的位置。

【讨论】:

这是一篇很棒的帖子。谢谢!在我决定它回答我的问题之前,我需要对其进行更多研究并尝试将其投入使用!这是我第一次接触向量和向量空间,所以可能需要一些时间。 关于增量/向量的好帖子。 :-) “轴告诉我们如何移动”-太棒了。【参考方案2】:

事实证明,javascriptMath.cos()Math.sin() 在这种情况下非常有用。我不得不考虑的方式是,就好像有连续的同心圆,半径从我的网格段长度开始,每次连续加倍。从那里,我在谷歌上搜索了一些关于如何在给定度数的圆圈上找到点的信息。事实证明,像三角形一样,圆圈有度数,即弧度,而我的 z-index 方向的一个是 5PI/4。因此,我的函数看起来像这样:

for (var i = 0; i < zDistance; i++) 
    var r = xSegment * i;
    ctx.beginPath();
    ctx.arc(cx, cy, r, 0, 2 * Math.PI);
    ctx.strokeStyle="white";
    ctx.stroke();
    var zRadian = 
        divided: function() 
            return 5 * Math.PI
        , 
        divisor: function() 
            return 4;
        
    
    var zRadian = zRadian.divided() / zRadian.divisor();
    var x = cx + r * Math.cos(zRadian);
    var y = cy - r * Math.sin(zRadian);
    ctx.beginPath();
    ctx.fillText('(' + x + ', ' + y + ')', x, y);
    ctx.stroke();

结果如下:

【讨论】:

以上是关于如何计算 z 轴上的位置的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB | MATLAB中绘图的奇淫技巧合集

MATLAB | MATLAB中绘图的奇淫技巧合集

MATLAB 上的 Z 变换极点和零点位置

xml 表面的位置和深度导致了在亮度和阴影方面的微弱变化。新的elevation属性允许你在Z轴上指定查看的位置,然后框架会为该查看底部的项目加上实时的动态阴影。你可以在布局中明确的以DP为单位设置它

xml 表面的位置和深度导致了在亮度和阴影方面的微弱变化。新的elevation属性允许你在Z轴上指定查看的位置,然后框架会为该查看底部的项目加上实时的动态阴影。你可以在布局中明确的以DP为单位设置它

xml 表面的位置和深度导致了在亮度和阴影方面的微弱变化。新的elevation属性允许你在Z轴上指定查看的位置,然后框架会为该查看底部的项目加上实时的动态阴影。你可以在布局中明确的以DP为单位设置它