我有一个问题是围绕另一个旋转一个点。 我不擅长三角学,所以请帮助我并纠正我的解决方案。
要围绕另一个点旋转一个点,我将点移动到坐标系的原点,以便我想要旋转的点将位于坐标系的原点(0,0,0),旋转点绕Z点, Y轴和Z轴然后将其移回。
示例:我需要围绕y(3,2,1)点旋转点x(1,1,1),因此我在x,y附近从x - x @Test(dependsOnMethods="testStatusCode")
public void createUser1(ITestContext testContext) {
//Test code goes here
}
减去y点的坐标和z轴,然后通过添加y坐标将x``返回到正确的位置。它会起作用吗?
抱歉英语不好。
答案 0 :(得分:5)
2D坐标通过2个值x和y定义位置。 x是沿x轴的距离,y是沿y轴的距离。按照惯例,计算机图形通常具有从左到右定义的x轴和从上到下定义的y轴。
此答案中的注释代码为伪代码,不代表任何特定语言。
我们可以将轴表示为矢量,例如x轴在x方向上为1个单位,向下为0个单位,y轴在x方向上为0个单位,向下为1个单位。
对于代码,我们将向量定义为(例如x轴xAxis.x = 1
,yAxis.y = 0
)
Axis具有重要的品质,它们总是1个单位长。请参阅下面的单位矢量
因此,定义了轴,我们可以通过沿x轴然后沿y轴移动来找到它的位置。
xAxis = { x : 1, y : 0 }; // define the x axis
yAxis = { x : 0, y : 1 }; // define the y axis
point = { x : 10, y : 10 };
// position the point first move along the x axis by distance x
pos.x = point.x * xAxis.x;
pos.y = point.x * xAxis.y;
// then move along the y axis by distance y
pos.x = pos.x + point.y * yAxis.x;
pos.y = pos.y + point.y * yAxis.y;
这似乎是定位观点的漫长道路。但是当您旋转坐标系时,您实际上是在旋转x轴和y轴。因此,要获得旋转坐标系中的坐标,您需要2个旋转轴。请参阅下面的角度单位矢量
x轴旋转了旋转量,y轴与x轴成90度。
rotation = PI / 4; // using radians rotate clockwise 45 deg
// get the x axis at 45 deg
xAxis.x = cos(rotation);
xAxis.y = sin(rotation);
// get the y axis at 90 deg (PI / 2) from the x axis
yAxis.x = cos(rotation + (PI / 2));
yAxis.y = sin(rotation + (PI / 2));
我们现在可以在旋转坐标系中移动点
point = { x : 10, y : 10 };
// position the point first move along the x axis by distance x
pos.x = point.x * xAxis.x;
pos.y = point.x * xAxis.y;
// then move along the y axis by distance y
pos.x = pos.x + point.y * yAxis.x;
pos.y = pos.y + point.y * yAxis.y;
有一些捷径。 y轴与x轴成90度(除非倾斜)旋转矢量90deg我们交换组件否定y
// get the x axis at 45 deg
xAxis.x = cos(rotation);
xAxis.y = sin(rotation);
// get y at 90 deg from x
yAxis.x = -xAxis.y;
yAxis.y = xAxis.x;
同样沿轴移动,每个组件都独立于另一个组件,因此计算可以在一行进行。
pos.x = point.x * xAxis.x + point.y * yAxis.x;
pos.y = point.x * xAxis.y + point.y * yAxis.y;
坐标系由原点以及描述轴的单位矢量定义。要围绕特定点旋转点,我们需要将旋转点作为原点。然后我们移动坐标以相对于新原点旋转
point = { x : 10, y : 10 };
origin = { x : 5 , y : 4 };
// move point relative to the origin
pos.x = point.x - origin.x;
pos.y = point.y - origin.y;
现在我们可以应用轮换
rotatedPos.x = pos.x * xAxis.x + pos.y * yAxis.x;
rotatedPos.y = pos.x * xAxis.y + pos.y * yAxis.y;
但是旋转点仍然相对于原点,我们需要将其相对于原点移回。
rotatedPos.x = rotatedPos.x + origin.x;
rotatedPos.y = rotatedPos.y + origin.y;
在计算机图形学中,我们通常保持相对于其本地原点的相关坐标。它有一个坐标系,我们称之为局部坐标,以[0,0]或3d [0,0,0]为旋转点。这意味着我们可以跳过相对于旋转点移动点的计算部分。
然后我们可以为每个轴在一行中进行旋转和定位
pos.x = point.x * xAxis.x + point.y * yAxis.x + origin.x;
pos.y = point.x * xAxis.y + point.y * yAxis.y + origin.y;
我们想要缩放坐标也很常见,这可以通过改变表示每个轴的单位矢量的长度来完成。例如,如果我们想沿x轴缩放坐标2次,我们将x轴设为2倍
point = {x : 5, y : 6}; // point in local coordinates.
xAxis = {x : 1, y : 0}; // normalised x axis
xAxis.x = xAxis.x * 2; // scale x axis
xAxis.y = xAxis.y * 2;
// apply transformation.
pos.x = point.x * xAxis.x + point.y * yAxis.x + origin.x;
pos.y = point.x * xAxis.y + point.y * yAxis.y + origin.y;
对于3D,一切都大致相同,但有一个额外的轴和组件
xAxis = {x : 1, y : 0, z : 0}; // direction and scale of x axis
yAxis = {x : 0, y : 1, z : 0}; // direction and scale of y axis
zAxis = {x : 0, y : 0, z : 1}; // direction and scale of z axis
origin = {x : 0, y : 0, z : 0}; // position of origin.
所以将点移动到上面描述的3D坐标系中
point = {x : 5, y : 6, z : 4}; // point in local coordinates.
// move point.x distances along x axis
pos.x = point.x * xAxis.x
pos.y = point.x * xAxis.y
pos.z = point.x * xAxis.z
// move point.y distances along y axis
pos.x += point.y * yAxis.x
pos.y += point.y * yAxis.y
pos.z += point.y * yAxis.z
// move point.y distances along y axis
pos.x += point.z * zAxis.x
pos.y += point.z * zAxis.y
pos.z += point.z * zAxis.z
// then relative to the origin
pos.x += origin.x
pos.y += origin.y
pos.z += origin.z
或更紧凑
pos.x = point.x * xAxis.x + point.y * yAxis.x + point.z * zAxis.x + origin.x
pos.y = point.x * xAxis.y + point.y * yAxis.y + point.z * zAxis.y + origin.y
pos.z = point.x * xAxis.z + point.y * yAxis.z + point.z * zAxis.z + origin.z
以上内容开始变得有点笨拙,为了简化它,我们可以转换上述对象point
,xAxis
,yAxis
,zAxis
,origin
到一组数组(称为矩阵)
point = [5,6,4]; // vector as array [x,y,z]
origin = [0,0,0]; // origin as array [x,y,z]
rotation = [1,0,0,0,1,0,0,0,1]; // 3 axis [x.x,x.y,x.z, y.x,y.y,y.z, z.x,z.y,z.z]
// rotation /*
[x.x,x.y,x.z, // x axis
y.x,y.y,y.z, // y axis
z.x,z.y,z.z] // z axis
*/
符号可以简化,在许多语言中,重载将允许您以速记形式直接进行数学运算。
pos = point * rotation + origin;
在2D中,我们通常只围绕3D的一个虚轴(z轴进出屏幕)旋转,我们围绕3轴,x,y或z轴之一旋转。
我们旋转的顺序也会影响最终的旋转位置。绕z旋转5度然后围绕y旋转10度不等于y度约10度然后围绕z旋转5度。
由于每个轴本身都是一个可以旋转的矢量,我们可以通过旋转矩阵旋转每个轴。结果是一个矩阵,其中包含许多旋转。
所以说我们想围绕z轴旋转10度,我们创建3个旋转轴
ang = 10; // in deg
xAxisA = [cos(ang) ,sin(ang),0]; // 1 unit long
yAxisA = [-sin(ang),cos(ang),0]; // 1 unit long
zAxisA = [0 ,0 ,1]; // 1 unit long
或作为旋转矩阵
A = rotationZ = [cos(ang), sin(ang), 0, -sin(ang), cos(ang), 0, 0, 0, 1];
然后我们想围绕y
旋转xAxisB = [cos(ang) ,0 , sin(ang)]; // 1 unit long
yAxisB = [0, 1 , 0 ]; // 1 unit long
zAxisB = [-sin(ang),0, cos(ang)]; // 1 unit long
或作为旋转矩阵
B = rotationY = [cos(ang), 0, sin(ang), 0, 1, 0, -sin(ang), 0, cos(ang)];
然后我们可以通过y旋转在z旋转中旋转每个轴。
// rotate each rotation axis by the second rotation axis.
xAxisAB.x = xAxisA.x * xAxisB.x + xAxisA.y * yAxisB.x + xAxisA.z * zAxisB.x;
xAxisAB.y = xAxisA.x * xAxisB.y + xAxisA.y * yAxisB.y + xAxisA.z * zAxisB.y;
xAxisAB.z = xAxisA.x * xAxisB.z + xAxisA.y * yAxisB.z + xAxisA.z * zAxisB.z;
yAxisAB.x = yAxisA.x * xAxisB.x + yAxisA.y * yAxisB.x + yAxisA.z * zAxisB.x;
yAxisAB.y = yAxisA.x * xAxisB.y + yAxisA.y * yAxisB.y + yAxisA.z * zAxisB.y;
yAxisAB.z = yAxisA.x * xAxisB.z + yAxisA.y * yAxisB.z + yAxisA.z * zAxisB.z;
zAxisAB.x = zAxisA.x * xAxisB.x + zAxisA.y * yAxisB.x + zAxisA.z * zAxisB.x;
zAxisAB.y = zAxisA.x * xAxisB.y + zAxisA.y * yAxisB.y + zAxisA.z * zAxisB.y;
zAxisAB.z = zAxisA.x * xAxisB.z + zAxisA.y * yAxisB.z + zAxisA.z * zAxisB.z;
或短手
rotationAB = rotationZ * rotationY;
或
AB = A * B;
结果矩阵AB
是z旋转和y旋转的组合旋转。你可以继续前进,围绕x
// rotate about the x Axis
xAxisC = [1, 0 , 0 ]; // 1 unit long
yAxisC = [0, cos(ang) , sin(ang)]; // 1 unit long
zAxisC = [0, -sin(ang), cos(ang)]; // 1 unit long
C = rotationX =[1, 0, 0, 0, cos(ang), sin(ang), 0, -sin(ang), cos(ang)];
最后一轮是
ABC = A * B * C
但请记住,顺序很重要。
A * B * C != C * B * A; // order of multiplication is important.
以上是几周内计算机科学一年级课程所涵盖的内容,但它会假设您对矢量数学有很好的理解。编写代码可能会变得非常重复,并且由于问题的性质,很难阅读和发现错误。
我始终认为最好的学习方法是编写自己的库,但在这种情况下,库是一个很好的起点,因为这个主题比旋转,缩放和翻译更深入。
有数百个矩阵/矢量数学库,一个很好的起点是github
在数学中,轴为x轴,î
(发音为i hat),y轴为ĵ
(j hat)。每个轴由单位向量î = [1,0]
和ĵ = [0,1]
定义(对于3D,我们使用三个3D向量î = [1,0,0]
,ĵ = [0,1,0]
和k hat = [0,0,1]
抱歉我找不到k字符集中的帽子)
矢量是一组表示方向和距离的数字。在数学中,向量是一个矩阵。例如,v = [1,0]
在代码中作为结构/对象/类v = { x : 1, y : 0}
向量也可以描述为距离和方向,例如东南10公里。很容易从一种类型转换为另一种类型(见下文)
单位向量是1个单位长的向量。 (1,0)是单位矢量,其长度为1个单位长。您可以将单位向量相乘以找到原点的n个单位。
n = 5;
axis = { x : 1, y : 0 };
point.x = axis.x * n; // 5 * 1 = 5
point.y = axis.y * n; // 5 * 0 = 0
您可以使用毕达哥拉斯来获得向量的长度。例如,向量{x : 3, y : 4}
的长度等于sqrt( 3 * 3 + 4 * 4 ) = sqrt( 9 + 16 ) = sqrt( 25 ) = 5
五个单位长,显然不是单位向量
归一化矢量的过程将矢量转换为单位矢量。它是通过将矢量的分量除以矢量长度来完成的。
vec = { x : 3, y : 4 };
length = sqrt( vec.x * vec.x + vec.y * vec.y ); // length = 5
// nVec is the normalised vector vec
nVec.x = vec.x / length; // 3/5 = 0.6;
nVec.y = vec.y / length; // 4/5 = 0.8;
要在特定方向创建单位向量,我们使用一点trig
angle = 90; // in deg (normally this is radians)
v90.x = cos(angle);
v90.y = sin(angle);
答案 1 :(得分:0)
你的方法是正确的。它可以应用于不同的操作,如旋转和缩放。如果您仅限于具有几何函数的编程开发环境,该几何函数的中心仅限于原点(0,0,0),则可以应用步骤来执行相对于中心点的操作:
1) Apply a vector to the point to rotate that would move the center point to the origin by:
a) Determine the vector offset that would move the center point (for example point 3,2,1) to the origin.
In this case, it is vector <-3,-2,-1>.
b) Then apply it to the point (in this case 1,1,1 => [1 - 3,1 - 2,1 - 1];
2) Apply the operation (in this case a rotation), and probably a transformation matrix;
3) Apply the reverse of the vector in "1a" to the point determined in step "b" above.
第一个答案的类似解决方案: Rotation of Point in 3D Space