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);
Related
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
I'm using Leaflet.js to save coverage maps and am giving the user the option of using polygons or circles.
To keep all objects in the same format, I'm converting the circle to a polygon before saving.
However, when I then reload the circle it is oval-shaped.
I know that this is due to the earth's curve but I'm unsure how to correct my method to take this into account? (I've looked but can't find anything that gives the solution I'm after).
The main issue is the javascript method I'm using below as that doesn't take into account the earth's curve.
// GenerateCirlcePolygon - Creates Circle from 360 line Segments
function GenerateCirlcePolygon(origin, radius) {
var earthRadius = 6371;
//latitude in radians
var lat = (origin.Latitude * Math.PI) / 180;
//longitude in radians
var lon = (origin.Longitude * Math.PI) / 180;
//angular distance covered on earth's surface
var d = parseFloat(radius) / earthRadius;
polyPoints = new Array();
for (i = 0; i <= 360; i++) {
var point = new VELatLong(0, 0)
var bearing = i * Math.PI / 180; //rad
point.Latitude = Math.asin(Math.sin(lat) * Math.cos(d) + Math.cos(lat) * Math.sin(d) * Math.cos(bearing));
point.Longitude = ((lon + Math.atan2(Math.sin(bearing) * Math.sin(d) * Math.cos(lat), Math.cos(d) - Math.sin(lat) * Math.sin(point.Latitude))) * 180) / Math.PI;
point.Latitude = (point.Latitude * 180) / Math.PI;
polyPoints.push(point);
}
Any advice at all would be great.
You can use the built in function from leaflet-geoman: L.PM.Utils.circleToPolygon(circle, sides)
L.PM.Utils.circleToPolygon(circle, 60).addTo(map)
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).
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>
I'm building a globe(sphere geometry) with set of predefined locations on geo-mapped and drawn as point(sphere geometry). I would like to focus(moving one location to another) those locations by rotating globe along y-axis. I tried the following code, seems not working for all locations.
location.geometry.computeBoundingBox();
var position = new THREE.Vector3();
position.subVectors( location.geometry.boundingBox.max, location.geometry.boundingBox.min );
position.multiplyScalar( 0.20 );
position.sub( location.geometry.boundingBox.min );
location.matrixWorld.multiplyVector3( position );
var point1 = scene.clone().position;
var point2 = position;
var distance = point1.distanceTo( point2 );
locationCollection.rotation.y = distance;
I think, I don't understand the concept enough. Hopefully, I will get some idea from the community.
Fiddle
var c = group.rotation.y;
var d = -b * (Math.PI / 180)%(2 * Math.PI);
var e = Math.PI / 2 * -1;
group.rotation.y = c % (2 * Math.PI);
group.rotation.x = a * (Math.PI / 180) % Math.PI;
group.rotation.y= d+e;
where a= latitude, b= longitude,group=Object3D(or sphere)