Calculating correct longitude when it's over |180|?
up vote
7
down vote
favorite
I'm trying to develop a "formula" to correct the lat-lng values.
I'm using vue-leaflet but when you pan outside the "first" world you get big numbers. Over +180 or under -180.
For example: when I pan to America to the right (east direction), I get as lng 215.
In my mind, I would just correct it with 215-360=-145
The same is for when I pan to east russia to the left (west direction) and I get for example -222. Now I need to calculate -222+360=138
However, since the world is indefinite the user could pan to the 8th world and I had to adjust the values.
Is it possible to calculate the right longitude? (and another requirement is when the user is in the first world, 24 lng should still be 24 lng.
leaflet javascript latitude-longitude
New contributor
add a comment |
up vote
7
down vote
favorite
I'm trying to develop a "formula" to correct the lat-lng values.
I'm using vue-leaflet but when you pan outside the "first" world you get big numbers. Over +180 or under -180.
For example: when I pan to America to the right (east direction), I get as lng 215.
In my mind, I would just correct it with 215-360=-145
The same is for when I pan to east russia to the left (west direction) and I get for example -222. Now I need to calculate -222+360=138
However, since the world is indefinite the user could pan to the 8th world and I had to adjust the values.
Is it possible to calculate the right longitude? (and another requirement is when the user is in the first world, 24 lng should still be 24 lng.
leaflet javascript latitude-longitude
New contributor
add a comment |
up vote
7
down vote
favorite
up vote
7
down vote
favorite
I'm trying to develop a "formula" to correct the lat-lng values.
I'm using vue-leaflet but when you pan outside the "first" world you get big numbers. Over +180 or under -180.
For example: when I pan to America to the right (east direction), I get as lng 215.
In my mind, I would just correct it with 215-360=-145
The same is for when I pan to east russia to the left (west direction) and I get for example -222. Now I need to calculate -222+360=138
However, since the world is indefinite the user could pan to the 8th world and I had to adjust the values.
Is it possible to calculate the right longitude? (and another requirement is when the user is in the first world, 24 lng should still be 24 lng.
leaflet javascript latitude-longitude
New contributor
I'm trying to develop a "formula" to correct the lat-lng values.
I'm using vue-leaflet but when you pan outside the "first" world you get big numbers. Over +180 or under -180.
For example: when I pan to America to the right (east direction), I get as lng 215.
In my mind, I would just correct it with 215-360=-145
The same is for when I pan to east russia to the left (west direction) and I get for example -222. Now I need to calculate -222+360=138
However, since the world is indefinite the user could pan to the 8th world and I had to adjust the values.
Is it possible to calculate the right longitude? (and another requirement is when the user is in the first world, 24 lng should still be 24 lng.
leaflet javascript latitude-longitude
leaflet javascript latitude-longitude
New contributor
New contributor
edited 6 hours ago
PolyGeo♦
52.7k1779236
52.7k1779236
New contributor
asked 22 hours ago
Shadrix
1384
1384
New contributor
New contributor
add a comment |
add a comment |
5 Answers
5
active
oldest
votes
up vote
10
down vote
accepted
You need to repeatedly add (or subtract) 360 to your value until it lies in the range of -180 - 180. So usually a pair of loops like:
lon = -187;
while(lon < -180){
lon +=360;
}
while (lon > 180){
lon -= 360;
}
signs wrong way round? Should be lon +=360 in first case.
– JimT
21 hours ago
2
bleeugh, coding before coffee. Thanks
– Ian Turton♦
21 hours ago
2
you can do it with only one loopwhile (Math.abs(lon) > 180) { lon -= Math.sign(lon) * 360 }
I am not providing it as an answer though because your version actually matches the explanation, while my version is just an optimization that likely doesn't make any difference. I keep it as a comment only as a reminder that things can be done in multiple ways, some more optimized than others.
– Andrei
20 hours ago
1
I don't think I would ever use that one as it uses 2 function calls per loop and only one of my loops would ever execute. Probably makes no difference in this example but that's my prejudice
– Ian Turton♦
20 hours ago
2
You can't dolon %= 180
?
– Nic Hartley
13 hours ago
|
show 2 more comments
up vote
7
down vote
An answer that avoids conditionals and function calls:
longitude = (longitude % 360 + 540) % 360 - 180
I wrote a quick microbenchmark at https://jsperf.com/longitude-normalisation and the conditional code seems to be faster (in Chrome on my machine) for 'reasonable' ranges of input values. In general you probably shouldn't be worrying in advance about performance in small calculations like this, giving more weight to readability and consistency with the rest of your codebase.
Probably more important in this case is the question of whether your code could ever come across extreme input values (1e10, Infinity etc.). If so, the looping implementation could end up running really slowly or silently hanging your program. This might occur with calculations performed near the poles, e.g. trying to pan east or west by some distance (rather than angle) from a pole could easily result in an infinite longitude.
New contributor
1
Interesting. Let's race a conditional jmp against a FP divide. Hmmm I wonder.
– Joshua
11 hours ago
1
@Joshua You can't use a conditional jump. You have to use multiple conditional jumps, aka a loop. (Plus the loop contains floating point additional, which isn't free.) How many iterations the loop needs depends on the input. So you have to know something about the data to look at performance. If the vast majority are near the desired range and require few iterations, sure, the addition loop might be faster, but it isn't as obvious as your sarcasm suggests.
– jpmc26
9 hours ago
1
@jpmc26: In this case, expecting to go around the loop more than once is silly.
– Joshua
9 hours ago
1
There was no sarcasm. I actually don't know which way it would fall.
– Joshua
9 hours ago
1
@Joshua yep, I wasn't sure either :). I added more to the answer on performance (and a potential failure case of the loop code)
– Joe Lee-Moyet
6 hours ago
add a comment |
up vote
3
down vote
One-liner:
normalized = remainder(longitude, 360);
Explanation: You want to know what remains after you disregard full rotations (360°).
This process is called normalizing.
Example (cpp.sh)
New contributor
1
Wouldn't this result in a [0, 360) value, not [-180, 180] as Shadrix requested?
– The Guy with The Hat
15 hours ago
@TheGuywithTheHat Check this example: cpp.sh/7uy2v
– Peter Paff
14 hours ago
Ah, didn't know this was C++. In Shadrix's context of JavaScript, I interpretedremainder
asmodulus
. Modulus in JS would result in [0, 360).
– The Guy with The Hat
14 hours ago
@TheGuywithTheHat subtract 180 from the result and done.
– Peter Paff
14 hours ago
I don't think that would work. You would need to subtract 360 iff result > 180. Another problem I just realized with JavaScript is that modulo is symmetrical across 0, e.g.-1 % 3
is -1, not 2 as would be necessary for it to work here.remainder
is a great C++ solution, but unfortunately there's just no function/operator in JS that's similar enough to be useful.
– The Guy with The Hat
13 hours ago
add a comment |
up vote
0
down vote
Another option: longitude = atan2(cos(long), sin(long))
1
This doesn't seem like a good idea. It's very hard to understand, computationally expensive and potentially subject to rounding errors.
– David Richerby
12 hours ago
add a comment |
up vote
0
down vote
If the programming language you're using supports the % (mod) operator on floating point numbers (like Python and Ruby), I'd recommend using that. Otherwise, some other languages (like C and C++) allow you to use fmod().
(Whichever mod operator you use, make sure ahead of time that it will do mod operations on floating-point numbers. Otherwise you'll get a nasty surprise later when many of your lat/lon points are not correct.)
Use it like this:
# Put the longitude in the range of [0,360):
longitude %= 360
# Put the longitude in the range of [-180,180):
if longitude >= 180:
longitude -= 360
If you'd prefer to do it all in one line:
# Put the longitude in the range of [-180,180):
longitude = (longitude + 180) % 360 - 180
These approaches have no loops, so they'll normalize longitude values without needing to repeatedly add or subtract, no matter how many times your observation has circled around the earth.
Edit:
Hmmm... I just noticed that Javascript doesn't seem to handle %
with negative values like I thought it would.
In that case, try this one-liner:
longitude = (longitude + 36180) % 360 - 180
The 36180
we're adding is 36,000 + 180. The 36,000 is to move a negative value into the positive domain, and the 180 is to shift it over so that when it is modded by 360
, it'll be in the range of [0,360). The - 180
part shifts it back to the range of [-180,180).
Here's another one-liner, one that doesn't rely on 36,000 being big enough:
longitude = (longitude % 360 + 360 + 180) % 360 - 180
The longitude % 360 + 360
part will ensure the value stays in the positive domain when it's later modded by 360
. The + 180
part shifts it over so that when it later gets 180 subtracted from it (with - 180
), it'll be in the desired range of [-180,180).
New contributor
Note: C,C++fmod(longitude, 360)
--> (-360.0 ... +360.0) andilongitude % 360
--> [-359 ... +359].
– chux
1 hour ago
add a comment |
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
10
down vote
accepted
You need to repeatedly add (or subtract) 360 to your value until it lies in the range of -180 - 180. So usually a pair of loops like:
lon = -187;
while(lon < -180){
lon +=360;
}
while (lon > 180){
lon -= 360;
}
signs wrong way round? Should be lon +=360 in first case.
– JimT
21 hours ago
2
bleeugh, coding before coffee. Thanks
– Ian Turton♦
21 hours ago
2
you can do it with only one loopwhile (Math.abs(lon) > 180) { lon -= Math.sign(lon) * 360 }
I am not providing it as an answer though because your version actually matches the explanation, while my version is just an optimization that likely doesn't make any difference. I keep it as a comment only as a reminder that things can be done in multiple ways, some more optimized than others.
– Andrei
20 hours ago
1
I don't think I would ever use that one as it uses 2 function calls per loop and only one of my loops would ever execute. Probably makes no difference in this example but that's my prejudice
– Ian Turton♦
20 hours ago
2
You can't dolon %= 180
?
– Nic Hartley
13 hours ago
|
show 2 more comments
up vote
10
down vote
accepted
You need to repeatedly add (or subtract) 360 to your value until it lies in the range of -180 - 180. So usually a pair of loops like:
lon = -187;
while(lon < -180){
lon +=360;
}
while (lon > 180){
lon -= 360;
}
signs wrong way round? Should be lon +=360 in first case.
– JimT
21 hours ago
2
bleeugh, coding before coffee. Thanks
– Ian Turton♦
21 hours ago
2
you can do it with only one loopwhile (Math.abs(lon) > 180) { lon -= Math.sign(lon) * 360 }
I am not providing it as an answer though because your version actually matches the explanation, while my version is just an optimization that likely doesn't make any difference. I keep it as a comment only as a reminder that things can be done in multiple ways, some more optimized than others.
– Andrei
20 hours ago
1
I don't think I would ever use that one as it uses 2 function calls per loop and only one of my loops would ever execute. Probably makes no difference in this example but that's my prejudice
– Ian Turton♦
20 hours ago
2
You can't dolon %= 180
?
– Nic Hartley
13 hours ago
|
show 2 more comments
up vote
10
down vote
accepted
up vote
10
down vote
accepted
You need to repeatedly add (or subtract) 360 to your value until it lies in the range of -180 - 180. So usually a pair of loops like:
lon = -187;
while(lon < -180){
lon +=360;
}
while (lon > 180){
lon -= 360;
}
You need to repeatedly add (or subtract) 360 to your value until it lies in the range of -180 - 180. So usually a pair of loops like:
lon = -187;
while(lon < -180){
lon +=360;
}
while (lon > 180){
lon -= 360;
}
edited 21 hours ago
answered 21 hours ago
Ian Turton♦
46.7k546109
46.7k546109
signs wrong way round? Should be lon +=360 in first case.
– JimT
21 hours ago
2
bleeugh, coding before coffee. Thanks
– Ian Turton♦
21 hours ago
2
you can do it with only one loopwhile (Math.abs(lon) > 180) { lon -= Math.sign(lon) * 360 }
I am not providing it as an answer though because your version actually matches the explanation, while my version is just an optimization that likely doesn't make any difference. I keep it as a comment only as a reminder that things can be done in multiple ways, some more optimized than others.
– Andrei
20 hours ago
1
I don't think I would ever use that one as it uses 2 function calls per loop and only one of my loops would ever execute. Probably makes no difference in this example but that's my prejudice
– Ian Turton♦
20 hours ago
2
You can't dolon %= 180
?
– Nic Hartley
13 hours ago
|
show 2 more comments
signs wrong way round? Should be lon +=360 in first case.
– JimT
21 hours ago
2
bleeugh, coding before coffee. Thanks
– Ian Turton♦
21 hours ago
2
you can do it with only one loopwhile (Math.abs(lon) > 180) { lon -= Math.sign(lon) * 360 }
I am not providing it as an answer though because your version actually matches the explanation, while my version is just an optimization that likely doesn't make any difference. I keep it as a comment only as a reminder that things can be done in multiple ways, some more optimized than others.
– Andrei
20 hours ago
1
I don't think I would ever use that one as it uses 2 function calls per loop and only one of my loops would ever execute. Probably makes no difference in this example but that's my prejudice
– Ian Turton♦
20 hours ago
2
You can't dolon %= 180
?
– Nic Hartley
13 hours ago
signs wrong way round? Should be lon +=360 in first case.
– JimT
21 hours ago
signs wrong way round? Should be lon +=360 in first case.
– JimT
21 hours ago
2
2
bleeugh, coding before coffee. Thanks
– Ian Turton♦
21 hours ago
bleeugh, coding before coffee. Thanks
– Ian Turton♦
21 hours ago
2
2
you can do it with only one loop
while (Math.abs(lon) > 180) { lon -= Math.sign(lon) * 360 }
I am not providing it as an answer though because your version actually matches the explanation, while my version is just an optimization that likely doesn't make any difference. I keep it as a comment only as a reminder that things can be done in multiple ways, some more optimized than others.– Andrei
20 hours ago
you can do it with only one loop
while (Math.abs(lon) > 180) { lon -= Math.sign(lon) * 360 }
I am not providing it as an answer though because your version actually matches the explanation, while my version is just an optimization that likely doesn't make any difference. I keep it as a comment only as a reminder that things can be done in multiple ways, some more optimized than others.– Andrei
20 hours ago
1
1
I don't think I would ever use that one as it uses 2 function calls per loop and only one of my loops would ever execute. Probably makes no difference in this example but that's my prejudice
– Ian Turton♦
20 hours ago
I don't think I would ever use that one as it uses 2 function calls per loop and only one of my loops would ever execute. Probably makes no difference in this example but that's my prejudice
– Ian Turton♦
20 hours ago
2
2
You can't do
lon %= 180
?– Nic Hartley
13 hours ago
You can't do
lon %= 180
?– Nic Hartley
13 hours ago
|
show 2 more comments
up vote
7
down vote
An answer that avoids conditionals and function calls:
longitude = (longitude % 360 + 540) % 360 - 180
I wrote a quick microbenchmark at https://jsperf.com/longitude-normalisation and the conditional code seems to be faster (in Chrome on my machine) for 'reasonable' ranges of input values. In general you probably shouldn't be worrying in advance about performance in small calculations like this, giving more weight to readability and consistency with the rest of your codebase.
Probably more important in this case is the question of whether your code could ever come across extreme input values (1e10, Infinity etc.). If so, the looping implementation could end up running really slowly or silently hanging your program. This might occur with calculations performed near the poles, e.g. trying to pan east or west by some distance (rather than angle) from a pole could easily result in an infinite longitude.
New contributor
1
Interesting. Let's race a conditional jmp against a FP divide. Hmmm I wonder.
– Joshua
11 hours ago
1
@Joshua You can't use a conditional jump. You have to use multiple conditional jumps, aka a loop. (Plus the loop contains floating point additional, which isn't free.) How many iterations the loop needs depends on the input. So you have to know something about the data to look at performance. If the vast majority are near the desired range and require few iterations, sure, the addition loop might be faster, but it isn't as obvious as your sarcasm suggests.
– jpmc26
9 hours ago
1
@jpmc26: In this case, expecting to go around the loop more than once is silly.
– Joshua
9 hours ago
1
There was no sarcasm. I actually don't know which way it would fall.
– Joshua
9 hours ago
1
@Joshua yep, I wasn't sure either :). I added more to the answer on performance (and a potential failure case of the loop code)
– Joe Lee-Moyet
6 hours ago
add a comment |
up vote
7
down vote
An answer that avoids conditionals and function calls:
longitude = (longitude % 360 + 540) % 360 - 180
I wrote a quick microbenchmark at https://jsperf.com/longitude-normalisation and the conditional code seems to be faster (in Chrome on my machine) for 'reasonable' ranges of input values. In general you probably shouldn't be worrying in advance about performance in small calculations like this, giving more weight to readability and consistency with the rest of your codebase.
Probably more important in this case is the question of whether your code could ever come across extreme input values (1e10, Infinity etc.). If so, the looping implementation could end up running really slowly or silently hanging your program. This might occur with calculations performed near the poles, e.g. trying to pan east or west by some distance (rather than angle) from a pole could easily result in an infinite longitude.
New contributor
1
Interesting. Let's race a conditional jmp against a FP divide. Hmmm I wonder.
– Joshua
11 hours ago
1
@Joshua You can't use a conditional jump. You have to use multiple conditional jumps, aka a loop. (Plus the loop contains floating point additional, which isn't free.) How many iterations the loop needs depends on the input. So you have to know something about the data to look at performance. If the vast majority are near the desired range and require few iterations, sure, the addition loop might be faster, but it isn't as obvious as your sarcasm suggests.
– jpmc26
9 hours ago
1
@jpmc26: In this case, expecting to go around the loop more than once is silly.
– Joshua
9 hours ago
1
There was no sarcasm. I actually don't know which way it would fall.
– Joshua
9 hours ago
1
@Joshua yep, I wasn't sure either :). I added more to the answer on performance (and a potential failure case of the loop code)
– Joe Lee-Moyet
6 hours ago
add a comment |
up vote
7
down vote
up vote
7
down vote
An answer that avoids conditionals and function calls:
longitude = (longitude % 360 + 540) % 360 - 180
I wrote a quick microbenchmark at https://jsperf.com/longitude-normalisation and the conditional code seems to be faster (in Chrome on my machine) for 'reasonable' ranges of input values. In general you probably shouldn't be worrying in advance about performance in small calculations like this, giving more weight to readability and consistency with the rest of your codebase.
Probably more important in this case is the question of whether your code could ever come across extreme input values (1e10, Infinity etc.). If so, the looping implementation could end up running really slowly or silently hanging your program. This might occur with calculations performed near the poles, e.g. trying to pan east or west by some distance (rather than angle) from a pole could easily result in an infinite longitude.
New contributor
An answer that avoids conditionals and function calls:
longitude = (longitude % 360 + 540) % 360 - 180
I wrote a quick microbenchmark at https://jsperf.com/longitude-normalisation and the conditional code seems to be faster (in Chrome on my machine) for 'reasonable' ranges of input values. In general you probably shouldn't be worrying in advance about performance in small calculations like this, giving more weight to readability and consistency with the rest of your codebase.
Probably more important in this case is the question of whether your code could ever come across extreme input values (1e10, Infinity etc.). If so, the looping implementation could end up running really slowly or silently hanging your program. This might occur with calculations performed near the poles, e.g. trying to pan east or west by some distance (rather than angle) from a pole could easily result in an infinite longitude.
New contributor
edited 6 hours ago
New contributor
answered 14 hours ago
Joe Lee-Moyet
1713
1713
New contributor
New contributor
1
Interesting. Let's race a conditional jmp against a FP divide. Hmmm I wonder.
– Joshua
11 hours ago
1
@Joshua You can't use a conditional jump. You have to use multiple conditional jumps, aka a loop. (Plus the loop contains floating point additional, which isn't free.) How many iterations the loop needs depends on the input. So you have to know something about the data to look at performance. If the vast majority are near the desired range and require few iterations, sure, the addition loop might be faster, but it isn't as obvious as your sarcasm suggests.
– jpmc26
9 hours ago
1
@jpmc26: In this case, expecting to go around the loop more than once is silly.
– Joshua
9 hours ago
1
There was no sarcasm. I actually don't know which way it would fall.
– Joshua
9 hours ago
1
@Joshua yep, I wasn't sure either :). I added more to the answer on performance (and a potential failure case of the loop code)
– Joe Lee-Moyet
6 hours ago
add a comment |
1
Interesting. Let's race a conditional jmp against a FP divide. Hmmm I wonder.
– Joshua
11 hours ago
1
@Joshua You can't use a conditional jump. You have to use multiple conditional jumps, aka a loop. (Plus the loop contains floating point additional, which isn't free.) How many iterations the loop needs depends on the input. So you have to know something about the data to look at performance. If the vast majority are near the desired range and require few iterations, sure, the addition loop might be faster, but it isn't as obvious as your sarcasm suggests.
– jpmc26
9 hours ago
1
@jpmc26: In this case, expecting to go around the loop more than once is silly.
– Joshua
9 hours ago
1
There was no sarcasm. I actually don't know which way it would fall.
– Joshua
9 hours ago
1
@Joshua yep, I wasn't sure either :). I added more to the answer on performance (and a potential failure case of the loop code)
– Joe Lee-Moyet
6 hours ago
1
1
Interesting. Let's race a conditional jmp against a FP divide. Hmmm I wonder.
– Joshua
11 hours ago
Interesting. Let's race a conditional jmp against a FP divide. Hmmm I wonder.
– Joshua
11 hours ago
1
1
@Joshua You can't use a conditional jump. You have to use multiple conditional jumps, aka a loop. (Plus the loop contains floating point additional, which isn't free.) How many iterations the loop needs depends on the input. So you have to know something about the data to look at performance. If the vast majority are near the desired range and require few iterations, sure, the addition loop might be faster, but it isn't as obvious as your sarcasm suggests.
– jpmc26
9 hours ago
@Joshua You can't use a conditional jump. You have to use multiple conditional jumps, aka a loop. (Plus the loop contains floating point additional, which isn't free.) How many iterations the loop needs depends on the input. So you have to know something about the data to look at performance. If the vast majority are near the desired range and require few iterations, sure, the addition loop might be faster, but it isn't as obvious as your sarcasm suggests.
– jpmc26
9 hours ago
1
1
@jpmc26: In this case, expecting to go around the loop more than once is silly.
– Joshua
9 hours ago
@jpmc26: In this case, expecting to go around the loop more than once is silly.
– Joshua
9 hours ago
1
1
There was no sarcasm. I actually don't know which way it would fall.
– Joshua
9 hours ago
There was no sarcasm. I actually don't know which way it would fall.
– Joshua
9 hours ago
1
1
@Joshua yep, I wasn't sure either :). I added more to the answer on performance (and a potential failure case of the loop code)
– Joe Lee-Moyet
6 hours ago
@Joshua yep, I wasn't sure either :). I added more to the answer on performance (and a potential failure case of the loop code)
– Joe Lee-Moyet
6 hours ago
add a comment |
up vote
3
down vote
One-liner:
normalized = remainder(longitude, 360);
Explanation: You want to know what remains after you disregard full rotations (360°).
This process is called normalizing.
Example (cpp.sh)
New contributor
1
Wouldn't this result in a [0, 360) value, not [-180, 180] as Shadrix requested?
– The Guy with The Hat
15 hours ago
@TheGuywithTheHat Check this example: cpp.sh/7uy2v
– Peter Paff
14 hours ago
Ah, didn't know this was C++. In Shadrix's context of JavaScript, I interpretedremainder
asmodulus
. Modulus in JS would result in [0, 360).
– The Guy with The Hat
14 hours ago
@TheGuywithTheHat subtract 180 from the result and done.
– Peter Paff
14 hours ago
I don't think that would work. You would need to subtract 360 iff result > 180. Another problem I just realized with JavaScript is that modulo is symmetrical across 0, e.g.-1 % 3
is -1, not 2 as would be necessary for it to work here.remainder
is a great C++ solution, but unfortunately there's just no function/operator in JS that's similar enough to be useful.
– The Guy with The Hat
13 hours ago
add a comment |
up vote
3
down vote
One-liner:
normalized = remainder(longitude, 360);
Explanation: You want to know what remains after you disregard full rotations (360°).
This process is called normalizing.
Example (cpp.sh)
New contributor
1
Wouldn't this result in a [0, 360) value, not [-180, 180] as Shadrix requested?
– The Guy with The Hat
15 hours ago
@TheGuywithTheHat Check this example: cpp.sh/7uy2v
– Peter Paff
14 hours ago
Ah, didn't know this was C++. In Shadrix's context of JavaScript, I interpretedremainder
asmodulus
. Modulus in JS would result in [0, 360).
– The Guy with The Hat
14 hours ago
@TheGuywithTheHat subtract 180 from the result and done.
– Peter Paff
14 hours ago
I don't think that would work. You would need to subtract 360 iff result > 180. Another problem I just realized with JavaScript is that modulo is symmetrical across 0, e.g.-1 % 3
is -1, not 2 as would be necessary for it to work here.remainder
is a great C++ solution, but unfortunately there's just no function/operator in JS that's similar enough to be useful.
– The Guy with The Hat
13 hours ago
add a comment |
up vote
3
down vote
up vote
3
down vote
One-liner:
normalized = remainder(longitude, 360);
Explanation: You want to know what remains after you disregard full rotations (360°).
This process is called normalizing.
Example (cpp.sh)
New contributor
One-liner:
normalized = remainder(longitude, 360);
Explanation: You want to know what remains after you disregard full rotations (360°).
This process is called normalizing.
Example (cpp.sh)
New contributor
edited 14 hours ago
New contributor
answered 16 hours ago
Peter Paff
312
312
New contributor
New contributor
1
Wouldn't this result in a [0, 360) value, not [-180, 180] as Shadrix requested?
– The Guy with The Hat
15 hours ago
@TheGuywithTheHat Check this example: cpp.sh/7uy2v
– Peter Paff
14 hours ago
Ah, didn't know this was C++. In Shadrix's context of JavaScript, I interpretedremainder
asmodulus
. Modulus in JS would result in [0, 360).
– The Guy with The Hat
14 hours ago
@TheGuywithTheHat subtract 180 from the result and done.
– Peter Paff
14 hours ago
I don't think that would work. You would need to subtract 360 iff result > 180. Another problem I just realized with JavaScript is that modulo is symmetrical across 0, e.g.-1 % 3
is -1, not 2 as would be necessary for it to work here.remainder
is a great C++ solution, but unfortunately there's just no function/operator in JS that's similar enough to be useful.
– The Guy with The Hat
13 hours ago
add a comment |
1
Wouldn't this result in a [0, 360) value, not [-180, 180] as Shadrix requested?
– The Guy with The Hat
15 hours ago
@TheGuywithTheHat Check this example: cpp.sh/7uy2v
– Peter Paff
14 hours ago
Ah, didn't know this was C++. In Shadrix's context of JavaScript, I interpretedremainder
asmodulus
. Modulus in JS would result in [0, 360).
– The Guy with The Hat
14 hours ago
@TheGuywithTheHat subtract 180 from the result and done.
– Peter Paff
14 hours ago
I don't think that would work. You would need to subtract 360 iff result > 180. Another problem I just realized with JavaScript is that modulo is symmetrical across 0, e.g.-1 % 3
is -1, not 2 as would be necessary for it to work here.remainder
is a great C++ solution, but unfortunately there's just no function/operator in JS that's similar enough to be useful.
– The Guy with The Hat
13 hours ago
1
1
Wouldn't this result in a [0, 360) value, not [-180, 180] as Shadrix requested?
– The Guy with The Hat
15 hours ago
Wouldn't this result in a [0, 360) value, not [-180, 180] as Shadrix requested?
– The Guy with The Hat
15 hours ago
@TheGuywithTheHat Check this example: cpp.sh/7uy2v
– Peter Paff
14 hours ago
@TheGuywithTheHat Check this example: cpp.sh/7uy2v
– Peter Paff
14 hours ago
Ah, didn't know this was C++. In Shadrix's context of JavaScript, I interpreted
remainder
as modulus
. Modulus in JS would result in [0, 360).– The Guy with The Hat
14 hours ago
Ah, didn't know this was C++. In Shadrix's context of JavaScript, I interpreted
remainder
as modulus
. Modulus in JS would result in [0, 360).– The Guy with The Hat
14 hours ago
@TheGuywithTheHat subtract 180 from the result and done.
– Peter Paff
14 hours ago
@TheGuywithTheHat subtract 180 from the result and done.
– Peter Paff
14 hours ago
I don't think that would work. You would need to subtract 360 iff result > 180. Another problem I just realized with JavaScript is that modulo is symmetrical across 0, e.g.
-1 % 3
is -1, not 2 as would be necessary for it to work here. remainder
is a great C++ solution, but unfortunately there's just no function/operator in JS that's similar enough to be useful.– The Guy with The Hat
13 hours ago
I don't think that would work. You would need to subtract 360 iff result > 180. Another problem I just realized with JavaScript is that modulo is symmetrical across 0, e.g.
-1 % 3
is -1, not 2 as would be necessary for it to work here. remainder
is a great C++ solution, but unfortunately there's just no function/operator in JS that's similar enough to be useful.– The Guy with The Hat
13 hours ago
add a comment |
up vote
0
down vote
Another option: longitude = atan2(cos(long), sin(long))
1
This doesn't seem like a good idea. It's very hard to understand, computationally expensive and potentially subject to rounding errors.
– David Richerby
12 hours ago
add a comment |
up vote
0
down vote
Another option: longitude = atan2(cos(long), sin(long))
1
This doesn't seem like a good idea. It's very hard to understand, computationally expensive and potentially subject to rounding errors.
– David Richerby
12 hours ago
add a comment |
up vote
0
down vote
up vote
0
down vote
Another option: longitude = atan2(cos(long), sin(long))
Another option: longitude = atan2(cos(long), sin(long))
answered 12 hours ago
Andres
163211
163211
1
This doesn't seem like a good idea. It's very hard to understand, computationally expensive and potentially subject to rounding errors.
– David Richerby
12 hours ago
add a comment |
1
This doesn't seem like a good idea. It's very hard to understand, computationally expensive and potentially subject to rounding errors.
– David Richerby
12 hours ago
1
1
This doesn't seem like a good idea. It's very hard to understand, computationally expensive and potentially subject to rounding errors.
– David Richerby
12 hours ago
This doesn't seem like a good idea. It's very hard to understand, computationally expensive and potentially subject to rounding errors.
– David Richerby
12 hours ago
add a comment |
up vote
0
down vote
If the programming language you're using supports the % (mod) operator on floating point numbers (like Python and Ruby), I'd recommend using that. Otherwise, some other languages (like C and C++) allow you to use fmod().
(Whichever mod operator you use, make sure ahead of time that it will do mod operations on floating-point numbers. Otherwise you'll get a nasty surprise later when many of your lat/lon points are not correct.)
Use it like this:
# Put the longitude in the range of [0,360):
longitude %= 360
# Put the longitude in the range of [-180,180):
if longitude >= 180:
longitude -= 360
If you'd prefer to do it all in one line:
# Put the longitude in the range of [-180,180):
longitude = (longitude + 180) % 360 - 180
These approaches have no loops, so they'll normalize longitude values without needing to repeatedly add or subtract, no matter how many times your observation has circled around the earth.
Edit:
Hmmm... I just noticed that Javascript doesn't seem to handle %
with negative values like I thought it would.
In that case, try this one-liner:
longitude = (longitude + 36180) % 360 - 180
The 36180
we're adding is 36,000 + 180. The 36,000 is to move a negative value into the positive domain, and the 180 is to shift it over so that when it is modded by 360
, it'll be in the range of [0,360). The - 180
part shifts it back to the range of [-180,180).
Here's another one-liner, one that doesn't rely on 36,000 being big enough:
longitude = (longitude % 360 + 360 + 180) % 360 - 180
The longitude % 360 + 360
part will ensure the value stays in the positive domain when it's later modded by 360
. The + 180
part shifts it over so that when it later gets 180 subtracted from it (with - 180
), it'll be in the desired range of [-180,180).
New contributor
Note: C,C++fmod(longitude, 360)
--> (-360.0 ... +360.0) andilongitude % 360
--> [-359 ... +359].
– chux
1 hour ago
add a comment |
up vote
0
down vote
If the programming language you're using supports the % (mod) operator on floating point numbers (like Python and Ruby), I'd recommend using that. Otherwise, some other languages (like C and C++) allow you to use fmod().
(Whichever mod operator you use, make sure ahead of time that it will do mod operations on floating-point numbers. Otherwise you'll get a nasty surprise later when many of your lat/lon points are not correct.)
Use it like this:
# Put the longitude in the range of [0,360):
longitude %= 360
# Put the longitude in the range of [-180,180):
if longitude >= 180:
longitude -= 360
If you'd prefer to do it all in one line:
# Put the longitude in the range of [-180,180):
longitude = (longitude + 180) % 360 - 180
These approaches have no loops, so they'll normalize longitude values without needing to repeatedly add or subtract, no matter how many times your observation has circled around the earth.
Edit:
Hmmm... I just noticed that Javascript doesn't seem to handle %
with negative values like I thought it would.
In that case, try this one-liner:
longitude = (longitude + 36180) % 360 - 180
The 36180
we're adding is 36,000 + 180. The 36,000 is to move a negative value into the positive domain, and the 180 is to shift it over so that when it is modded by 360
, it'll be in the range of [0,360). The - 180
part shifts it back to the range of [-180,180).
Here's another one-liner, one that doesn't rely on 36,000 being big enough:
longitude = (longitude % 360 + 360 + 180) % 360 - 180
The longitude % 360 + 360
part will ensure the value stays in the positive domain when it's later modded by 360
. The + 180
part shifts it over so that when it later gets 180 subtracted from it (with - 180
), it'll be in the desired range of [-180,180).
New contributor
Note: C,C++fmod(longitude, 360)
--> (-360.0 ... +360.0) andilongitude % 360
--> [-359 ... +359].
– chux
1 hour ago
add a comment |
up vote
0
down vote
up vote
0
down vote
If the programming language you're using supports the % (mod) operator on floating point numbers (like Python and Ruby), I'd recommend using that. Otherwise, some other languages (like C and C++) allow you to use fmod().
(Whichever mod operator you use, make sure ahead of time that it will do mod operations on floating-point numbers. Otherwise you'll get a nasty surprise later when many of your lat/lon points are not correct.)
Use it like this:
# Put the longitude in the range of [0,360):
longitude %= 360
# Put the longitude in the range of [-180,180):
if longitude >= 180:
longitude -= 360
If you'd prefer to do it all in one line:
# Put the longitude in the range of [-180,180):
longitude = (longitude + 180) % 360 - 180
These approaches have no loops, so they'll normalize longitude values without needing to repeatedly add or subtract, no matter how many times your observation has circled around the earth.
Edit:
Hmmm... I just noticed that Javascript doesn't seem to handle %
with negative values like I thought it would.
In that case, try this one-liner:
longitude = (longitude + 36180) % 360 - 180
The 36180
we're adding is 36,000 + 180. The 36,000 is to move a negative value into the positive domain, and the 180 is to shift it over so that when it is modded by 360
, it'll be in the range of [0,360). The - 180
part shifts it back to the range of [-180,180).
Here's another one-liner, one that doesn't rely on 36,000 being big enough:
longitude = (longitude % 360 + 360 + 180) % 360 - 180
The longitude % 360 + 360
part will ensure the value stays in the positive domain when it's later modded by 360
. The + 180
part shifts it over so that when it later gets 180 subtracted from it (with - 180
), it'll be in the desired range of [-180,180).
New contributor
If the programming language you're using supports the % (mod) operator on floating point numbers (like Python and Ruby), I'd recommend using that. Otherwise, some other languages (like C and C++) allow you to use fmod().
(Whichever mod operator you use, make sure ahead of time that it will do mod operations on floating-point numbers. Otherwise you'll get a nasty surprise later when many of your lat/lon points are not correct.)
Use it like this:
# Put the longitude in the range of [0,360):
longitude %= 360
# Put the longitude in the range of [-180,180):
if longitude >= 180:
longitude -= 360
If you'd prefer to do it all in one line:
# Put the longitude in the range of [-180,180):
longitude = (longitude + 180) % 360 - 180
These approaches have no loops, so they'll normalize longitude values without needing to repeatedly add or subtract, no matter how many times your observation has circled around the earth.
Edit:
Hmmm... I just noticed that Javascript doesn't seem to handle %
with negative values like I thought it would.
In that case, try this one-liner:
longitude = (longitude + 36180) % 360 - 180
The 36180
we're adding is 36,000 + 180. The 36,000 is to move a negative value into the positive domain, and the 180 is to shift it over so that when it is modded by 360
, it'll be in the range of [0,360). The - 180
part shifts it back to the range of [-180,180).
Here's another one-liner, one that doesn't rely on 36,000 being big enough:
longitude = (longitude % 360 + 360 + 180) % 360 - 180
The longitude % 360 + 360
part will ensure the value stays in the positive domain when it's later modded by 360
. The + 180
part shifts it over so that when it later gets 180 subtracted from it (with - 180
), it'll be in the desired range of [-180,180).
New contributor
edited 6 hours ago
New contributor
answered 11 hours ago
J-L
1011
1011
New contributor
New contributor
Note: C,C++fmod(longitude, 360)
--> (-360.0 ... +360.0) andilongitude % 360
--> [-359 ... +359].
– chux
1 hour ago
add a comment |
Note: C,C++fmod(longitude, 360)
--> (-360.0 ... +360.0) andilongitude % 360
--> [-359 ... +359].
– chux
1 hour ago
Note: C,C++
fmod(longitude, 360)
--> (-360.0 ... +360.0) and ilongitude % 360
--> [-359 ... +359].– chux
1 hour ago
Note: C,C++
fmod(longitude, 360)
--> (-360.0 ... +360.0) and ilongitude % 360
--> [-359 ... +359].– chux
1 hour ago
add a comment |
Shadrix is a new contributor. Be nice, and check out our Code of Conduct.
Shadrix is a new contributor. Be nice, and check out our Code of Conduct.
Shadrix is a new contributor. Be nice, and check out our Code of Conduct.
Shadrix is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgis.stackexchange.com%2fquestions%2f303300%2fcalculating-correct-longitude-when-its-over-180%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown