Translate from X, Y, Z to Latitude and Longitude - javascript

This is not a dupe of Converting from longitude\latitude to Cartesian coordinates.
I want to have functions that will translate back and forth between X, Y, Z coordinates and Latitude and Longitude. The things is the application already has this function to go from latitude/longitude to XYZ (this function is not changeable)...
export function getXYZ(lat, lng, radius) {
radius = radius || 200;
var gamma = ( 90 - lat) * Math.PI / 180;
var theta = (180 - lng) * Math.PI / 180;
var x = radius * Math.sin(gamma) * Math.cos(theta);
var y = radius * Math.cos(gamma);
var z = radius * Math.sin(gamma) * Math.sin(theta);
return {x: x, y: y, z: z};
}
I tried to create a paired function to go back the other way, but there's something not right.
export function getLatLng(vector, radius) {
radius = radius || 200;
var lat, latRads, lng, lngRads;
latRads = Math.acos(vector.y / radius);
lngRads = Math.atan2(vector.z, vector.x);
lat = (Math.PI / 2 - latRads) * 180 / Math.PI;
lng = (Math.PI - lngRads) * 180 / Math.PI;
return [lat, lng];
}
Any ideas?

I'll just go ahead and answer my own question...
export function getLatLng(vector, radius) {
radius = radius || 200;
var latRads = Math.acos(vector.y / radius);
var lngRads = Math.atan2(vector.z, vector.x);
var lat = (Math.PI / 2 - latRads) * (180 / Math.PI);
var lng = (Math.PI - lngRads) * (180 / Math.PI);
return [lat, lng - 180];
}
And the other way around...
export function getXYZ(lat, lng, radius) {
radius = radius || 200;
var latRads = ( 90 - lat) * Math.PI / 180;
var lngRads = (180 - lng) * Math.PI / 180;
var x = radius * Math.sin(latRads) * Math.cos(lngRads);
var y = radius * Math.cos(latRads);
var z = radius * Math.sin(latRads) * Math.sin(lngRads);
return {x: x, y: y, z: z};
}

I can't post comment so i'll start an "answer" although its not one:
In the getXYZ the radius can be passed as a parameter, but in the inverse function radius cannot be a parameter: it must be length(vector). Try replace the "radius = radius || 200;" by var radius = length(vector)" and remove the radius argument (didnt test).

Related

Get new point coordinate by current Point coordinate, angle and distance in arcgis js api 4.x

I want to get coordinate (x,y) of a point B based on coordinate of point A and distance from the point A and an angle using Arcgis js API 4.x .
For example : i have point A in (a,b) the distance between A and B is 500m and the angle is 20°, how can i get (x,y) of B.
i fount the equation here, i implemented it and it works perfectly.
this is my simple :
const R = 6371e3; //rayon of the erth
let lat1 = 36.7538 * Math.PI / 180; // latitude in rad
let long1 = 3.0588 * Math.PI / 180; // longiture in rad
let d = 5000; //distance between the two points
let angle = (90-20)*Math.PI/180; // the angle between the 2 points in rad (20°)
const sigma = d / R;
const delLat = sigma * Math.cos(angle);
let lat2 = (lat1 + delLat) * 180 / Math.PI;//latitude of the destination point
const del = Math.log(Math.tan(lat2 / 2 + Math.PI / 4) / Math.tan(lat1 / 2 + Math.PI / 4));
// const q = Math.abs(del) > 10e-12 ? delLat / del : Math.cos(lat1);
const q = Math.cos(lat1)
const delLong = sigma * Math.sin(angle) / q;
let long2 = (long1 + delLong) * 180 / Math.PI; //longitude of the destination point

Calculate the point between two coordinates based on a percentage (Spherically)

I found the following answer on Stackoverflow.
From what I understand, this is not the proper way to do it. The math is linear, however, the coordinates are mapped to a spherical surface. So what is the proper way to do it?
I have a function that calculates a midpoint, how can I alter it to accept a percentage as a parameter. In other words, find a midpoint that is between point 1 and 2 and is a percentage away from point 1...
middle_point(lat1, long1, lat2, long2) {
// Longitude difference.
var d_long = (long2 - long1) * Math.PI / 180;
// Convert to radians.
lat1 = lat1 * Math.PI / 180;
lat2 = lat2 * Math.PI / 180;
long1 = long1 * Math.PI / 180;
var b_x = Math.cos(lat2) * Math.cos(d_long);
var b_y = Math.cos(lat2) * Math.sin(d_long);
var lat3 = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + b_x) * (Math.cos(lat1) + b_x) + b_y * b_y));
var long3 = long1 + Math.atan2(b_y, Math.cos(lat1) + b_x);
// Return result.
return [long3 * 180/Math.PI, lat3 * 180/Math.PI];
}
The answer is given here: http://www.movable-type.co.uk/scripts/latlong.html and here: http://www.edwilliams.org/avform.htm#Intermediate
Here is the function you need, with "perc" between 0 and 100:
intermediate_point(lat1, long1, lat2, long2, perc) {
// Normalize percentage
perc = perc / 100;
// Convert to radians.
lat1 = lat1 * Math.PI / 180;
lat2 = lat2 * Math.PI / 180;
long1 = long1 * Math.PI / 180;
long2 = long2 * Math.PI / 180;
// get angular distance between points
var d_lat = lat2 - lat1;
var d_lon = long2 - long1;
var a = Math.sin(d_lat/2) * Math.sin(d_lat/2) + Math.cos(lat1) *
Math.cos(lat2) * Math.sin(d_lon/2) * Math.sin(d_lat/2);
var d = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var A = Math.sin((1-perc)*d) / Math.sin(d);
var B = Math.sin(perc*d) / Math.sin(d);
var x = A * Math.cos(lat1) * Math.cos(long1) + B * cos(lat2) * cos(long2);
var y = A * Math.cos(lat1) * Math.sin(long1) + B * cos(lat2) * sin(long2);
var z = A * Math.sin(lat1) + B * Math.sin(lat2);
var lat3 = Math.atan2(z, Math.sqrt(x*x + y*y));
var long3 = Math.atan2(y, x);
// Return result, normalising longitude to -180°...+180°
return [long3 * 180/Math.PI, (lat3 * 180/Math.PI + 540)%360-180];
}

3d sphere using javascript

I have been trying to learn creating basic 3d sphere using html5 canvas and I am new to 3d programming. When I googled, I found this incredibly useful article.You can find working example there.
function drawEllipse(ox, oy, oz, or, alpha, beta, gamma, hidden) {
for (var theta=0; theta <=2 * Math.PI; theta += 0.02) {
var px = ox + or * Math.cos(theta);
var py = oy;
var pz = oz + or * Math.sin(theta);
var a = transform(px, py, pz, alpha, beta, gamma);
if (!hidden || a[2] >= 0) {
drawDot(radius * a[0], radius * a[1]);
}
}
}
function drawDot(x, y) {
ctx.fillRect(x, y, 1, 1);
}
/* 3d rotation matrix */
function transform(x, y, z, rz, rx, ry) {
return [
((x * Math.sin(rz) - y * Math.cos(rz)) * Math.sin(rx) + z * Math.cos(rx)) * Math.sin(ry) + (x * Math.cos(rz) - y * Math.sin(rz)) * Math.cos(ry),
(x * Math.sin(rz) - y * Math.cos(rz)) * Math.cos(rx) - z * Math.sin(rx),
((x * Math.sin(rz) - y * Math.cos(rz)) * Math.sin(rx) + z * Math.cos(rx)) * Math.cos(ry) - (x * Math.cos(rz) - y * Math.sin(rz)) * Math.sin(ry)
]
}
/*latitude circles*/
for (var latitude = 0; latitude < Math.PI / 2; latitude += Math.PI / 18) {
drawEllipse(0, Math.sin(latitude), 0,Math.cos(latitude),0, alpha, gamma,true);
drawEllipse(0, -Math.sin(latitude), 0,Math.cos(latitude),0, alpha, gamma,true);
}
/*longitude circles*/
for (var longitude=0 ; longitude < Math.PI; longitude += Math.PI / 18) {
drawEllipse(0, 0, 0,1,longitude, Math.PI / 2 + alpha, gamma,true);
} // alpha and gamma are the x and y axis rotation angles
But the only problem is the direction of rotation when dragging the mouse on the sphere. Yaw and Pitch direction is not correct. Rotating left to right(yaw) working fine. But rotating top to bottom(pitch) is different. Can anyone please find a solution ?

javascript Latitude Longitude to xyz position on earth (threejs)

i´m playing arround with three.js
i want to render objects on specific geocoordinates on a bigger sphere, i´m pretty near to the solution, but i dont get the correct xyz position from lat lon
i have set up a test case on jsfiddle, there are two coordinates
latlons = [[40.7142700,-74.0059700], [52.5243700,13.4105300]];
its New York and Berlin
and this is my function to calc xyz from lat lon and radius
function calcPosFromLatLonRad(lat,lon,radius){
// Attempt1
var cosLat = Math.cos(lat * Math.PI / 180.0);
var sinLat = Math.sin(lat * Math.PI / 180.0);
var cosLon = Math.cos(lon * Math.PI / 180.0);
var sinLon = Math.sin(lon * Math.PI / 180.0);
var rad = radius;
y = rad * cosLat * sinLon;
x = rad * cosLat * cosLon;
z = rad * sinLat;
// Attempt2
// x = radius * Math.sin(lat) * Math.cos(lon)
// y = radius * Math.sin(lat) * Math.sin(lon)
// z = radius * Math.cos(lat)
// Attempt3
// latitude = lat * Math.PI/180
// longitude = lon * Math.PI/180
// x = -radius * Math.cos(latitude) * Math.cos(longitude)
// y = radius * Math.sin(latitude)
// z = radius * Math.cos(latitude) * Math.sin(longitude)
// Attempt4
// var phi = (90-lat)*(Math.PI/180);
// var theta = (lng+180)*(Math.PI/180);
// x = ((rad) * Math.sin(phi)*Math.cos(theta));
// z = ((rad) * Math.sin(phi)*Math.sin(theta));
// y = ((rad) * Math.cos(phi));
console.log([x,y,z]);
return [x,y,z];
}
but all attempts return different xy, and they are all not correct ( z is always correct).
could someone pleas guide me to the right way ?
i have no idea what could be wrong
heres the fiddle to play with
UPDATE: working jsfiddle
unfortunatly i can´t further explain, but after playing around this one works like a charme :)
function calcPosFromLatLonRad(lat,lon,radius){
var phi = (90-lat)*(Math.PI/180);
var theta = (lon+180)*(Math.PI/180);
x = -(radius * Math.sin(phi)*Math.cos(theta));
z = (radius * Math.sin(phi)*Math.sin(theta));
y = (radius * Math.cos(phi));
return [x,y,z];
}
yeah thats pretty cool isnt it ?
And i´m still interested into some shorter equation
working fiddle
This function works for me:
function calcPosFromLatLonRad(radius, lat, lon) {
var spherical = new THREE.Spherical(
radius,
THREE.Math.degToRad(90 - lon),
THREE.Math.degToRad(lat)
);
var vector = new THREE.Vector3();
vector.setFromSpherical(spherical);
console.log(vector.x, vector.y, vector.z);
return vector;
}
calcPosFromLatLonRad(0.5, -74.00597, 40.71427);

How to find the angle between two locations defined by latitude or longitude using javascript? [duplicate]

I want to calculate the bearing from point 1 to point 2
The input format is 52.070564 - 4.407116
No matter what i try i cannot get an correct output.
The formula i use is :
// koers berekenen
var y = Math.sin(ln-ln1) * Math.cos(lt);
var x = Math.cos(lt1)*Math.sin(lt) -
Math.sin(lt1)*Math.cos(lt)*Math.cos(ln-ln1);
var radians = Math.atan2(y, x);
var bearing = Math.round(radians * (180/Math.PI));
/* >>>>>> original <<<<<<<
var y = Math.sin(λ2-λ1) * Math.cos(φ2);
var x = Math.cos(φ1)*Math.sin(φ2) -
Math.sin(φ1)*Math.cos(φ2)*Math.cos(λ2-λ1);
var brng = Math.atan2(y, x).toDegrees();
φ1,λ1 is the start point, φ2,λ2 the end point (Δλ is the difference in longitude)
*/
You can calculate bearing using this functions:
// Converts from degrees to radians.
function toRadians(degrees) {
return degrees * Math.PI / 180;
};
// Converts from radians to degrees.
function toDegrees(radians) {
return radians * 180 / Math.PI;
}
function bearing(startLat, startLng, destLat, destLng){
startLat = toRadians(startLat);
startLng = toRadians(startLng);
destLat = toRadians(destLat);
destLng = toRadians(destLng);
y = Math.sin(destLng - startLng) * Math.cos(destLat);
x = Math.cos(startLat) * Math.sin(destLat) -
Math.sin(startLat) * Math.cos(destLat) * Math.cos(destLng - startLng);
brng = Math.atan2(y, x);
brng = toDegrees(brng);
return (brng + 360) % 360;
}
start_latitude = 12.9389352
start_longitude = 77.6994306
stop_latitude = 12.939103
stop_longitude = 77.705825
var y = Math.sin(stop_longitude-start_longitude) * Math.cos(stop_latitude);
var x = Math.cos(start_latitude)*Math.sin(stop_latitude) -
Math.sin(start_latitude)*Math.cos(stop_latitude)*Math.cos(stop_longitude-start_longitude);
var brng = Math.atan2(y, x) * 180 / Math.PI;
alert("Bearing in degreee: " + brng);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Categories

Resources