0

Hi i'm starting to work with webGL using Three.js and I need to detect if a click on a sphere is within a certain section of it's surface.

Currently i can detect if the sphere was clicked and get the coords of the point clicked. Now what i need is to detect if that click was in a certain region of that sphere, based on a array of 3D points from that sphere (another suggestion is ok).

The sphere is in the center point, and the point is garrantied to be on the surface of the sphere. Now i need to calculate if it's just within a section section. Any suggestions? My problem seams to be more mathematical. Also i prefere a generic way to do this because the sections may be just a triangle or may be more complex figures.

Hugo Alves
  • 1,555
  • 2
  • 18
  • 41
  • Possibly related: [How do I check if a longitude/latitude point is within a range of coordinates?](http://stackoverflow.com/questions/11510326/how-do-i-check-if-a-longitude-latitude-point-is-within-a-range-of-coordinates/11510666). Only in that question, the OP had lattitude/longitude rather than points in three dimensional space. But converting between the two is not too difficult IIRC. – Kevin Dec 17 '12 at 16:29
  • 1
    I expect the answer to this will depend somewhat on how you define your sections, which you haven't described. – Alnitak Dec 17 '12 at 16:31
  • I'm sorry. My sections are described so far with a group of points that are on the surface of the sphere making a random shape. – Hugo Alves Dec 17 '12 at 17:16
  • I assume the group is ordered (otherwise the problem can't be solved). Does it have *sense*? That is, can we count on it to be counter-clockwise (by mathematical convention)? – Beta Dec 17 '12 at 17:36
  • yes they are. i wouldn't make sense of it if they was random points – Hugo Alves Dec 17 '12 at 17:48

4 Answers4

0

My first idea was to project your 3D points on to the screen coordinates (ie from world coordinates to view coordinates, exactly as in drawing the shape on the screen). This gives you the visual region that corresponds to the surface-of-interest. This would be a simple 3D-to-2D projection using your view, and then you can see if the click location lies in the 2D polygon.

Then I realised a problem with this approach, which is that it won't work if your region-of-interest goes around onto the back-surface of the sphere.

If this is a problem, you will need to construct the projection of your mouse click along the camera direction. If you are using an isometric camera, this should be possible...

Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58
  • Back surface problem is easily fixed. Do a back face culling of the points. Where culled skip points accordingly. Then the 2d test is easy, shoot a 2d ray if your ray crosses the polygon a odd number of times your inside. This may be inefficient tough. – joojaa Dec 17 '12 at 21:19
0

Draw a (great-circle) ray from the point. Find the nearest intersection with a segment of the curve. The point is inside the curve if and only if the segment crosses the ray from right to left.

Beta
  • 96,650
  • 16
  • 149
  • 150
  • i don't understand the idea. what do you mean with draw a great-circle? – Hugo Alves Dec 17 '12 at 17:56
  • @HugoAlves, draw an arc from the point P to the point on the opposite side of the sphere. Imagine standing on the point, then walking until you hit the fence (it doesn't even have to be along a great circle). If the fence is running from right to left, you're inside it. – Beta Dec 17 '12 at 17:58
0

One solution is to render a pseudocolor image where your areas each have a color of their own to a texture. Then sample the image, use the pesudocolor as array index. * for parctical reason the encoding should spread values around a bit.

joojaa
  • 4,354
  • 1
  • 27
  • 45
0

I've ended using a different method then the suggestions.

I'm using matrix determinants where: (T1, T2, T3) are points that form a triangle and X is the point i want to know if it's inside this triangle, then i simple calculate 3 determinants where:

d1 = det([T1 T2 X])
d2 = det([T1 X T3])
d3 = det([T1 T2 X])

If all determinants are the same sign, then the point is inside the triangle. Now i form a list of triangles based on the selection area and check if the point is inside one of those triangles.

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;
}

The function pointInTriangle(x,t1,t2,t3) does the determinant verification.

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;
};
Hugo Alves
  • 1,555
  • 2
  • 18
  • 41