对于任何数学/3d 几何爱好者来说,这都是一件大事。先感谢您。
概述
我有一个通过在空间中扭曲样条曲线周围挤出面而创建的图形。我试图在曲线的给定段上沿样条路径放置一个“环”(环),以便它与样条“对齐”。我的意思是圆环的宽度平行于给定挤压段的样条路径,它的高度垂直于选定的面(见下图)。
我知道的数据:
我得到了人物的一张脸。从中我还可以收集该面的质心(中心点)、构成它的顶点、周围的面以及面的法线向量。
当前(非工作)解决方案结果:
我可以正确地围绕被点击的脸的质心创建一个圆环。但是,它不能正确旋转以与面部“对齐”。看看他们在下面看起来有点“不正常”。
这是一张带有周围材料的图片:
这是一张线框模式下的图片。您可以非常清楚地看到挤压段。
当前(非工作)方法:
我正在尝试做两个计算。首先,我正在计算两个平面之间的角度(选定的面和原点的水平面)。其次,我正在计算原点处面部与垂直平面之间的角度。使用这两个角度,然后我将进行两次旋转 - 在圆环上进行 X 和 Y 旋转,以达到我希望的正确方向。它以可变的量旋转圆环,但不在我想要的位置。
公式:
在执行上述操作时,我使用以下方法使用它们的法向量计算两个平面之间的角度:
法线向量 1 和法线向量 2 的点积 = 向量 1 的大小 * 向量 2 的大小 * Cos (theta)
或者:
(n1)(n2) = || n1 || * || n2 || * cos (θ)
或者:
角度 = ArcCos { ( n1 * n2 ) / ( || n1 || * || n2 || ) }
要确定向量的大小,公式为:
分量平方和的平方根。
或者:
平方 { n1.x^2 + n1.y^2 + n1.z^2 }
此外,我将以下内容用于“原点”平面的法线向量:
水平面的法向量:(1, 0, 0)
垂直平面的法向量:(0, 1, 0)
我已经多次考虑过上述法线向量......我认为(?)他们是对的?
当前实施:
下面是我目前用来实现它的代码。任何想法将不胜感激。我有一种下沉的感觉,我在尝试计算平面之间的角度时采取了错误的方法。任何建议/想法/建议将不胜感激。非常感谢您提前提出任何建议。
计算角度的函数:
this.toRadians = function (face, isX)
{
//Normal of the face
var n1 = face.normal;
//Normal of the vertical plane
if (isX)
var n2 = new THREE.Vector3(1, 0, 0); // Vector normal for vertical plane. Use for Y rotation.
else
var n2 = new THREE.Vector3(0, 1, 0); // Vector normal for horizontal plane. Use for X rotation.
//Equation to find the cosin of the angle. (n1)(n2) = ||n1|| * ||n2|| (cos theta)
//Find the dot product of n1 and n2.
var dotProduct = (n1.x * n2.x) + (n1.y * n2.y) + (n1.z * n2.z);
// Calculate the magnitude of each vector
var mag1 = Math.sqrt (Math.pow(n1.x, 2) + Math.pow(n1.y, 2) + Math.pow(n1.z, 2));
var mag2 = Math.sqrt (Math.pow(n2.x, 2) + Math.pow(n2.y, 2) + Math.pow(n2.z, 2));
//Calculate the angle of the two planes. Returns value in radians.
var a = (dotProduct)/(mag1 * mag2);
var result = Math.acos(a);
return result;
}
创建和旋转圆环的函数:
this.createTorus = function (tubeMeshParams)
{
var torus = new THREE.TorusGeometry(5, 1.5, segments/10, 50);
fIndex = this.calculateFaceIndex();
//run the equation twice to calculate the angles
var xRadian = this.toRadians(geometry.faces[fIndex], false);
var yRadian = this.toRadians(geometry.faces[fIndex], true);
//Rotate the Torus
torus.applyMatrix(new THREE.Matrix4().makeRotationX(xRadian));
torus.applyMatrix(new THREE.Matrix4().makeRotationY(yRadian));
torusLoop = new THREE.Mesh(torus, this.m);
torusLoop.scale.x = torusLoop.scale.y = torusLoop.scale.z = tubeMeshParams['Scale'];
//Create the torus around the centroid
posx = geometry.faces[fIndex].centroid.x;
posy = geometry.faces[fIndex].centroid.y;
posz = geometry.faces[fIndex].centroid.z;
torusLoop.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(posx, posy, posz));
torusLoop.geometry.computeCentroids();
torusLoop.geometry.computeFaceNormals();
torusLoop.geometry.computeVertexNormals();
return torusLoop;
}