Javascript 确定点是否在球体曲面的某个部分内

Javascript 确定点是否在球体曲面的某个部分内,javascript,math,3d,three.js,Javascript,Math,3d,Three.js,大家好,我开始使用Three.js使用webGL,我需要检测球体上的点击是否在其表面的特定部分内 目前,我可以检测球体是否被点击,并获得点击点的坐标。现在我需要的是,根据球体的3D点阵列,检测点击是否在球体的某个区域(另一个建议是可以的) 球体位于中心点,该点被固定在球体的表面上。现在我需要计算它是否在一个区域内。有什么建议吗?我的问题需要更多的数学知识。 此外,我更喜欢一种通用的方法,因为剖面可能只是一个三角形,也可能是更复杂的图形。我的第一个想法是将3D点投影到屏幕坐标上(即从世界坐标到视图

大家好,我开始使用Three.js使用webGL,我需要检测球体上的点击是否在其表面的特定部分内

目前,我可以检测球体是否被点击,并获得点击点的坐标。现在我需要的是,根据球体的3D点阵列,检测点击是否在球体的某个区域(另一个建议是可以的)

球体位于中心点,该点被固定在球体的表面上。现在我需要计算它是否在一个区域内。有什么建议吗?我的问题需要更多的数学知识。
此外,我更喜欢一种通用的方法,因为剖面可能只是一个三角形,也可能是更复杂的图形。

我的第一个想法是将3D点投影到屏幕坐标上(即从世界坐标到视图坐标,与在屏幕上绘制形状完全相同)。这将为您提供与感兴趣的曲面相对应的可视区域。这将是一个使用视图的简单三维到二维投影,然后可以查看单击位置是否位于二维多边形中

然后我意识到这种方法有一个问题,那就是如果你感兴趣的区域转到球体的后表面上,它就不起作用了


如果这是一个问题,则需要沿摄影机方向构建鼠标单击的投影。如果您使用的是等轴测相机,这应该是可能的…

从该点绘制一条(大圆)光线。找到与曲线段最近的交点。当且仅当线段从右到左穿过光线时,点位于曲线内部。

一种解决方案是渲染伪彩色图像,其中每个区域都有自己的纹理颜色。然后对图像进行采样,使用伪彩色作为数组索引。*出于某些原因,编码应该将值分散一点。

我结束时使用了不同的方法,然后是建议

我使用矩阵行列式,其中:(T1,T2,T3)是形成三角形的点,X是我想知道它是否在这个三角形内的点,然后我简单地计算3个行列式,其中:

d1 = det([T1 T2 X])
d2 = det([T1 X T3])
d3 = det([T1 T2 X])
如果所有行列式都是同一个符号,则该点位于三角形内。 现在,我根据选择区域形成一个三角形列表,并检查该点是否在其中一个三角形内

this.Detector.triangleDetector = function(position, triangleArray){
    for(var idxString in triangleArray){
        var index = parseInt(idxString);
        if(this.pointInTriangle(position, triangleArray[index].coords1, triangleArray[index].coords2, triangleArray[index].coords3))
            return true;
    }
    return false;
}
函数
pointinttriangle(x,t1,t2,t3)
执行行列式验证

this.Detector.pointInTriangle = function(x,T1,T2,T3){
    var array1 = [coord1.x ,coord1.y ,coord1.z];
    var array2 = [coord2.x ,coord2.y ,coord2.z];
    var array3 = [coord3.x ,coord3.y ,coord3.z];
    var zero = 0;
    var A = [[zero,zero,zero],[zero,zero,zero],[zero,zero,zero]];
    var d1,d2,d3;
    A[0][0] = position.x;
    A[0][1] = position.y;
    A[0][2] = position.z;
    A[1][0] = array2[0];
    A[1][1] = array2[1];
    A[1][2] = array2[2];
    A[2][0] = array3[0];
    A[2][1] = array3[1];
    A[2][2] = array3[2];
    d1 = MyMath.determinant(A,3);

    A[0][0] = array1[0];
    A[0][1] = array1[1];
    A[0][2] = array1[2];
    A[1][0] = position.x;
    A[1][1] = position.y;
    A[1][2] = position.z;
    d2 = MyMath.determinant(A,3);

    A[1][0] = array2[0];
    A[1][1] = array2[1];
    A[1][2] = array2[2];
    A[2][0] = position.x;
    A[2][1] = position.y;
    A[2][2] = position.z;
    d3 = MyMath.determinant(A,3);

    if((d1>=0 && d2 >=0 && d3>=0) || (d1<=0 && d2 <=0 && d3<=0)){
        return true;
    }
    return false;
};
this.Detector.pointInTriangle=函数(x,T1,T2,T3){
var array1=[coord1.x,coord1.y,coord1.z];
var array2=[coord2.x,coord2.y,coord2.z];
var array3=[coord3.x,coord3.y,coord3.z];
var 0=0;
var A=[[0,0,0],[0,0,0],[0,0,0];
变量d1、d2、d3;
A[0][0]=位置.x;
A[0][1]=位置y;
A[0][2]=位置z;
A[1][0]=阵列2[0];
A[1][1]=阵列2[1];
A[1][2]=阵列2[2];
A[2][0]=阵列3[0];
A[2][1]=阵列3[1];
A[2][2]=阵列3[2];
d1=MyMath.行列式(A,3);
A[0][0]=阵列1[0];
A[0][1]=阵列1[1];
A[0][2]=阵列1[2];
A[1][0]=位置.x;
A[1][1]=位置y;
A[1][2]=位置z;
d2=MyMath.行列式(A,3);
A[1][0]=阵列2[0];
A[1][1]=阵列2[1];
A[1][2]=阵列2[2];
A[2][0]=位置.x;
A[2][1]=位置y;
A[2][2]=位置z;
d3=我的数学行列式(A,3);

如果((d1>=0&&d2>=0&&d3>=0)|(d1可能相关:。仅在这个问题中,OP具有格/经度,而不是三维空间中的点。但是转换这两个空间并不太困难IIRC。我希望这一点的答案在一定程度上取决于您如何定义您尚未描述的节段。对不起。我的部分目前用o组描述在球面上形成随机形状的f点。我假设组是有序的(否则问题就无法解决)。这有意义吗?也就是说,我们可以指望它是逆时针的(根据数学惯例)?是的。如果它们是随机点,我就搞不懂了。我不明白这个想法。画一个大圆是什么意思?@HugoAlves,从点P到球体另一侧的点画一条弧。想象一下站在点上,然后一直走到撞到栅栏为止(它甚至不必沿着大圆)。如果围栏是从右向左运行的,你就在里面。后表面问题很容易解决。对点进行后表面剔除。在剔除的跳过点处进行相应的剔除。然后2d测试很容易,如果你的光线穿过多边形奇数倍于你的内部,则拍摄2d光线。这可能是低效的。