Dan*_*oss 7 algorithm math 3d linear-algebra three.js
我试图在3D中绘制由两个平面的交叉点形成的线,但是我无法理解数学,这已经在这里和这里解释过了.
我试图弄清楚自己,但是我得到解决方案的最接近的是一个指向与交叉线相同方向的矢量,通过使用平面法线的叉积.我不知道如何在交叉线上找到一个点,任何一点都可以.我认为这种方法是死路一条.以下是此尝试的屏幕截图:
我试图使用这个问题中提到的解决方案,但它与原始解释有一个死链接,并且该等式对我不起作用(它有不平衡的括号,我试图在下面纠正).
var planeA = new THREE.Plane((new THREE.Vector3(0, 0, 1)).normalize(), 100);
var planeB = new THREE.Plane((new THREE.Vector3(1, 1, 1)).normalize(), -100);
var x1 = planeA.normal.x,
y1 = planeA.normal.y,
z1 = planeA.normal.z,
d1 = planeA.constant;
var x2 = planeB.normal.x,
y2 = planeB.normal.y,
z2 = planeB.normal.z,
d2 = planeB.constant;
var point1 = new THREE.Vector3();
point1.x = 0;
point1.z = (y2 / y1) * (d1 - d2) / (z2 - z1 * y2 / y1);
point1.y = (-z1 * point1.z - d1) / y1;
var point2 = new THREE.Vector3();
point2.x = 1;
point2.z = (y2 / y1) * (x1 * point2.x + d1) - (x2 * point2.x - d2) / (z2 - z1 * y2 / y1);
point2.y = (-z1 * point2.z - x1 * point2.x - d1) / y1;
console.log(point1, point2);
Run Code Online (Sandbox Code Playgroud)
输出:
THREE.Vector3 {x: -1, y: NaN, z: NaN, …}
THREE.Vector3 {x: 1, y: Infinity, z: -Infinity, …}
Run Code Online (Sandbox Code Playgroud)
预期产量:
如果有人能指出我应该如何工作的一个很好的解释,或者一个平面交叉算法的例子,我将不胜感激.
小智 6
以下是http://geomalgorithms.com/a05-_intersect-1.html中描述的平面交叉解决方案的实现.基本上,您首先使用平面法线的叉积来找到两个平面中线的方向.其次,你在平面的隐式方程上使用一些代数(P.n + d = 0,其中P是平面上的某个点,n是法线,d是平面常数)来求解一个点在平面的交叉点以及x = 0,y = 0或z = 0平面之一.然后解决方案是由点和矢量描述的线.我使用的是three.js版本79
/*
Algorithm taken from http://geomalgorithms.com/a05-_intersect-1.html. See the
section 'Intersection of 2 Planes' and specifically the subsection
(A) Direct Linear Equation
*/
function intersectPlanes(p1, p2) {
// the cross product gives us the direction of the line at the intersection
// of the two planes, and gives us an easy way to check if the two planes
// are parallel - the cross product will have zero magnitude
var direction = new THREE.Vector3().crossVectors(p1.normal, p2.normal)
var magnitude = direction.distanceTo(new THREE.Vector3(0, 0, 0))
if (magnitude === 0) {
return null
}
// now find a point on the intersection. We use the 'Direct Linear Equation'
// method described in the linked page, and we choose which coordinate
// to set as zero by seeing which has the largest absolute value in the
// directional vector
var X = Math.abs(direction.x)
var Y = Math.abs(direction.y)
var Z = Math.abs(direction.z)
var point
if (Z >= X && Z >= Y) {
point = solveIntersectingPoint('z', 'x', 'y', p1, p2)
} else if (Y >= Z && Y >= X){
point = solveIntersectingPoint('y', 'z', 'x', p1, p2)
} else {
point = solveIntersectingPoint('x', 'y', 'z', p1, p2)
}
return [point, direction]
}
/*
This method helps finding a point on the intersection between two planes.
Depending on the orientation of the planes, the problem could solve for the
zero point on either the x, y or z axis
*/
function solveIntersectingPoint(zeroCoord, A, B, p1, p2){
var a1 = p1.normal[A]
var b1 = p1.normal[B]
var d1 = p1.constant
var a2 = p2.normal[A]
var b2 = p2.normal[B]
var d2 = p2.constant
var A0 = ((b2 * d1) - (b1 * d2)) / ((a1 * b2 - a2 * b1))
var B0 = ((a1 * d2) - (a2 * d1)) / ((a1 * b2 - a2 * b1))
var point = new THREE.Vector3()
point[zeroCoord] = 0
point[A] = A0
point[B] = B0
return point
}
var planeA = new THREE.Plane((new THREE.Vector3(0, 0, 1)).normalize(), 100)
var planeB = new THREE.Plane((new THREE.Vector3(1, 1, 1)).normalize(), -100)
var [point, direction] = intersectPlanes(planeA, planeB)
Run Code Online (Sandbox Code Playgroud)
当我遇到这样的问题时,我通常让符号代数包(本例中为 Mathematica)来处理它。打字后
In[1]:= n1={x1,y1,z1};n2={x2,y2,z2};p={x,y,z};
In[2]:= Solve[n1.p==d1&&n2.p==d2,p]
Run Code Online (Sandbox Code Playgroud)
简化并代入 x=0 和 x=1,我得到
d2 z1 - d1 z2 d2 y1 - d1 y2
Out[5]= {{{y -> -------------, z -> ----------------}},
y2 z1 - y1 z2 -(y2 z1) + y1 z2
d2 z1 - x2 z1 - d1 z2 + x1 z2
> {{y -> -----------------------------,
y2 z1 - y1 z2
d2 y1 - x2 y1 + (-d1 + x1) y2
> z -> -----------------------------}}}
-(y2 z1) + y1 z2
Run Code Online (Sandbox Code Playgroud)
让 Three.js 为您解决这个问题很容易。
如果你用矩阵表示法来表达你的问题
m * x = v
Run Code Online (Sandbox Code Playgroud)
那么 x 的解就是
x = inverse( m ) * v
Run Code Online (Sandbox Code Playgroud)
我们将使用 4x4 矩阵作为 m,因为 Three.js 有一个inverse()用于该类的方法Matrix4。
var x1 = 0,
y1 = 0,
z1 = 1,
d1 = 100;
var x2 = 1,
y2 = 1,
z2 = 1,
d2 = -100;
var c = 0; // the desired value for the x-coordinate
var v = new THREE.Vector4( d1, d2, c, 1 );
var m = new THREE.Matrix4( x1, y1, z1, 0,
x2, y2, z2, 0,
1, 0, 0, 0,
0, 0, 0, 1
);
var minv = new THREE.Matrix4().getInverse( m );
v.applyMatrix4( minv );
console.log( v );
Run Code Online (Sandbox Code Playgroud)
根据需要,v 的 x 分量将等于 c,y 和 z 分量将包含您要查找的值。w 分量是不相关的。
现在,对 c 的下一个值重复,c = 1。
三.js r.58