Trying to write some maths from Wikipedia in Javascript (sun position computation) - javascript

I am trying to approximate the position of the sun in XYZ for a threejs project.
I am following the maths found here: http://en.wikipedia.org/wiki/Position_of_the_Sun
Following the above, I have written the following Javascript code:
var n = ((2440587.5 + (this.datemillis / 8.64E7)) - 2451545);
var L = 280.460 + 0.9856474 * n;
var g = 357.528 + 0.9856003 * n;
L = (L + 360) % 360;
g = (g + 360) % 60;
var lambda = L + 1.915 * Math.sin(g) + 0.0020 * Math.sin(2 * g);
var r = 1.00014 - 0.01671 * Math.cos(g) - 0.00014 * Math.cos(2 * g);
var e = 23.439 - 0.0000004 * n;
var x = (r * this.constants.EARTH_RADIUS * 2) * Math.cos(lambda);
var y = (r * this.constants.EARTH_RADIUS * 2) * Math.cos(e) * Math.sin(lambda);
var z = (r * this.constants.EARTH_RADIUS * 2) * Math.sin(e) * Math.sin(lambda);
this.datemillis is returned by the getMillisecond function of the Javascript date object. It is updated each frame so that time advances at about 1 hour every 2 seconds.
However something must not be correct as this does not produce the expected result. When I apply the computed x y z coordinates to my sun in my threejs project, I can see the sun rotate around the earth (sitting in 0,0,0) but at a very slow rate (rotating the earth in a few days instead of 24 hours).
I'm thinking it might have something to do with the angle calculations that I'm not doing correctly (degrees/radians?) but I'm not very good at maths so I don't really know what I'm doing so maybe I just misinterpreted the Wiki calculations.
If somebody could spot something obvious I'm doing wrong and help me fix this, would be greatly appreciated!
Thanks
EDIT: so my sun currently is not rotating around the earth in a continous way - it rotates clockwise/counterclockwise alternatively and sometimes jumps positions...

I suggest this to get the Julian Date, from Calculating Jday(Julian Day) in javascript
var today = Date();
var JD = Math.floor((today / 86400000) - (today.getTimezoneOffset()/1440) + 2440587.5);
Add to JD the desired amount of days and increment that value at the desired speed. Note that if you add 1 day each millisecond you'll get 1000 days per second, not 1 hour every 2 seconds.
JD += offset;
Then go on with the wikipedia recipe:
var n = JD - 2451545;
//...
To put L and g in the range 0-360 (you have an error here) use
L = L % 360 + ( L < 0 ? 360 : 0 );
g = g % 360 + ( g < 0 ? 360 : 0 );
The wikipedia formulas express angles in degrees. However JavaScript trigonometric functions cos and sin expect radians.
Just write a "degrees" version of them:
function cosD( deg ) {
return Math.cos( deg * Math.PI / 180.0 );
}
function sinD( deg ) {
return Math.sin( deg * Math.PI / 180.0 );
}
Then use sinD() and cosD() in subsequent calculations.
var r = 1.00014 - 0.01671 * cosD(g) - 0.00014 * cosD(2 * g);
var e = 23.439 - 0.0000004 * n;
var x = (r * this.constants.EARTH_RADIUS * 2) * cosD(lambda);
var y = (r * this.constants.EARTH_RADIUS * 2) * cosD(e) * sinD(lambda);
var z = (r * this.constants.EARTH_RADIUS * 2) * sinD(e) * sinD(lambda);

I cannot answer your question but I do know this is a solved problem in threejs. There is an example running in an architecture/engineering workflow on Github on this topic. The sun position code is here https://github.com/radio412/viewer/blob/gh-pages/sun-position.js
You can see it being tapped for a directional light in threejs at line 108 here: https://github.com/radio412/viewer/blob/gh-pages/va3c-viewer.js

Related

Geometric rotations of a group of objects

Referring to the first diagram, I am trying to copy the three objects, looking at them from an arbitrary angle(A1). The distance between where I'm and the first object does not matter just the relative location of the object to one another.
In the second diagram, I select a point to copy these objects, facing another arbitrary angle(B1).
Angle (C1) shows the approximate position of -90 degrees.
I can get this to work if A1 = 0,90,180,270 and even 45,135 etc but the equations I come up with only work for 0 and 180 or 90 and 270. I have to modify them to work in those directions by changing a hardcoded offset angle and putting/removing a negative sign before the offset.
I'm doing this is javascript (and its Minecraft) usually I can figure out this but I have been working on it for weeks.
Here is some pseudo-code that works some of the time in certain right-angle directions. I have updated this to be more accurate, the 1x and 2x are the blocks x coordinate, etc. - everything is relative from the (1) block.
Minecraft's coordinate system is a little different from normal - 0 is south, +90 is west, 180 is north, 270 is east.
the only difference is that I am making negative az, ax.
// works for north/south looking - A1 is either 180/0 , B1 can be anything
var x = 1x - 2x;
var z = 1z - 2z;
var direction = Math.atan2(z1, x1);
var L1 = Math.sqrt(Math.pow(x1, 2) + Math.pow(z1, 2));
var az = Math.round(L1 * Math.sin((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
var ax = Math.round(L1 * Math.cos((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
// works for east/west looking - A1 is either 90/270 , B1 can be anything
var x = 1x - 2x;
var z = 1z - 2z;
var direction = Math.atan2(z1, x1);
var L1 = Math.sqrt(Math.pow(x1, 2) + Math.pow(z1, 2));
var az = -Math.round(L1 * Math.sin((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
var ax = -Math.round(L1 * Math.cos((B1 + A1 + (direction * 180 / Math.PI)) * Math.PI / 180));
First diagram
Second diagram

Implement hermite interpolation - multiplayer game

I am trying to make a client-server architecture. I am stuck at the interpolation part. Right now, I have a very naive implementation of the interpolation algorithm. I have every player given a position history and whenever I receive a position data for other player from the server I push the position in to that array. Every client frame I use the oldest position history to interpolate to a new position with a constant speed.
// when new position for other player recieved
p.stateHistory.push(data)
// Every client frame
if(p.stateHistory.length < 1)
return false
let deltaPosition = p.stateHistory[0].position.clone().sub(p.clientPosition)
let direction = Math.atan2(deltaPosition.y, deltaPosition.x)
let velocity = new Vector2(Math.cos(direction), Math.sin(direction)).scale(30/100)
let threshold = 10
if(deltaPosition.magnitude() < threshold) {
p.clientPosition.x = p.stateHistory[0].position.x
p.clientPosition.y = p.stateHistory[0].position.y
p.stateHistory.shift()
} else {
p.clientPosition.add(velocity.clone().scale(deltaTime))
}
I couldn't find way other to interpolate with a constant speed. I came to know about hermite interpolation from gafferongames. But it's sad that the article didn't have anything about its math and its implementation. I tried to go through the wikipedia article on hermite interpolation, but it didn't help. I know nothing about the math behind it. A pseudo code would be appreciated.
What I have been able to do so far: http://client-side-prediction-attempt.herokuapp.com/
Let's say say that your client receives a new position-velocity update at time currentTime. Then, you need to save the current position/velocity, the target position/velocity, the current time, and the time when you expect the next update:
function updateFromServer(position, velocity) {
startP = currentPosition; //the current position of the player
startV = currentVelocity;
endP = position;
endV = velocity;
startT = currentTime; //the current time of the game
endT = startT + 0.1; //expect the next update in 100 ms
}
Once you have stored this data, you can do your frame update using interpolation. If you are outside of the [startT, endT] interval, you might just want to continue a uniform motion:
function frameUpdate(deltaT) {
if(currentTime > endT)
//uniform motion
currentPosition += deltaT * currentVelocity;
else {
//cubic Hermite interpolation
var t = (currentTime - startT) / (endT - startT); //interpolation parameter
var t2 = t * t;
var t3 = t2 * t;
currentPosition =
(2 * t3 - 3 * t2 + 1) * startP +
(t3 - 2 * t2 + t) * (endT - startT) * startV +
(-2 * t3 + 3 * t2) * endP +
(t3 - t2) * (endT - startT) * endV;
currentVelocity = 1 / (endT - startT) * (
(6 * t2 - 6 * t) * startP +
(3 * t2 - 4 * t + 1) * (endT - startT) * startV +
(-6 * t2 + 6 * t) * endP +
(3 * t2 - 2 * t) * (endT - startT) * endV);
}
}
Note that the formulas in this snippet are not valid JavaScript code. They must be translated to whatever library you use.

Clear & simple example of how to calculate TDOA (Time Difference Of Arrival)

Trying to calculate TDOA (Time Difference Of Arrival) but I can’t get my head around it. Can someone please help me with an clear and simple example.
I have 3 microphone located at:
X0 = 0 cm
Y0 = 0 cm
-
X1 = 0 cm
Y1 = 15 cm
-
X2 = 0 cm
Y2 = 30 cm
Time different of sound arrive to the 3 microphone:
A0 = 0 sec
A1 = 0.002 sec
A2 = 0.004 sec
Speed of sound:
S = 340 m/sec
Updated after response from wessel
I am trying to make a script calc TDOA
let ? = (Y1 - Y0) / (S); // = 0.00044
let ? = (Y2 - Y0) / (S); // = 0.00088
let VX = (X1 - X0) / A0; // = NaN
let VY = (Y1 - Y0) / A0; // = Infinity
let V = Math.sqrt(VX^2 + VY^2) // = 1.4142
let alpha = atan(VY / VX) // = NaN
console.log(alpha+' deg with the x-axis.');
If you have a distance and a speed (distance / time), you get a time by doing distance / speed = distance / (distance / time ) = distance / distance * time = time.
What you omit in your question, is the direction and the shape of the sound wave. If the sound is traveling along the x-axis, the shape does not matter, and the time difference would be:
(A1 - A0) = (X1 - X0) / (340 m/s) = 0.15 / 340 s = 0.00044 s
(A2 - A0) = (X2 - X0) / (340 m/s) = 0.3 / 340 s = 0.00088 s
If the shape is a straight line, e.g. from an infinitely far point source or from a particularly shaped non-point source, the different of arrival time is given by the x-component of the direction of the sound wave:
VX = (X1 - X0) / (A1 - A0) = 37.5 m/s.
The total sound speed, which you give as 340 m/s, should equal
V = Sqrt(VX^2 + VY^2)
such that you can work out that
VY = Sqrt(V^2 - VX^2) = 338 m/s
or
VY = -Sqrt(V^2 - VX^2) = -338 m/s
such that your sound wave must in incoming under an angle alpha:
alpha = atan(VY / VX) = 83 deg
with the x-axis.
I don't see why javascript is relevant here, though. Just in case: use Math.sqrt, Math.pow or V*V, and Math.atan or Math.atan2 (beware of the order of the arguments there!).

Getting to 16 Available Bits in Javascript

I recently came across a YouTube video that discussed handling GPS coordinates by using space filled curves. There was a formula provided to accomplish this so I've decided to try and replicate it, however I have not been able to figure out how to get to the same result using JavaScript.
The formula was as follows:
Scale Latitude and longitude to use 16 available bits each:
scaled_x = (-122.4012 + 180) / 360 * 2 ^ 16 // result = 10485
scale_y = (37.7839 + 90) / 180 * 2 ^ 16 // result = 46524
Video Reference
I've tries several ways of writing the formula and my results are far off from what I should be getting based on what was shown in the presentation. Either the presentation was inaccurate or I've not landed on the correct way of getting to this.
Here are some of my attempts, all fail.
Using Pow
base = Math.round((lat + 180) / 360);
scale = Math.pow(base * 2, 16); // Result = 0
Exact Formula
base = Math.round((lat + 180) / 360 * 2 ^ 16); // Result = 16
Inline Power
base = Math.round((lat + 180) / 360 * Math.pow(2, 16)); // Result = -22282
Does anyone know how this formula needs to be structured in JavaScript to get the expected outcome?
base = Math.round((lat + 180) / 360);
scale = Math.pow(base * 2, 16)
This doesn't work because you're rounding the value before multiplying it by 216 -- so it will round to either 0 or 1. This is not what you want.
base = Math.round((lat + 180) / 360 * 2 ^ 16);
In Javascript -- and many other languages -- ^ is used for bitwise XOR, not exponentiation. 2 ^ 16 is 18, not 65536.
base = Math.round((lat + 180) / 360 * Math.pow(2, 16));
This looks correct. The result you've quoted isn't right for lat = -122.4012, though -- did you leave out the + 180, perhaps?

Distance from long lat line segment wrong over long distances [duplicate]

This question already has answers here:
Calculate possible lines from points
(2 answers)
Closed 9 years ago.
I am calculating how far away a point is from a line segment on the earth.
My function seemed to work, but as i've increased the distances it's clear it's not working. I presume this is due to the curvature of the earth.
In my calculations Rome is shown as 5km from the line:
London, UK - 0km
Rome, Italy - 5km
Cyrene, Libya - 0km
But on Google Earth it's actually more like 61km
When I start going longer distances the calculations get even worse!
Rome, Italy - 0km
Mohenjo-daro, Pakistan - 0km
Istanbul, Turkey - 250km
I believe the problem is somewhere in the code here:
function distToSegment(lat1, lon1, lat2, lon2, lat3, lon3) {
var y = Math.sin(lon3 - lon1) * Math.cos(lat3);
var x = Math.cos(lat1) * Math.sin(lat3) - Math.sin(lat1) * Math.cos(lat3) * Math.cos(lat3 - lat1);
var bearing1 = radiansToDegrees(Math.atan2(y, x));
bearing1 = 360 - (bearing1 + 360 % 360);
var y2 = Math.sin(lon2 - lon1) * Math.cos(lat2);
var x2 = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lat2 - lat1);
var bearing2 = radiansToDegrees(Math.atan2(y2, x2));
bearing2 = 360 - (bearing2 + 360 % 360);
var lat1Rads = degreesToRadians(lat1);
var lat3Rads = degreesToRadians(lat3);
var dLon = degreesToRadians(lon3 - lon1);
var distanceAC = Math.acos(Math.sin(lat1Rads) * Math.sin(lat3Rads) + Math.cos(lat1Rads) * Math.cos(lat3Rads) * Math.cos(dLon)) * 6371;
var min_distance = Math.abs(Math.asin(Math.sin(distanceAC / 6371) * Math.sin(degreesToRadians(bearing1) - degreesToRadians(bearing2))) * 6371);
return min_distance;
}
Here is a working fiddle you can use to test:
http://jsfiddle.net/kmturley/cfg2D/3/
Any help to figure this one out would be appreciated!
This
bearing1 = 360 - (bearing1 + 360 % 360)
looks fishy to me. Do you mean
bearing1 = 360 - (bearing1 + 360) % 360
?
Likewise for bearing2.
% is a multiplicative operator and has higher precedence than +.

Categories

Resources