创建一个只有 2 个已知点的立方体
Creating a cube with only 2 known points
我目前正在制作一个程序,根据用户给出的 2 分生成立方体。我知道立方体可以仅基于 2 个点以无限多种方式旋转。但是,例如 geogebra 仅基于 2 个点生成一个立方体,我想复制它。我对矢量的了解非常有限,但我猜我需要从 2 个点与这 3 个矢量总共形成的矢量创建 2 个法线我能够创建立方体。
我的问题是我不知道如何创建 2 条相互对齐的法线,使我可以使用它们创建立方体,因为 3 中的向量有无限多条法线维space。我的猜测是我需要在计算法线时丢弃一个轴。但我不知道该怎么做。
编辑。
我的代码只是计算每个角的点,立方体的面积和中心点,没有图形只是将每个点的x,y,z保存到立方体class。我只需要我需要添加到我的代码中的数学来计算每个角点。
假设您的 2 个点定义立方体的内部对角线 u
(蓝色)。
从这2点我们已经知道立方体的2个顶点,它们的平均值是立方体的中心p
。
现在我们需要 select 平面,其中两条 u,v
对角线将使用任何不(反)平行于对角线 u
的方向并将其用作平面的法线n
(绿色)。在这种情况下,我通常使用 (1.0,0.0,0.0)
或 (0.0,1.0,0.0)
取决于第一个是否平行(可以用点积来决定)。您还可以使用相机向前和向右的方向,这样无论相机方向如何,立方体都以相同的方式对齐。
现在为了获得红色对角线,我们只需将蓝色对角线围绕对齐向量 n
和中心 p
.
旋转 ~70.529deg = 2*atan(1/sqrt(2))
最后,为了获得最后缺失的 2 条对角线(代码中的 U,V
),我们只需将前两条 (u,v
) 围绕 n'
旋转 90deg
并居中 p
。 n'
只是 u
和 -v
中间的方向,所以 n'=u-v
.
这里是使用我的 GLSL style vector math 的小 C++ 代码(你可以使用任何其他类似 GLM 的东西,甚至你只需要 v+v,v-v,v*c,v/c,dot,cross,length
)还要注意角度 a0,a1
以弧度表示:
//---------------------------------------------------------------------------
vec3 A=vec3(-0.7,-0.8,+0.5), // input points
B=vec3(+0.5,+0.6,-0.4);
vec3 pnt[8]; // output cube points
//---------------------------------------------------------------------------
// return rotated p around axis (center is (0,0,0))
vec3 rotate(float ang,vec3 axis,vec3 p)
{
float c=cos(ang),s=sin(ang);// precompute goniometrics
vec3 u,v,w; // bazis vectors
float x,y,z,xx,yy;
w=normalize(axis); // w is rotation axis
u=vec3(1.0,0.0,0.0); // u = any unit align vector not parallel to w
if (fabs(dot(u,w))>0.75) u=vec3(0.0,1.0,0.0);
u=cross(u,w); // make u paralel to w and align vector
v=cross(u,w); // make v paralel to u and w
// convert to basis vectors local coordinates
xx=dot(p,u);
yy=dot(p,v);
z =dot(p,w);
// rotate XY plane
x=xx*c-yy*s;
y=xx*s+yy*c;
// convert back to global coordinates
p=(x*u)+(y*v)+(z*w);
return p;
}
//---------------------------------------------------------------------------
// compute pnt[] from A,B
void diagonal2cube()
{
const float a0=1.230959417340774682134929178248; // 70.5288 deg
const float a1=1.5707963267948966192313216916398; // 90.0000 deg
float a;
vec3 p,u,v,U,V,n;
p=0.5*(A+B); // center of cube
u=A-p; // half diagonal from center to pnt[0]
a=length(u); // half size of cube's diagonal
u=normalize(u); // normalize u
n=vec3(1.0,0.0,0.0);// n = any unit align vector not parallel to u
if (fabs(dot(u,n))>0.75) n=vec3(0.0,1.0,0.0);
n=cross(u,n); // make n paralel to u and align vector
u*=a; // rescale u back to original size
v=rotate(a0,n,u); // v is u rotated by 70.5288 deg around n
n=u-v; // n is axis perpendicular to n and in the same plane as u,v
U=rotate(a1,n,u); // U is u rotated by 90.0 deg around n
V=rotate(a1,n,v); // V is v rotated by 90.0 deg around n
pnt[0]=p+u; // construct the cube vertexes
pnt[6]=p-u;
pnt[1]=p+v;
pnt[7]=p-v;
pnt[3]=p+U;
pnt[5]=p-U;
pnt[2]=p+V;
pnt[4]=p-V;
}
//---------------------------------------------------------------------------
此处预览使用 OpenGL 生成的立方体:
我目前正在制作一个程序,根据用户给出的 2 分生成立方体。我知道立方体可以仅基于 2 个点以无限多种方式旋转。但是,例如 geogebra 仅基于 2 个点生成一个立方体,我想复制它。我对矢量的了解非常有限,但我猜我需要从 2 个点与这 3 个矢量总共形成的矢量创建 2 个法线我能够创建立方体。
我的问题是我不知道如何创建 2 条相互对齐的法线,使我可以使用它们创建立方体,因为 3 中的向量有无限多条法线维space。我的猜测是我需要在计算法线时丢弃一个轴。但我不知道该怎么做。
编辑。 我的代码只是计算每个角的点,立方体的面积和中心点,没有图形只是将每个点的x,y,z保存到立方体class。我只需要我需要添加到我的代码中的数学来计算每个角点。
假设您的 2 个点定义立方体的内部对角线 u
(蓝色)。
从这2点我们已经知道立方体的2个顶点,它们的平均值是立方体的中心p
。
现在我们需要 select 平面,其中两条 u,v
对角线将使用任何不(反)平行于对角线 u
的方向并将其用作平面的法线n
(绿色)。在这种情况下,我通常使用 (1.0,0.0,0.0)
或 (0.0,1.0,0.0)
取决于第一个是否平行(可以用点积来决定)。您还可以使用相机向前和向右的方向,这样无论相机方向如何,立方体都以相同的方式对齐。
现在为了获得红色对角线,我们只需将蓝色对角线围绕对齐向量 n
和中心 p
.
~70.529deg = 2*atan(1/sqrt(2))
最后,为了获得最后缺失的 2 条对角线(代码中的 U,V
),我们只需将前两条 (u,v
) 围绕 n'
旋转 90deg
并居中 p
。 n'
只是 u
和 -v
中间的方向,所以 n'=u-v
.
这里是使用我的 GLSL style vector math 的小 C++ 代码(你可以使用任何其他类似 GLM 的东西,甚至你只需要 v+v,v-v,v*c,v/c,dot,cross,length
)还要注意角度 a0,a1
以弧度表示:
//---------------------------------------------------------------------------
vec3 A=vec3(-0.7,-0.8,+0.5), // input points
B=vec3(+0.5,+0.6,-0.4);
vec3 pnt[8]; // output cube points
//---------------------------------------------------------------------------
// return rotated p around axis (center is (0,0,0))
vec3 rotate(float ang,vec3 axis,vec3 p)
{
float c=cos(ang),s=sin(ang);// precompute goniometrics
vec3 u,v,w; // bazis vectors
float x,y,z,xx,yy;
w=normalize(axis); // w is rotation axis
u=vec3(1.0,0.0,0.0); // u = any unit align vector not parallel to w
if (fabs(dot(u,w))>0.75) u=vec3(0.0,1.0,0.0);
u=cross(u,w); // make u paralel to w and align vector
v=cross(u,w); // make v paralel to u and w
// convert to basis vectors local coordinates
xx=dot(p,u);
yy=dot(p,v);
z =dot(p,w);
// rotate XY plane
x=xx*c-yy*s;
y=xx*s+yy*c;
// convert back to global coordinates
p=(x*u)+(y*v)+(z*w);
return p;
}
//---------------------------------------------------------------------------
// compute pnt[] from A,B
void diagonal2cube()
{
const float a0=1.230959417340774682134929178248; // 70.5288 deg
const float a1=1.5707963267948966192313216916398; // 90.0000 deg
float a;
vec3 p,u,v,U,V,n;
p=0.5*(A+B); // center of cube
u=A-p; // half diagonal from center to pnt[0]
a=length(u); // half size of cube's diagonal
u=normalize(u); // normalize u
n=vec3(1.0,0.0,0.0);// n = any unit align vector not parallel to u
if (fabs(dot(u,n))>0.75) n=vec3(0.0,1.0,0.0);
n=cross(u,n); // make n paralel to u and align vector
u*=a; // rescale u back to original size
v=rotate(a0,n,u); // v is u rotated by 70.5288 deg around n
n=u-v; // n is axis perpendicular to n and in the same plane as u,v
U=rotate(a1,n,u); // U is u rotated by 90.0 deg around n
V=rotate(a1,n,v); // V is v rotated by 90.0 deg around n
pnt[0]=p+u; // construct the cube vertexes
pnt[6]=p-u;
pnt[1]=p+v;
pnt[7]=p-v;
pnt[3]=p+U;
pnt[5]=p-U;
pnt[2]=p+V;
pnt[4]=p-V;
}
//---------------------------------------------------------------------------
此处预览使用 OpenGL 生成的立方体: