JavaScript 中的二维透视变换
2D perspective transform in JavaScript
正在寻找一个 code
示例,说明如何从特定角度的自上而下视图(90 度)计算(准确)矩形的尺寸。
例如 我有一个 1200mm x 2000mm
的矩形
如果矩形的一侧向下倾斜 30 degrees
,我将如何确定矩形的新透视测量值。 (从 90o 视角,自上而下)
从这个角度看,底边看起来更短了,当然事实并非如此。 (在某种程度上是伪 3D.. 但在 2D 形状和 2D 视图中)
编辑:这是一个参考问题,请添加替代答案和解决方案
您所描述的透视变换称为透视,我建议您不仅要查看我的答案,还要查找有关它的更多信息,因为它是具有各种应用程序的概念,可以通过不同的方法解决。
请记住 Javascript 不是我的强项,所以如果我犯了任何语法错误,我深表歉意,请指正。
对于您的特定形状,简单使用相似三角形应该可以为您提供顶点坐标,然后您可以使用它来构造您的形状。您可以在 space 中将顶点坐标定义为向量。
我将首先在 2d space 中将您的原始形状定义为一系列 4 个顶点。 (我将左下角定义为原点。)在 Javascript 中,您应该定义一个包含 4 个 3 值数组的二维数组。二维数组中的每个数组都是 [x,y,z] 形式的顶点坐标。 x 值将是顶点的水平值,y 值将是高度值,z 值将是它在 3d space 中的距离。可以通过将斜坡的斜边(在本例中为 2000)乘以斜坡角度的余弦(在本例中为 30 度)来获取 y 值。为了进行余弦运算,我们必须将角度从度数转换为弧度。转换始终是 pi = 180,因此以弧度表示的 30 是 pi/6。 x值可以通过斜边乘以同角度的正弦得到。
var hypotenuse = 2000;
var theta = Math.PI/6;
var x = Math.sin(theta)*hypotenuse;
var y = Math.cos(theta)*hypotenuse;
var z = 1200;
var vertices = [[0,y,0], [0,y,z], [x,0,0], [x,0,z]];
透视变换是由于观察者相对于对象的透视而发生的。因此,为了获得实际的透视变换,我们必须定义观察者的位置。我会在点(x/2,y+y/2,z/2).
任意定义他
var viewer = [x/2,y+y/2,z/2];
然后我们选择一个焦距来定义图像的定义位置。焦距只是与观看者的距离问题,因此它仅被定义为一个点。我将焦距任意设置为 (viewer_x,(y+y/2)/2,viewer_z) 因为它是距离 (y+y/2)/2观众。 但是,您必须确保焦点与观察者的 x 和 z 坐标相同,并且只有 y 轴发生变化。可以找到有关焦距和透视变换的更多信息在 http://en.wikipedia.org/wiki/3D_projection.
var focal_length = [viewer[0],(y+y/2)/2,viewer[2]];
1.Now 我们得到矩形的每个顶点沿 y 轴(我们应用透视变换的轴)到观察者的距离。
2.Then我们得到焦距y坐标到观察者的距离。
3.We 然后得到焦距和顶点距离的比值。
4.Then 将顶点的 x 和 z 坐标乘以该比率以获得每个顶点的新的缩短坐标。
通过简单地减去 y 坐标并取结果的绝对值来找到距离。为了获得更有效的代码,我将在一个 for 循环中完成这一切。
var focal_distance = Math.abs(viewer[1] - focal_length[1]);
//gets distance between focal point y and viewer y
var vert_distance;
for(var i = 0; i< vertices.length-1; i++){
vert_distance = Math.abs(viewer[1]-vertices[i][1]);
//access each individual vertex and and get the distance between vertex y and viewer y
for (var j = 0; j<vertices[i].length-1; j++){
vertices[i][j] = vertices[i][j]*(focal_distance/vert_distance);
//gets the ratio between focal distance and vertex distance and multiplies each vertex by it
}
}
最后,由于我们沿 y 轴进行了透视缩短,因此不再需要每个顶点的 y 坐标,因此我们现在将获取每个顶点并将其保存到一个新的 2d 顶点数组而不是 3d 顶点数组中。
var vertices2d = [[0,0],[0,0],[0,0],[0,0]];
//creates a new 2d vertex array of 4 empty 2d vertex coordinates
for(var i = 0; i<vertices.length-1; i++){
vertices2d[i][0] = vertices[i][0];
//sets the x values of the 2d vertices = to the x values of 3d vertices
vertices2d[i][1] = vertices[i][2];
//sets the y values of the 2d vertices = to the z values of the 3d vertices
}
现在只需将这些 2d 顶点坐标输入任何绘图程序,您就会得到想要的结果。
无论如何我都会让程序打印出顶点坐标:
for (var i = 0; i<vertices2d.length-1; i++){
document.write("(" + vertices2d[i][0] + "," + vertices2d[i][1] + ")");
}
随意修改观察者坐标、焦距y值、平面的长度和宽度以及斜坡角度以获得不同的结果。 干杯,如果您不明白,请随时提出任何问题。
不间断的完整代码如下:
var hypotenuse = 2000;
var theta = Math.PI/6;
var x = Math.Sin(theta)*hypotenuse;
var y = Math.Cos(theta)*hypotenuse;
var z = 1200;
var vertices = [[0,y,0], [0,y,z], [x,0,0], [x,0,z]];
var viewer = [x/2,y+y/2,z/2];
var focal_length = [viewer[0],(y+y/2)/2,viewer[2]];
var focal_distance = Math.abs(viewer[1] - focal_length[1]);
//gets distance between focal point y and viewer y
var vert_distance;
for(var i = 0; i< vertices.length-1; i++){
vert_distance = Math.abs(viewer[1]-vertices[i][1]);
//access each individual vertex and and get the distance between vertex y and viewer y
for (var j = 0; j<vertices[i].length-1; j++){
vertices[i][j] = vertices[i][j]*(focal_distance/vert_distance);
//gets the ratio between focal distance and vertex distance and multiplies each vertex by it
}
}
var vertices2d = [[0,0],[0,0],[0,0],[0,0]];
//creates a new 2d vertex array of 4 empty 2d vertex coordinates
for(var i = 0; i<vertices.length-1; i++){
vertices2d[i][0] = vertices[i][0];
//sets the x values of the 2d vertices = to the x values of 3d vertices
vertices2d[i][1] = vertices[i][2];
//sets the y values of the 2d vertices = to the z values of the 3d vertices
}
for (var i = 0; i<vertices2d.length-1; i++){
document.write("(" + vertices2d[i][0] + "," + vertices2d[i][1] + ")");
}
正在寻找一个 code
示例,说明如何从特定角度的自上而下视图(90 度)计算(准确)矩形的尺寸。
例如 我有一个 1200mm x 2000mm
如果矩形的一侧向下倾斜 30 degrees
,我将如何确定矩形的新透视测量值。 (从 90o 视角,自上而下)
从这个角度看,底边看起来更短了,当然事实并非如此。 (在某种程度上是伪 3D.. 但在 2D 形状和 2D 视图中)
编辑:这是一个参考问题,请添加替代答案和解决方案
您所描述的透视变换称为透视,我建议您不仅要查看我的答案,还要查找有关它的更多信息,因为它是具有各种应用程序的概念,可以通过不同的方法解决。
请记住 Javascript 不是我的强项,所以如果我犯了任何语法错误,我深表歉意,请指正。
对于您的特定形状,简单使用相似三角形应该可以为您提供顶点坐标,然后您可以使用它来构造您的形状。您可以在 space 中将顶点坐标定义为向量。
我将首先在 2d space 中将您的原始形状定义为一系列 4 个顶点。 (我将左下角定义为原点。)在 Javascript 中,您应该定义一个包含 4 个 3 值数组的二维数组。二维数组中的每个数组都是 [x,y,z] 形式的顶点坐标。 x 值将是顶点的水平值,y 值将是高度值,z 值将是它在 3d space 中的距离。可以通过将斜坡的斜边(在本例中为 2000)乘以斜坡角度的余弦(在本例中为 30 度)来获取 y 值。为了进行余弦运算,我们必须将角度从度数转换为弧度。转换始终是 pi = 180,因此以弧度表示的 30 是 pi/6。 x值可以通过斜边乘以同角度的正弦得到。
var hypotenuse = 2000;
var theta = Math.PI/6;
var x = Math.sin(theta)*hypotenuse;
var y = Math.cos(theta)*hypotenuse;
var z = 1200;
var vertices = [[0,y,0], [0,y,z], [x,0,0], [x,0,z]];
透视变换是由于观察者相对于对象的透视而发生的。因此,为了获得实际的透视变换,我们必须定义观察者的位置。我会在点(x/2,y+y/2,z/2).
任意定义他var viewer = [x/2,y+y/2,z/2];
然后我们选择一个焦距来定义图像的定义位置。焦距只是与观看者的距离问题,因此它仅被定义为一个点。我将焦距任意设置为 (viewer_x,(y+y/2)/2,viewer_z) 因为它是距离 (y+y/2)/2观众。 但是,您必须确保焦点与观察者的 x 和 z 坐标相同,并且只有 y 轴发生变化。可以找到有关焦距和透视变换的更多信息在 http://en.wikipedia.org/wiki/3D_projection.
var focal_length = [viewer[0],(y+y/2)/2,viewer[2]];
1.Now 我们得到矩形的每个顶点沿 y 轴(我们应用透视变换的轴)到观察者的距离。 2.Then我们得到焦距y坐标到观察者的距离。 3.We 然后得到焦距和顶点距离的比值。 4.Then 将顶点的 x 和 z 坐标乘以该比率以获得每个顶点的新的缩短坐标。
通过简单地减去 y 坐标并取结果的绝对值来找到距离。为了获得更有效的代码,我将在一个 for 循环中完成这一切。
var focal_distance = Math.abs(viewer[1] - focal_length[1]);
//gets distance between focal point y and viewer y
var vert_distance;
for(var i = 0; i< vertices.length-1; i++){
vert_distance = Math.abs(viewer[1]-vertices[i][1]);
//access each individual vertex and and get the distance between vertex y and viewer y
for (var j = 0; j<vertices[i].length-1; j++){
vertices[i][j] = vertices[i][j]*(focal_distance/vert_distance);
//gets the ratio between focal distance and vertex distance and multiplies each vertex by it
}
}
最后,由于我们沿 y 轴进行了透视缩短,因此不再需要每个顶点的 y 坐标,因此我们现在将获取每个顶点并将其保存到一个新的 2d 顶点数组而不是 3d 顶点数组中。
var vertices2d = [[0,0],[0,0],[0,0],[0,0]];
//creates a new 2d vertex array of 4 empty 2d vertex coordinates
for(var i = 0; i<vertices.length-1; i++){
vertices2d[i][0] = vertices[i][0];
//sets the x values of the 2d vertices = to the x values of 3d vertices
vertices2d[i][1] = vertices[i][2];
//sets the y values of the 2d vertices = to the z values of the 3d vertices
}
现在只需将这些 2d 顶点坐标输入任何绘图程序,您就会得到想要的结果。
无论如何我都会让程序打印出顶点坐标:
for (var i = 0; i<vertices2d.length-1; i++){
document.write("(" + vertices2d[i][0] + "," + vertices2d[i][1] + ")");
}
随意修改观察者坐标、焦距y值、平面的长度和宽度以及斜坡角度以获得不同的结果。 干杯,如果您不明白,请随时提出任何问题。
不间断的完整代码如下:
var hypotenuse = 2000;
var theta = Math.PI/6;
var x = Math.Sin(theta)*hypotenuse;
var y = Math.Cos(theta)*hypotenuse;
var z = 1200;
var vertices = [[0,y,0], [0,y,z], [x,0,0], [x,0,z]];
var viewer = [x/2,y+y/2,z/2];
var focal_length = [viewer[0],(y+y/2)/2,viewer[2]];
var focal_distance = Math.abs(viewer[1] - focal_length[1]);
//gets distance between focal point y and viewer y
var vert_distance;
for(var i = 0; i< vertices.length-1; i++){
vert_distance = Math.abs(viewer[1]-vertices[i][1]);
//access each individual vertex and and get the distance between vertex y and viewer y
for (var j = 0; j<vertices[i].length-1; j++){
vertices[i][j] = vertices[i][j]*(focal_distance/vert_distance);
//gets the ratio between focal distance and vertex distance and multiplies each vertex by it
}
}
var vertices2d = [[0,0],[0,0],[0,0],[0,0]];
//creates a new 2d vertex array of 4 empty 2d vertex coordinates
for(var i = 0; i<vertices.length-1; i++){
vertices2d[i][0] = vertices[i][0];
//sets the x values of the 2d vertices = to the x values of 3d vertices
vertices2d[i][1] = vertices[i][2];
//sets the y values of the 2d vertices = to the z values of the 3d vertices
}
for (var i = 0; i<vertices2d.length-1; i++){
document.write("(" + vertices2d[i][0] + "," + vertices2d[i][1] + ")");
}