Question

I'm using WebGL globe from http://workshop.chromeexperiments.com/globe/. If any point of the globe is clicked, I need to get the longitude and latitude of that point. These parameters are to be passed to the Google Maps for 2D map.

How can I get the long. and lat. from the webgl globe?

Through this function I'm getting the double clicked point, and through this point I'm finding the long. and lat. But the results are not correct. It seems that the clicked point is not determined properly.

function onDoubleClick(event) {
        event.preventDefault();

        var vector = new THREE.Vector3(
            ( event.clientX / window.innerWidth ) * 2 - 1,
            -( event.clientY / window.innerHeight ) * 2 + 1,
            0.5
        );

        projector.unprojectVector(vector, camera);

        var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());

        var intersects = ray.intersectObject(globe3d);

        if (intersects.length > 0) {

            object = intersects[ 0 ];

            console.log(object);
            r = object.object.boundRadius;
            x = object.point.x;
            y = object.point.y;
            z = object.point.z;
            console.log(Math.sqrt(x * x + y * y + z * z));

            lat = 90 - (Math.acos(y / r)) * 180 / Math.PI;
            lon = ((270 + (Math.atan2(x, z)) * 180 / Math.PI) % 360) - 180;
            
            console.log(lat);
            console.log(lon);

        }
    }

Get the WebGL Globe here https://github.com/dataarts/webgl-globe/archive/master.zip You can open it directly on Mozilla, if you open it in Chrome it works with earth surface image lack because of Cross-Origin Resource Sharing policy. It needs to be put in a virtual host.

Was it helpful?

Solution

Try to use the function in this way

    function onDoubleClick(event) {
        event.preventDefault();

        var canvas = renderer.domElement;
        var vector = new THREE.Vector3( ( (event.offsetX) / canvas.width ) * 2 - 1, - ( (event.offsetY) / canvas.height) * 2 + 1,
0.5 );

        projector.unprojectVector( vector, camera );

        var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());

        var intersects = ray.intersectObject(globe3d);

        if (intersects.length > 0) {

            object = intersects[0];

            r = object.object.boundRadius;
            x = object.point.x;
            y = object.point.y;
            z = object.point.z;

            lat = 90 - (Math.acos(y / r)) * 180 / Math.PI;
            lon = ((270 + (Math.atan2(x, z)) * 180 / Math.PI) % 360) - 180;

            lat = Math.round(lat * 100000) / 100000;
            lon = Math.round(lon * 100000) / 100000;
            window.location.href = 'gmaps?lat='+lat+'&lon='+lon;

        }
    }

OTHER TIPS

I used the code you share with a little correction and it works great.

The way to let it work correctly is to understand exactly what you pass to the new THREE.Vector3.

This function need three parameters (x, y, z)

z in our/your case is sculpted as 0.5 and it's ok

x and y must be a number among -1 and 1, so, to obtain this values you need to catch the click coordinates on your canvas and then, with this formula, reduce them to a value in this range (-1...0...1);

var vectorX = ((p_coord_X / canvas.width ) * 2 - 1);
var vectorY = -((p_coord_Y / canvas.height ) * 2 - 1);

where p_coord_X and p_coord_Y are the coordinates of the click (referred to the left top corner of your canvas) and canvas is the canvas area where lives your webgl globe.

The problem is how to get the click X and Y coordinates in pixel, because it depends by how your canvas is placed in your HTML enviroment. For my cases the solution over proposed where not suitable cause i returned always false results; so i build a solution to get extacly the x and y coordinates of my canvas area as i clicked on it (i had for my case too to insert a scrollY page correction).

Now imagine to devide in 4 square your canvas area, a click in the NW quadrant will return for example a -0.8, -05 x and y values, a click in SE i.e. a couple of 0.6, 0.4 values.

The ray.intersectObject() function that follows uses then our click-vector-converted data to understand if our click intersects the globe, if it matches, return correctly the coordinates lat and lon.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top