简体   繁体   English

如何计算z轴上的位置

[英]How to calculate positions on a z-axis

我在下面的画布中绘制了一个简单的3坐标图

I drew a simple 3-coordinate graph in canvas above; 我在画布上画了一个简单的3坐标图;

I defined a few constants to work with 我定义了一些常量来处理

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 and cy and cz all refer to the center of the canvas. cx和cy和cz都是指画布的中心。 blcx means bottom-left-corner-x, brcy is bottom-right-corner-y, etc. I realize this is a bit hack-ish, as this is the first attempt to do this, but if you bear with me, there is a real concept I am trying to grasp here. blcx意味着左下角-x, brcy是右下角-y等。我意识到这有点黑客,因为这是第一次尝试这样做,但如果你忍受我,那里是一个我想在这里抓住的真实概念。

and then drew the red lines like this: 然后画出这样的红线:

(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();
    }
})();

I tried this: 我试过这个:

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

and got this: 得到了这个:

在此输入图像描述

But I realized I am missing some fundamental mathematical concept. 但我意识到我缺少一些基本的数学概念。 Thanks for any insight you can give! 感谢您提供的任何见解! My basic question here is: How do I select a point on the z-axis given a distance away from the center? 我的基本问题是: 如何在距离中心一定距离的z轴上选择一个点?

Transforming 3 dimensions into 2 dimensions 将3个维度转换为2个维度

Axis tell us how to move Axis告诉我们如何移动

To find a point in the first dimension x, move along the x axis, from left to right. 要在第一维x中找到一个点,请沿x轴从左向右移动。 To find a point in the second dimension y you must integrate both the first and second dimensions, thus 1st x from left to right, once you have that then 2nd along the y axis down the screen. 要在第二个维度y中找到一个点,您必须整合第一个和第二个维度,从而从左到右依次为第一个x,然后在屏幕下沿y轴进行第二个x。

With each dimension you rely on the positioning of the previous dimension. 每个维度都依赖于前一维度的定位。 It also relies on the axis, the x and y axis are at 90 deg to each other, but they could be at 45 or 120, it would not make any difference to finding 2D coords of a point. 它也依赖于轴,x和y轴彼此成90度,但它们可以是45或120,找到一个点的2D坐标没有任何区别。 First along X axis then Y along the y axis. 首先沿X轴,然后沿y轴Y.

Vector functions 矢量函数

Because the display is only 2D the axis can be represented as 2D vectors. 因为显示器仅为2D,所以轴可以表示为2D矢量。 The length of the vector tells the scale of the axis. 矢量的长度表示轴的比例。 Thus for the x axis if I define the axis as a 2D (display coords) vector (2,0) then I am saying that it goes 2 across and 0 down for each unit in the x coordinate. 因此,对于x轴,如果我将轴定义为2D(显示坐标)向量(2,0),那么我说它对于x坐标中的每个单位为2和0。 If I want to be at x coordinate 10 I multiply it by the axis to get the screen position. 如果我想要在x坐标10处,我将它乘以轴以获得屏幕位置。

Thus to the code... 因此对代码......

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,
    }
}

So let's define the X axis that I had (2,0) scaled up by 2 所以让我们定义我有(2,0)按比例缩放2的X轴

var xAxis = screenVector(2,0);

Now ax position say 10 现在斧头位置说10

var xPos = 10

To find its location we need to get the screen coordinates along the x axis. 要找到它的位置,我们需要获得沿x轴的屏幕坐标。 We do that by multiplying xAxis by xPos. 我们通过将xAxis乘以xPos来实现。 To make it easier we can create a vector multiply function 为了更容易,我们可以创建一个向量乘法函数

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)
}

Now to find the first dimensional pos of xPos 现在找到xPos的第一个维度位置

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

Now to do the 2nd dimension we add that to the previous. 现在做第二个维度,我们将其添加到前一个维度。 Let's define a function to add a vector to another 让我们定义一个向另一个添加向量的函数

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);
}

So now lets create the y axis 所以现在让我们创建y轴

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

and the y pos 和y pos

var posY = 10;

So now lets do it from x 所以现在让我们从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

Now we add the results of the two coordinates 现在我们添加两个坐标的结果

var screenXY = add(screenPosX,screenPosY);

And we have a coordinate on the screen of x = 10 and y = 10 (which in this case turns out to be at pixel location 20 across 20 down. 我们在x = 10和y = 10的屏幕上有一个坐标(在这种情况下,它在20英尺处的像素位置20处。

The 3rd dimension 第三个维度

Now it does not take much to guess what happens for the 3rd z dimension. 现在猜测第3个z维度会发生什么并不需要太多。 For x along x axis, then y along the y axis and then z along the z axis 对于沿x轴的x,沿y轴为y,然后沿z轴为z

So define the z axis 因此定义z轴

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

Now the z coord 现在是z coord

var posZ = 10;

So to find our 3d position, x along its axis, then add y along its and then add z along its axis 因此,要找到我们的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

need to add them together 需要将它们加在一起

var screenXY = add(screenPosX,screenPosY);

Then z 然后是z

var screenXYZ = add(screenPosXY,screenPosZ);

and there you have how to do the conversion from one set of coordinates to another. 在那里你有如何从一组坐标转换到另一组坐标。 It is called a transform 它被称为变换

The origin 起源

We are missing one last bit of information. 我们遗漏了最后一点信息。 The origin. 起源。 This is where on the screen the the coords 0,0,0 (x,y,z) will be. 这是屏幕上的坐标0,0,0(x,y,z)。 It is the last part of the transform and is in screen coords (x,y) 它是变换的最后一部分,是屏幕坐标(x,y)

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

From the last calculation we got the screenXYZ coordinate in screen space, we need to add the origin to it 从上次计算中我们得到了屏幕空间中的screenXYZ坐标,我们需要将原点添加到它

screenXYZ = add(screenXYZ ,origin);

Now you can draw the pixel at coordinates (10,10,10) (x,y,z) from the origin in on the 2d screen. 现在,您可以在2d屏幕上从原点绘制坐标(10,10,10)(x,y,z)处的像素。

The Matrix 矩阵

Hope that helps, if you understand that you have just learnt how to use a 3D transformation matrix. 希望这有帮助,如果您了解您刚刚学会了如何使用3D转换矩阵。 It holds the x,y,z axis as a set of three 2D directions, and the coordinates of the origin. 它将x,y,z轴保持为三个2D方向的集合,以及原点的坐标。 The matrix does the very same functional steps, just it does it in a simple array that makes it more efficient and following some matrix rules allows very complex transforms. 矩阵执行完全相同的功能步骤,只是它在一个简单的数组中使它更有效,并遵循一些矩阵规则允许非常复杂的变换。 For example if you want to rotate, all you need to do is change the direction of the axies and you have rotated the object. 例如,如果要旋转,您需要做的就是更改轴的方向并旋转对象。 To change the scale just change the length of the axis, to move the object just change the position of the origin. 要更改比例只需更改轴的长度,移动对象只需更改原点的位置即可。

It turns out, JavaScript's Math.cos() and Math.sin() are super helpful in this scenario. 事实证明,JavaScript的Math.cos()Math.sin()在这种情况下非常有用。 The way I had to think about it was as if there were successive concentric circles with radiuses starting at my grid segment length and doubling for each succession. 我不得不考虑它的方式就好像有连续的同心圆,半径从我的网格段长度开始,每次连续加倍。 From there, I google a bit about how to find the point on a circle given a degree. 从那里,我谷歌一些关于如何在给定学位的圆上找到点。 It turns out circles, like triangles, have degrees, ie radians, and the one for the direction of my z-index is 5PI/4. 事实证明,圆形,如三角形,有度,即弧度,而我的z-index方向的圆是5PI / 4。 Therefore, my function looks something like this: 因此,我的函数看起来像这样:

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();
}

And here is the result: 这是结果:

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM