I'm trying to merge two databases for consolidating two clients' websites. However, Client A has been using regular Lat/Lon pairs for geolocation, while Client B is using Lambert 72 (X/Y) coordinates.
I've built a script that should convert these coordinates (as I'm not sure which coordinates will be used in the final merged database, I'm trying converting them either way).
I took some snippets from here: http://zoologie.umh.ac.be/tc/algorithms.aspx
Please note that all coordinates mentioned below point to locations in Belgium.
I'm converting some coordinates to see if the calculations are correct, but the coordinates I'm getting seem to be way off. For reference, the center of Belgium is roughly (North 50.84323737103243, East 4.355735778808594), so I'd expect all coordinates to be close to these values.
I converted the Lambert 72 value (X: 151488250, Y: 170492909) to a Lat/Lon pair, but the result is: (-87.538.... , -50.724....) which is way off from the expected values.
If I convert full circle (Lambert->LatLon->Lambert and vice versa), I get the same result values as I entered, so I know my conversions are at least consistent and the conversions are perfect inversions of one another.
I tried some online converter tools as well, and they give me the same (-87.538.... , -50.724....) result.
Since multiple sources yield the same results, and my conversions are correct inversions of eachother, I'm figuring the calculations themselves are correct, but the resulting values still need to be converted/offset further?
I consider myself to be sufficient in algebra, but cartographic projections completely elude me.
Can someone please shed some light on this?
Extra Info
I hope I posted this in the correct forum. I'm not really sure where to put this as this is a mix of geography, mathematics and coding/conversion...
The mentioned Lambert coordinates (X: 151488250, Y: 170492909) point to a location in Brussels, so the Lat/Lon result should be very near to (North 50.84323737103243, East 4.355735778808594).
Please find my conversion functions below:
public static Lambert72 LatLon_To_Lambert72(LatLon latlon)
{
var lat = latlon.Lat;
var lng = latlon.Lon;
double LongRef = 0.076042943;
//=4°21'24"983
double bLamb = 6378388 * (1 - (1 / 297));
double aCarre = Math.Pow(6378388, 2);
double eCarre = (aCarre - Math.Pow(bLamb, 2)) / aCarre;
double KLamb = 11565915.812935;
double nLamb = 0.7716421928;
double eLamb = Math.Sqrt(eCarre);
double eSur2 = eLamb / 2;
//conversion to radians
lat = (Math.PI / 180) * lat;
lng = (Math.PI / 180) * lng;
double eSinLatitude = eLamb * Math.Sin(lat);
double TanZDemi = (Math.Tan((Math.PI / 4) - (lat / 2))) * (Math.Pow(((1 + (eSinLatitude)) / (1 - (eSinLatitude))), (eSur2)));
double RLamb = KLamb * (Math.Pow((TanZDemi), nLamb));
double Teta = nLamb * (lng - LongRef);
double x = 0;
double y = 0;
x = 150000 + 0.01256 + RLamb * Math.Sin(Teta - 0.000142043);
y = 5400000 + 88.4378 - RLamb * Math.Cos(Teta - 0.000142043);
return new Lambert72(x, y);
}
public static LatLon Lambert72_To_LatLon(Lambert72 lb72)
{
double X = lb72.X;
double Y = lb72.Y;
double LongRef = 0.076042943;
//=4°21'24"983
double nLamb = 0.7716421928;
double aCarre = Math.Pow(6378388, 2);
double bLamb = 6378388 * (1 - (1 / 297));
double eCarre = (aCarre - Math.Pow(bLamb, 2)) / aCarre;
double KLamb = 11565915.812935;
double eLamb = Math.Sqrt(eCarre);
double eSur2 = eLamb / 2;
double Tan1 = (X - 150000.01256) / (5400088.4378 - Y);
double Lambda = LongRef + (1 / nLamb) * (0.000142043 + Math.Atan(Tan1));
double RLamb = Math.Sqrt(Math.Pow((X - 150000.01256), 2) + Math.Pow((5400088.4378 - Y), 2));
double TanZDemi = Math.Pow((RLamb / KLamb), (1 / nLamb));
double Lati1 = 2 * Math.Atan(TanZDemi);
double eSin = 0;
double Mult1 = 0;
double Mult2 = 0;
double Mult = 0;
double LatiN = 0;
double Diff = 0;
double lat = 0;
double lng = 0;
do {
eSin = eLamb * Math.Sin(Lati1);
Mult1 = 1 - eSin;
Mult2 = 1 + eSin;
Mult = Math.Pow((Mult1 / Mult2), (eLamb / 2));
LatiN = (Math.PI / 2) - (2 * (Math.Atan(TanZDemi * Mult)));
Diff = LatiN - Lati1;
Lati1 = LatiN;
} while (Math.Abs(Diff) > 2.77777E-08);
lat = (LatiN * 180) / Math.PI;
lng = (Lambda * 180) / Math.PI;
return new LatLon(lat, lng);
}
I am the author of the page you mention in your post.
I don't know if you have resolved your problem but the Lambert coordinates you give are not correct. I think that you have to divide them by 1000. That gives x=151488.250 and y=170492.909 which are possible coordinates and corresponding to a street in... Brussels.
Be careful to the choice of the datum when converting to and from lat/lng values.
Related
I tried converting lat/long to XYZ tile and again using the XYZ values trying to get back the lat/long. The values of lat/long are not the same (the original one and the converted one). I referred to https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#C.23 and got the formula for conversion.
Below is the code for your reference:
Converting from lat/long to XYZ:
var x = (int)Math.Floor((longitude + 180.0) / 360.0 * Math.Pow(2, zoom));
var y = (int)Math.Floor((1 - Math.Log(Math.Tan((Math.PI / 180) * latitude) + 1 / Math.Cos((Math.PI / 180) * latitude)) / Math.PI) / 2 * Math.Pow(2, zoom));
Converting from XYZ to lat/long:
var longitude = x / Math.Pow(2, z) * 360 - 180;
var n = Math.PI - 2 * Math.PI * y / Math.Pow(2, z);
var latitude = 180 / Math.PI * Math.Atan(0.5 * (Math.Exp(n) - Math.Exp(-n)));
When I pass latitude = -477.42187500000006, longitude = 37.3002752813443, zoom = 15, then I get x = 19779 and y = -2147483648.
But when I pass x = 19779, y = -2147483648, z = 15, then I get latitude = 90.0 and longitude = 37.298583984375 which is wrong.
I am not sure why the second conversion is giving the wrong results. Any help is highly appreciated.
Latitudes are by definition belong to range -90 (south pole) to 90 (north pole).
So you start with invalid one -477.421875 and the result can be arbitrary.
The longitude is correct. It is slightly different from original, which is expected since you truncate x to nearest integer. If you want the same value, don't round to integer.
In my case on picture firstPoint0 - as example my first point and center of the circle, relative this point confine screenings by radius 1 km. I need to show just all points in my radius, others points thisPoint not show by linq query.
var flats = context.Flats;
var first = flats.FirstOrDefault(x => x.Lattitude && x.Longitude);
var getAllInRadius = flats.Where(? take points where distance <= 1 km)
Just use the Haversine formula that returns the great-circle distance between two points on a sphere:
// Returns the great circle distance between two flats, as meters
public static double DistanceBetweenFlats(Flat flat1, Flat flat2)
{
const int EarthRadius = 6371;
double latitude = ToRadian(flat2.Latitude - flat1.Latitude);
double longitude = ToRadian(flat2.Longitude - flat1.Longitude);
double tmp = (Math.Sin(latitude / 2) * Math.Sin(latitude / 2)) +
(Math.Cos(ToRadian(flat1.Latitude)) * Math.Cos(ToRadian(flat2.Latitude)) *
Math.Sin(longitude / 2) * Math.Sin(longitude / 2));
double c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(tmp)));
double d = EarthRadius * c;
return d * 1000;
}
...
var centerFlat = ...;
var getAllInRadius = flats.Where(z => DistanceBetweenFlats(centerFlat, z) <= 1000);
Of course all of this assumes you're using LINQ in memory (not LINQ to Entities). If it's not the case, you'll have to use spatial queries.
I am trying to sort out a method to calculate the distance between 2 points in c#.
This is the code I have been trying though I fear the answer I get is not correct.
static void Main()
{
//postcode australia 2600 -> 3000
float latA = -31.997976f;
float longA = 115.762877f;
float latB = -31.99212f;
float longB = 115.763228f;
decimal distance = (DistanceBetween(latA, latB, longA, longB));
Console.WriteLine("Distance is" + distance);
Console.ReadLine();
}
static decimal DistanceBetween(float latA, float longA, float latB, float longB)
{
var RadianLatA = Math.PI * latA / 180;
var RadianLatb = Math.PI * latB / 180;
var RadianLongA = Math.PI * longA / 180;
var RadianLongB = Math.PI * longB / 180;
double theDistance = (Math.Sin(RadianLatA)) *
Math.Sin(RadianLatb) +
Math.Cos(RadianLatA) *
Math.Cos(RadianLatb) *
Math.Cos(RadianLongA - RadianLongB);
return Convert.ToDecimal(((Math.Acos(theDistance) * (180.0 / Math.PI)))) * 69.09M * 1.6093M;
}
this was adapted from a response found on this site here
Distance between addresses
Any thoughts on what is going wrong/
Thanks
Ryan
The class I usually use is GeoCoordinate
double latA = -31.997976f;
double longA = 115.762877f;
double latB = -31.99212f;
double longB = 115.763228f;
var locA = new GeoCoordinate(latA, longA);
var locB = new GeoCoordinate(latB, longB);
double distance = locA.GetDistanceTo(locB ); // metres
double lat1 = {};
double lat2 = {};
double lon1 = {};
double lon2 = {};
var R = 6376.5000; //Km
lat1 = lat1.ToRad();
lat2 = lat2.ToRad();
lon1 = lon1.ToRad();
lon2 = lon2.ToRad();
var dLat = lat2 - lat1;
var dLon = lon2 - lon1;
var a = Math.Pow(Math.Sin(dLat / 2), 2) + (Math.Pow(Math.Sin(dLon / 2), 2) * Math.Cos(lat1) * Math.Cos(lat2));
var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
var distance = R * c;
public double ToRad(this double degs) {
return degs * (Math.PI/180.0);
}
Input expects doubles.
This is the haversine formula, it's used to calculate the distances on our globe between two points. This is the distance in a straight line, if you need the distance on a path you will have to find all points on that path and then calculate the distances between each two points and then take the sum of that.
You can use DbGeography for spatial calculation. It has DbGeography.Distance method which is used to calculate the distance between two gps points.
Otherwise, try Ref: Harversine Formula to calculate the distance between two points.
Distance Formula: Given the two points (x1, y1) and (x2, y2), the distance between these points is given by the formula:
use it accordingly
I've read several links discussing storing 2 or 3 floats in one float. Here's an example:
Storing two float values in a single float variable
and another:
http://uncommoncode.wordpress.com/2012/11/07/float-packing-in-shaders-encoding-multiple-components-in-one-float/
and yet another:
decode rgb value to single float without bit-shift in glsl
I've seen others but all of them use the same principle. If you want to encode x and y, they multiply y by some factor and then add x to it. Well this makes since on paper, but I don't understand how in the world it can work when stored to a floating value. Floating values only have 7 significant digits. If you add a big number and a small number, the small number is just truncated and lost. The precision only shows the value of the big number.
Since everyone seems to prescribe the same method, I tried it myself and it did exactly what I thought it would do. When I decoded the numbers, the number that wasn't multiplied turned out as 0.0. It was completely lost in the encoded float.
Here's an example of some MaxScript I tried to test it:
cp = 256.0 * 256.0
scaleFac = 16777215
for i = 1 to 20 do (
for j = 1 to 20 do (
x = (i as float / 20.01f) as float;
y = (j as float / 20.01f) as float;
xScaled = x * scaleFac;
yScaled = y * scaleFac;
f = (xScaled + yScaled * cp) as float
print ("x[" + xScaled as string + "] y[" + yScaled as string + "]" + " e[" + f as string + "]")
dy = floor(f / cp)
dx = (f - dy * cp)
print ("x[" + dx as string + "] y[" + dy as string + "]" + " e[" + f as string + "]")
)
)
dx is 0.0 everytime. Can anyone shed some light on this? NOTE: It doesn't matter whether I make cp = 128, 256, 512 or whatever. It still gives me the same types of results.
This method works for storing two integers. You're effectively converting your floating point numbers to large integers by multiplying by scaleFac, which is good, but it would be better to make it explicit with int(). Then you need to make sure of two things: cp is greater than the largest number you're working with (scaleFac), and the square of cp is small enough to fit into a floating point number without truncation (about 7 digits for a single precision float).
Here is a working code in C to pack two floats into one float and unpack them.
You should change scaleFactor and cp parameters as according to your possible value ranges (yourBiggestNumber * scaleFactor < cp). It is a precision battle. Try printing a few results to find good values for your case. The example below allows floats in [0 to 1) range.
#include <math.h>
/* yourBiggestNumber * scaleFactor < cp */
double scaleFactor = 65530.0;
double cp = 256.0 * 256.0;
/* packs given two floats into one float */
float pack_float(float x, float y) {
int x1 = (int) (x * scaleFactor);
int y1 = (int) (y * scaleFactor);
float f = (y1 * cp) + x1;
return f;
}
/* unpacks given float to two floats */
int unpack_float(float f, float* x, float* y){
double dy = floor(f / cp);
double dx = f - (dy * cp);
*y = (float) (dy / scaleFactor);
*x = (float) (dx / scaleFactor);
return 0;
}
It will work only if your individual floats are small enough to be packed into one float location.
So you can pack 2 numbers by "dividing" this into two to store 2 numbers that can be represented by half the space.
Here's the code I use for packing and unpacking floats. It works by packing first float (0..1) into the first four bytes of a 8-bit (0..256) number, and the next float into the remaining 4 bits. The resulting numbers have 16 possible combinations each (2^4). In some cases this is good enough:
private float PackFloatsInto8Bits( float v1, float v2 )
{
var a = Mathf.Round( v1 * 15f );
var b = Mathf.Round( v2 * 15f );
var bitShiftVector = new Vector2( 1f/( 255f/16f ), 1f/255f );
return Vector2.Dot( new Vector2( a, b ), bitShiftVector );
}
private Vector2 UnpackFloatsFrom8Bits( float input )
{
float temp = input * 15.9375f;
float a = Mathf.Floor(temp) / 15.0f;
float b = Frac( temp ) * 1.0667f;
return new Vector2(a, b);
}
I have some C# code that generates google maps. This codes looks at all the Points I need to plot on the map and then works out the Bounds of a rectangle to include those points. It then passes this bounds to the Google Maps API to set the zoom level appropriately to show all of the points on the map.
This code is working fine however I have a new requirement.
One of the points may have a precision associated with it. If this is the case then I draw a circle around the point with the radius set to the precision value. Again this works fine however my bounds checking is now not doing what I want it to do. I want to have the bounding box include the complete circle.
This requires an algorithm to take a point x and calculate the point y that would be z metres north of x and also z metres south of x.
Does anyone have this algorithm, preferably in C#. I did find a generic algorithm here but I appear to have not implemented this correctly as the answers I am getting are 1000s of km adrift.
This is the Generic example
Lat/lon given radial and distance
A point {lat,lon} is a distance d out on the tc radial from point 1 if:
lat=asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
IF (cos(lat)=0)
lon=lon1 // endpoint a pole
ELSE
lon=mod(lon1-asin(sin(tc)*sin(d)/cos(lat))+pi,2*pi)-pi
ENDIF
And this is my C# translation.
// Extend a Point North/South by the specified distance
public static Point ExtendPoint(Point _pt, int _distance, int _bearing )
{
Decimal lat = 0.0;
Decimal lng = 0.0;
lat = Math.Asin(Math.Sin(_pt.Lat) * Math.Cos(_distance) + Math.Cos(_pt.Lat) *
Math.Sin(_distance) * Math.Cos(_bearing));
if (Math.Cos(lat) == 0)
{
lng = _pt.Lng; // endpoint a pole
}
else
{
lng = (
(_pt.Lng - Math.Asin(Math.Sin(_bearing) * Math.Sin(_distance) / Math.Cos(lat))
+ Math.PI) % (2 * Math.PI)) - Math.PI;
}
ret = new Point(lat,lng);
return ret;
}
I am calling this function with a bearing of 0 to calculate the new northerly position and a value of 180 to calculate the new southerly position.
Can anyone either see what I have done wrong or perhaps provide a known working algorithm?
I have a very similar piece of code. It got me very close results when compared to another implementation.
I think the problem with yours is that you are using "distance" as linear distance in meters instead of angular distance in radians.
/// <summary>
/// Calculates the end-point from a given source at a given range (meters) and bearing (degrees).
/// This methods uses simple geometry equations to calculate the end-point.
/// </summary>
/// <param name="source">Point of origin</param>
/// <param name="range">Range in meters</param>
/// <param name="bearing">Bearing in degrees</param>
/// <returns>End-point from the source given the desired range and bearing.</returns>
public static LatLonAlt CalculateDerivedPosition(LatLonAlt source, double range, double bearing)
{
double latA = source.Latitude * UnitConstants.DegreesToRadians;
double lonA = source.Longitude * UnitConstants.DegreesToRadians;
double angularDistance = range / GeospatialConstants.EarthRadius;
double trueCourse = bearing * UnitConstants.DegreesToRadians;
double lat = Math.Asin(
Math.Sin(latA) * Math.Cos(angularDistance) +
Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));
double dlon = Math.Atan2(
Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));
double lon = ((lonA + dlon + Math.PI) % UnitConstants.TwoPi) - Math.PI;
return new LatLonAlt(
lat * UnitConstants.RadiansToDegrees,
lon * UnitConstants.RadiansToDegrees,
source.Altitude);
}
Where
public const double EarthRadius = 6378137.0; // WGS-84 ellipsoid parameters
and LatLonAlt is in degrees/meters (conversion takes place internally).
Adjust as needed.
I assume you can figure out what the value for UnitConstants.DegreesToRadians is :)
For lazy people, (like me ;) ) a copy-paste solution, Erich Mirabal's version with very minor changes:
using System.Device.Location; // add reference to System.Device.dll
public static class GeoUtils
{
/// <summary>
/// Calculates the end-point from a given source at a given range (meters) and bearing (degrees).
/// This methods uses simple geometry equations to calculate the end-point.
/// </summary>
/// <param name="source">Point of origin</param>
/// <param name="range">Range in meters</param>
/// <param name="bearing">Bearing in degrees</param>
/// <returns>End-point from the source given the desired range and bearing.</returns>
public static GeoCoordinate CalculateDerivedPosition(this GeoCoordinate source, double range, double bearing)
{
var latA = source.Latitude * DegreesToRadians;
var lonA = source.Longitude * DegreesToRadians;
var angularDistance = range / EarthRadius;
var trueCourse = bearing * DegreesToRadians;
var lat = Math.Asin(
Math.Sin(latA) * Math.Cos(angularDistance) +
Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));
var dlon = Math.Atan2(
Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));
var lon = ((lonA + dlon + Math.PI) % (Math.PI*2)) - Math.PI;
return new GeoCoordinate(
lat * RadiansToDegrees,
lon * RadiansToDegrees,
source.Altitude);
}
private const double DegreesToRadians = Math.PI/180.0;
private const double RadiansToDegrees = 180.0/ Math.PI;
private const double EarthRadius = 6378137.0;
}
Usage:
[TestClass]
public class CalculateDerivedPositionUnitTest
{
[TestMethod]
public void OneDegreeSquareAtEquator()
{
var center = new GeoCoordinate(0, 0);
var radius = 111320;
var southBound = center.CalculateDerivedPosition(radius, -180);
var westBound = center.CalculateDerivedPosition(radius, -90);
var eastBound = center.CalculateDerivedPosition(radius, 90);
var northBound = center.CalculateDerivedPosition(radius, 0);
Console.Write($"leftBottom: {southBound.Latitude} , {westBound.Longitude} rightTop: {northBound.Latitude} , {eastBound.Longitude}");
}
}
I'm not sure if I'm missing something here, but I think the question could be rephrased as, "I have a lat/lon point, and I want to find the point x meters north and x meters south of that point."
If that's the question then you don't need to find a new longitude (which makes things simpler), you just need a new latitude. A degree of latitude is roughly 60 nautical miles long anywhere on Earth, and a nautical mile is 1,852 meters. So, for new latitudes x meters north and south:
north_lat = lat + x / (1852 * 60)
north_lat = min(north_lat, 90)
south_lat = lat - x / (1852 * 60)
south_lat = max(south_lat, -90)
This is not completely accurate because the Earth is not a perfect sphere with exactly 60 nautical miles between each degree of latitude. However, the other answers assume that lines of latitude are equidistant, so I'm assuming you don't care about that. If you're interested in how much error that might introduce, there is a nice table on Wikipedia that shows "Surface distance per 1° change in latitude" for different latitudes at this link:
http://en.wikipedia.org/wiki/Latitude#Degree_length
If you have a given latitude and longitude you can calculate the correct latitude and longitude of an x-km change in latitude like so:
new-lat = ((old-km-north + x-km-change)/40,075) * 360)
^ is the ratio of the ^ times the ratio of the circle
earth the change by 360 to get the total ratio
covers. covered in degrees.
The same can apply to longitude. If you have the total distance plus the change you can calculate the total degrees in a similar fashion.
new-long = ((old-km-east + x-km-change)/40,075) * 360)
^ is the ratio of the ^ times the ratio of the circle
earth the change by 360 to get the total ratio
covers. covered in degrees.
Again, these calculations should work, but I'm running off pure intuition here, but the logic does seem to hold true.
Edit: As pointed out by Skizz 40,075 needs to be adjusted to the circumference of the earth at any given latitude using 2.pi.r.cos(lat) or 40074.cos(lat)
There are problems with the two equations on Ed William's rather awesome site... but I didn't analyze them to see why.
A third equation that I found here seems to give proper results.
Here is the test case in php... the third equation is correct, the first two give wildly incorrect values for longitude.
<?php
$lon1 = -108.553412; $lat1 = 35.467155; $linDistance = .5; $bearing = 170;
$lon1 = deg2rad($lon1); $lat1 = deg2rad($lat1);
$distance = $linDistance/6371; // convert dist to angular distance in radians
$bearing = deg2rad($bearing);
echo "lon1: " . rad2deg($lon1) . " lat1: " . rad2deg($lat1) . "<br>\n";
// doesn't work
$lat2 = asin(sin($lat1) * cos($distance) + cos($lat1) * sin($distance) * cos($bearing) );
$dlon = atan2(sin($bearing) * sin($distance) * cos($lat1), cos($distance) - sin($lat1) * sin($lat2));
$lon2 = (($lon1 - $dlon + M_PI) % (2 * M_PI)) - M_PI; // normalise to -180...+180
echo "lon2: " . rad2deg($lon2) . " lat2: " . rad2deg($lat2) . "<br>\n";
// same results as above
$lat3 = asin( (sin($lat1) * cos($distance)) + (cos($lat1) * sin($distance) * cos($bearing)));
$lon3 = (($lon1 - (asin(sin($bearing) * sin($distance) / cos($lat3))) + M_PI) % (2 * M_PI)) - M_PI;
echo "lon3: " . rad2deg($lon3) . " lat3: " . rad2deg($lat3) . "<br>\n";
// gives correct answer... go figure
$lat4 = asin(sin($lat1) * cos($linDistance/6371) + cos($lat1) * sin($linDistance/6371) * cos($bearing) );
$lon4 = $lon1 + atan2( (sin($bearing) * sin($linDistance/6371) * cos($lat1) ), (cos($linDistance/6371) - sin($lat1) * sin($lat2)));
echo "lon4: " . rad2deg($lon4) . " lat4: " . rad2deg($lat4) . "<br>\n";
?>
Note I recieved by email from the author (Ed Williams) of the first two equations:
From my "implementation notes":
Note on the mod function. This appears to be implemented differently in
different languages, with differing conventions on whether the sign of the
result follows the sign of the divisor or the dividend. (We want the sign
to follow the divisor or be Euclidean. C's fmod and Java's % do not work.)
In this document, Mod(y,x) is the remainder on dividing y by x and always
lies in the range 0 <= mod < x. For instance: mod(2.3,2.)=0.3 and
mod(-2.3,2.)=1.7
If you have a floor function (int in Excel), that returns floor(x)=
"largest integer less than or equal to x" e.g. floor(-2.3)=-3 and
floor(2.3) =2
mod(y,x) = y - x*floor(y/x)
The following should work in the absence of a floor function- regardless of
whether "int" truncates or rounds downward:
mod=y - x * int(y/x)
if ( mod < 0) mod = mod + x
php is like fmod in C and does it "wrong" for my purposes.
It is more accurate if you first reproject it to UTM and then check the distance.
Hope this helps
For people who want a java version Eirch's code
/**
* move latlng point by rang and bearing
*
* #param latLng point
* #param range range in meters
* #param bearing bearing in degrees
* #return new LatLng
*/
public static LatLng moveLatLng(LatLng latLng, double range, double bearing) {
double EarthRadius = 6378137.0;
double DegreesToRadians = Math.PI / 180.0;
double RadiansToDegrees = 180.0 / Math.PI;
final double latA = latLng.latitude * DegreesToRadians;
final double lonA = latLng.longitude * DegreesToRadians;
final double angularDistance = range / EarthRadius;
final double trueCourse = bearing * DegreesToRadians;
final double lat = Math.asin(
Math.sin(latA) * Math.cos(angularDistance) +
Math.cos(latA) * Math.sin(angularDistance) * Math.cos(trueCourse));
final double dlon = Math.atan2(
Math.sin(trueCourse) * Math.sin(angularDistance) * Math.cos(latA),
Math.cos(angularDistance) - Math.sin(latA) * Math.sin(lat));
final double lon = ((lonA + dlon + Math.PI) % (Math.PI * 2)) - Math.PI;
return new LatLng(lat * RadiansToDegrees, lon * RadiansToDegrees);
}