itzikpel
itzikpel

Reputation: 163

Convert mouse click to latitude and longitude on rotated sphere

I have a sphere and I need to convert mouse click to latitude and longitude

Everything works fine as long as the sphere having no rotation, but if it have any rotation - I get wrong results

Here is my code:

var mouse = new THREE.Vector2();
mouse.x = (event.pageX / window.innerWidth) * 2 - 1;
mouse.y = -(event.pageY / window.innerHeight) * 2 + 1;

var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObject( EarthSphere );
if (intersects.length!=1) return;

var pointOnSphere = new THREE.Vector3();    
pointOnSphere.x = intersects[0].point.x;
pointOnSphere.y = intersects[0].point.y;
pointOnSphere.z = intersects[0].point.z;

var EarthRadius = 20;
var lat = 90 - (Math.acos(pointOnSphere.y / EarthRadius)) * 180 / Math.PI;
var lon = ((90 + (Math.atan2(pointOnSphere.x , pointOnSphere.z)) * 180 / Math.PI) % 360) - 180; 

I am gussing that I need to manipulate somehow the pointOnSphere based on EarthSphere, any ideas?

EDITED

earth.updateMatrixWorld(true); pointOnSphere = earth.localToWorld( pointOnSphere.clone() );

I thought something like the following would work:

EarthSphere.updateMatrixWorld(true);
pointOnSphere = EarthSphere.localToWorld( pointOnSphere.clone() );

But it does not work ..

Upvotes: 2

Views: 1193

Answers (1)

prisoner849
prisoner849

Reputation: 17596

three.js demo image

I think, you have to use .worldToLocal() rather than .localToWorld(). Thus you'll get a point in local coordinates of your sphere.

The documetation says about .worldToLocal():

Updates the vector from world space to local space.

Which means that the vector, passed into this function, will be updated. No creation of a new THREE.Vector3().

Both of those functions just update an existing vector which you pass to them.

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects;
var pointOfIntersection = new THREE.Vector3();
var localPoint = new THREE.Vector3();
var spherical = new THREE.Spherical();
var lat, lon;

window.addEventListener("mousedown", sphereClick, false);

function sphereClick(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  raycaster.setFromCamera(mouse, camera);
  intersects = raycaster.intersectObjects([sphere]);
  if (intersects.length == 0) return;
  pointOfIntersection = intersects[0].point;
  sphere.worldToLocal(localPoint.copy(pointOfIntersection));  // that's how it works with translation from the world coordinate system to the local one 
  createPoint(localPoint);
}

function createPoint(position) {
  var point = new THREE.Mesh(new THREE.SphereGeometry(0.0625, 16, 12), new THREE.MeshBasicMaterial({
    color: 0x777777 + Math.random() * 0x777777
  }));
  point.position.copy(position);
  sphere.add(point);
  var color = point.material.color.getHexString();

  // three.js already has useful object to get polar coordinates from the given vector - 'position', which is in local coordinates already 
  spherical.setFromVector3(position);
  lat = THREE.Math.radToDeg(Math.PI / 2 - spherical.phi);
  lon = THREE.Math.radToDeg(spherical.theta);

  pointList.innerHTML += "<span style='color:#" + color + "'>lat: " + lat + ";  lon: " + lon + "</span><br>";
}

jsfiddle example r87.

Upvotes: 2

Related Questions