Lat/Long equation in Javascript - javascript

I am trying to find an equation for finding the lat/long point between two lat/long points in Javascript. It would work something like this.
getMiddle(lat1, lng1, lat2, lng2) <= would return [lat3, lat3] halfway distance wise (going around the earth obviously).
I found this:
Link
Date: 10/11/2001 at 11:41:08
From: Doctor Rick
Subject: Re: Determining lat and long of a point between two given
points
Hi, Chuck.
This will probably be a little more complicated than you think. The
easiest way for me to do it is to think in terms of vectors. Some of
the items in our Archives on the topic of latitude and longitude use
the vector approach, so you can see them for background. For example:
Distance Between Two Points on the Earth
Link
Let's call the two points A and B, and choose a rectangular coordinate
system in which the equator is in the x-y plane and the longitude of
point A is in the x-z plane. Let lat1 be the latitude of A, let lat2
be the latitude of B, and let dlat be the longitude of B minus the
longitude of A. Finally, use distance units such that the radius of
the earth is 1. Then the vectors from the center of the earth to A and
B are
A = (cos(lat1), 0, sin(lat1)) B = (cos(lat2)*cos(dlon),
cos(lat2)*sin(dlon), sin(lat2))
Point C, the midpoint of the shortest line between A and B, lies along
the sum of vectors A and B. (This works because A and B have the same
length, so the sum of the vectors is the diagonal of a rhombus, and
this diagonal bisects the angle.)
A+B = (cos(lat1)+cos(lat2)*cos(dlon),
cos(lat2)*sin(dlon),
sin(lat1)+sin(lat2))
To get the actual vector C, we need to scale this vector to length R
so it ends at the surface of the earth. Thus we have to divide it by
|A+B|, that is, the length of vector A+B. That would get pretty messy.
But we can find the latitude lat3 and longitude difference (lon3-lon1)
by looking at ratios of the coordinates of A+B, and these ratios are
the same whether we scale the vector or not. To see this, look back at
the formula for vector B. Knowing that vector, we can recover lat2 and
dlon:
dlon = tan^-1(B_y/B_x) lat2 = tan^-1(B_z/sqrt(B_x^2+B_y^2))
Here, B_x, B_y, and B_z are the x, y, and z coordinates of vector B.
We can do the same thing with vector A+B to find the latitude and
longitude of point C:
dlon3 = tan^-1(cos(lat2)*sin(dlon)/
(cos(lat1)+cos(lat2)*cos(dlon))) lat3 = tan^-1((sin(lat1)+sin(lat2))/
sqrt((cos(lat1)+cos(lat2)*cos(dlon))^2+
(cos(lat2)*sin(dlon))^2))
That's the formula you seek. Since both formulas involve division, we
must consider the special cases. The longitude calculation fails when
C_x = 0, that is, when C is 90 degrees away from A in longitude, so
dlon3 will be +90 or -90; the sign depends on the sign of dlon. The
latitude calculation fails when C_x and C_y are both zero, thus we
know that in this case, lat3 = 0. A complete algorithm will check for
these cases, but they won't occur if you're interested only in the
continental US.
When I plug in the latitudes and longitudes for LA and NYC, I get:
LA 34.122222 118.4111111 NYC 40.66972222 73.94388889 midpt 39.54707861
97.201534
I hope this is helpful to you.
Doctor Rick, The Math Forum Link
Which I believe has the answer but not as Javascript.
This is what I am working with:
I have spent some time creating map point and determining distance between them, but to find a midway point between them has been difficult for me. Converting equations I have found so far has been unsuccessful.
Once I can find the midpoint I want to use recursion + (how many points I need between two points based on distance) to build properly spaced dotted lines.
Any help on this piece would be greatly appreciated.

Answer in python: http://code.activestate.com/recipes/577713-midpoint-of-two-gps-points/
Convert to js
Profit
Additionally: For those wanting to go straight to profit (yes I know I patched Math. Borrowed shamelessly from here: https://nickthecoder.wordpress.com/2012/04/15/radian-and-degree-conversion-in-javascript/)
getMidpoint: function(lat1, lng1, lat2, lng2) {
Math.degrees = function(rad) {
return rad * (180 / Math.PI);
}
Math.radians = function(deg) {
return deg * (Math.PI / 180);
}
lat1 = Math.radians(lat1);
lng1 = Math.radians(lng1);
lat2 = Math.radians(lat2);
lng = Math.radians(lng2);
bx = Math.cos(lat2) * Math.cos(lng - lng1)
by = Math.cos(lat2) * Math.sin(lng - lng1)
lat3 = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + bx) * (Math.cos(lat1) + bx) + Math.pow(by, 2)));
lon3 = lng1 + Math.atan2(by, Math.cos(lat1) + bx);
return [Math.round(Math.degrees(lat3), 5), Math.round(Math.degrees(lon3), 5)]
}

I think this is the formula you're looking for:
This is the half-way point along a great circle path between the two points.
Formula: Bx = cos φ2 ⋅ cos Δλ
By = cos φ2 ⋅ sin Δλ
φm = atan2( sin φ1 + sin φ2, √(cos φ1 + Bx)² + By² )
λm = λ1 + atan2(By, cos(φ1)+Bx)
JavaScript:
(all angles
in radians)
var Bx = Math.cos(φ2) * Math.cos(λ2-λ1);
var By = Math.cos(φ2) * Math.sin(λ2-λ1);
var φ3 = Math.atan2(Math.sin(φ1) + Math.sin(φ2),
Math.sqrt( (Math.cos(φ1)+Bx)*(Math.cos(φ1)+Bx) + By*By ) );
var λ3 = λ1 + Math.atan2(By, Math.cos(φ1) + Bx);
source: http://www.movable-type.co.uk/scripts/latlong.html

Related

How to create a square polygon with knowing single coordinate, angle and distance?

How can I create a polygon(square) with only knowing coordinate of single point with distance of each side (3km) and angle which is 90 degree using javascript. if I will have the coordinate of all 4 point then i can draw a rectangle.. Any suggestion will be of great help.
Mathematically, you cannot draw a square on a sphere, but we'll assume that:
the distance is small enough compared to the Earth that it doesn't matter and we can approximate a flat surface
it's not in the polar regions, as that messes with the maths.
From what I understood of your question, your start with Point 1 and the angle alpha which is the direction to the north (heading). If you define your angle differently, you'll have to adapt.
So we start with the following (I put the angle at 30 so it's more visible):
The first point is defined by lat1,lng1
var alpha = 30;
var dist=3;
var Rearth=6371.0
let cosa=Math.cos(alpha* Math.PI/180);
let sina=Math.sin(alpha* Math.PI/180);
let dlng=Rearth*Math.cos(lat1* Math.PI/180)
(dlng is the correction factor as the longitude dimensions gets smaller as the latitude goes from the equator to the poles. As the square is small, we can assume that the difference of latitude between the sides of the square doesn't really matter)
and to get to point 2 (as the angle between the centre of the earth and the side of the square is very small, there's no need to add a asin() function, as beta ~ sin(beta) in radians )
let lat2 = lat1 + (dist*cosa/Rearth*180/Math.PI);
let lng2 = lng1 + (dist*sina/(dlng)*180/Math.PI);
then we can find points 3 and 4 in a similar way:
let lat3 = lat2 - (dist*sina/Rearth*180/Math.PI);
let lng3 = lng2 + (dist*cosa/(dlng)*180/Math.PI);
let lat4=lat1 - dist*sina/Rearth*180/Math.PI;
let lng4=lng1 + dist*cosa /(dlng)*180/Math.PI;
and then you can use the lat,lng pairs to create a polygon:
var latlngs = [[lat1, lng1],[lat2, lng2],[lat3,lng3],[lat43,lng43],[lat4,lng4]];
L.polygon(latlngs, {color: 'blue'}).addTo(map);
For example, with dist=16km and alpha=45, you can draw a square that fits over the boundaries of Washington DC:

Converting longitude latitude to tile coordinates

I want to get a map tile from a server by typing in the longitude and latitude.
Since map tiles are arranged like a grid, i need to convert my longitude and latitude to an x and y position.
The algorithm is explained here: http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#ECMAScript_.28JavaScript.2FActionScript.2C_etc..29
I correctly implemented this algorithm, but unfortunately these are not the correct coordinates for the tileservers.
As you can see here http://tools.geofabrik.de/map/#12/52.5106/13.3989&type=Geofabrik_Standard&grid=1
the correct tilecoordinates for Berlin are (2200, 1343) on zoomlevel 12, while the algorithm gives me (2645, 1894).
Where is the mistake in the algorithm or my misunderstanding of how this conversion works?
Tilesname WebCalc seems to use the same code as presented on the slippy map tilenames wiki page and outputs the same tile names as the Geofabrik tool. So the algorithm must be correct and the error seems to be in your implementation which you didn't show us.
Oh, I'm pretty sure you just mixed up lat and lon. If I enter the coordinates in the wrong order into Tilesname WebCalc then it also returns the "wrong" tile names given in your question. So your code is fine, you just call it the wrong way.
The following code is takes lng, lat & zoom and return X & Y values and Z is the zoom. you need to put it in url and voila you get the tile
const EARTH_RADIUS = 6378137;
const MAX_LATITUDE = 85.0511287798;
function project (lat, lng)
{
var d = Math.PI / 180,
max = MAX_LATITUDE,
lat = Math.max(Math.min(max, lat), -max),
sin = Math.sin(lat * d);
return {x: EARTH_RADIUS * lng * d,
y: EARTH_RADIUS * Math.log((1 + sin) / (1 - sin)) / 2
};
}
function zoomScale (zoom)
{
return 256 * Math.pow(2, zoom);
}
function transform (point, scale) {
scale = scale || 1;
point.x = scale * (2.495320233665337e-8 * point.x + 0.5);
point.y = scale * (-2.495320233665337e-8 * point.y + 0.5);
return point;
}
var point1 = project (lat1, lng1);
var scaledZoom = zoomScale (zoom);
point1 = transform (point1, scaledZoom);
point1 is what you need the X & Y

Scramble latitude longitude coordinates within 100m radius with Javascript

Title says it all, I need to scramble lat/lon coordinates within 100m radius for privacy reasons. I'm just horrible at maths and can't figure out how to convert 100m to lat/lon...
Eg I would have a location like:
lat: 52.5037086
lng: 13.434223100000054
Need to scramble this within 100m radius randomly, ie the furthest the generated coordinates can be from the original coordinates in any direction is 100m.
I've seen this formula around:
d = acos( sin(φ1)⋅sin(φ2) + cos(φ1)⋅cos(φ2)⋅cos(Δλ) ) ⋅ R
where:
φ = latitude, λ = longitude
R = radius of earth
d = distance between the points
No idea how to accomplish this in JavaScript, though. These "points" are markers within a Google Map if it makes a difference.
To be honest, it doesn't even need to be a circle, just random location within 100m x 100m square would work as well.
At such small extents, we can work with a linear approximation of the problem and a spherical earth model.
Consider, you are at a position (lat, long). Then, increasing lat by 1° results in a distance from the original point of d_lat = Pi * R * 1°/180° (simple perimeter of a circle).
Similarly, increasing long by 1° results in a distance of d_long = cos(lat) * Pi * R * 1°/180°.
Then, you can calculate the maximum change of latitude and longitude:
maxChangeLatitude = 100 m / d_lat
maxChangeLongitude = 100 m / d_long
Find a random point in this square and you have your point:
newLat = lat + (2 * Math.random() - 1) * maxChangeLatitude;
newLong = long + (2 * Math.random() - 1) * maxChangeLongitude;

OpenLayers: Get distance from gpx

I have a gpx file. I'm displaying it on top of OSM using OpenLayers and this example.
My requirement is to get distance of the route. How can i achieve that?
Please help,
Thanks.
Basically, A GPX is an XML file defining a set of Track Segment which holds a list of Track Points which are logically connected in order.
<trkseg>
<trkpt lat='float' lon='float'/>
<trkpt lat='float' lon='float'/>
<trkpt lat='float' lon='float'/>
...
</trkseg>
All you need is to compute All the track segment length using distance from point to point (the points hold the lat and lon)
The distance from point to point will be compute using the following formula :
var radius = 6378137.0 ; // earth radius in meter
var DE2RA = 0.01745329252; // degre to radian conversion
// return the distance between (lat1,lon1) and (lat2,lon2) in meter.
GCDistance= function (lat1, lon1, lat2, lon2) {
if (lat1 == lat2 && lon1 == lon2) return 0;
lat1 *= DE2RA;
lon1 *= DE2RA;
lat2 *= DE2RA;
lon2 *= DE2RA;
var d = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2);
return (radius * Math.acos(d));
};
Be aware of the fact that Track Segment are NOT logically connected.
Parsing the GPX using DOM is straight forward.
this code is extract from a lib which in use for years.
here a sample of where I use it.
Hope this help.
G.

googlemaps get bounding box around marker

In googlemaps api v2 I have one marker on map and i need to calculate a bounding box around this one. How would I get a bonding box of 5 by 5 kilometers of which this marker is the center?
I'm not sure that such a functionality is provided by google map, but math will help you to survive ;) Calculate distance, bearing and more between Latitude/Longitude points is a great reference to different calculations with geographic data. Open that page, and go to "Destination point given distance and bearing from start point" part, there are formulas, as well as online calculator, so you can check them (as well as you can see points on the map). Formula has few parameters:
(lat1,lng1) - your point (marker coordinates)
d - distance (in your case it would be 2.5km)
brng - angle..
to find bound you need to find coordinates of south, north, east and west rectangle sides, so everything you will change in parameters is angle, and in your case it will be 0, 90, 180 and 270 grads. Formulas:
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) +
Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng) );
var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1),
Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));
Well, specifying angle = 0 you find north, PI/2 - east, PI - south, 3*PI/2 - west (angles should be passed in radians).
R = earth’s radius (mean radius = 6,371km)
ADD-ON: just looked at the source code of that page, because when I enter in online form bearing = 0, distance = 2 then I see map with two points and according to the map scale the distance between them is really 2km. Well, you can use this library under a simple attribution license, without any warranty express or implied, just include it
<script src="http://www.movable-type.co.uk/scripts/latlon.js"></script>
Function you need is:
/**
* Returns the destination point from this point having travelled the given distance (in km) on the
* given initial bearing (bearing may vary before destination is reached)
*
* see http://williams.best.vwh.net/avform.htm#LL
*
* #param {Number} brng: Initial bearing in degrees
* #param {Number} dist: Distance in km
* #returns {LatLon} Destination point
*/
LatLon.prototype.destinationPoint = function(brng, dist) {
dist = typeof(dist)=='number' ? dist : typeof(dist)=='string' && dist.trim()!='' ? +dist : NaN;
dist = dist/this._radius; // convert dist to angular distance in radians
brng = brng.toRad(); //
var lat1 = this._lat.toRad(), lon1 = this._lon.toRad();
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist) +
Math.cos(lat1)*Math.sin(dist)*Math.cos(brng) );
var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist)*Math.cos(lat1),
Math.cos(dist)-Math.sin(lat1)*Math.sin(lat2));
lon2 = (lon2+3*Math.PI)%(2*Math.PI) - Math.PI; // normalise to -180...+180
return new LatLon(lat2.toDeg(), lon2.toDeg());
}
and when I enter in online form bearing = 0, distance = 2, this method is executed with arguments latLonCalc.destinationPoint( 0, "2" );
try it, otherwise give me input parameters so I could check what's wrong
UPDATE2 that library works with grads,and converts them to radians for calculations and then back to grads. Just performed simple test:
var latLonCalc = new new LatLon( 25, 45 );
var point = latLonCalc.destinationPoint( 0, "2" );
console.info( point );
// prints 25°01′05″N, 045°00′00″E { _lat=25.01798643211838, _lon=45.00000000000005, _radius=6371}
so the distance between entry point and final destination is a bit more than 1 minute;
earth = 2 * PI * 6371; // 40 009.98km
=> 40 009.98km / 360grad =~111.14
=> 111,14 / 60 = 1.85 (km/minute) ~2km
it was round calculation, which tells me that final point is not far away then entry point, and distance should be 2km ;)
Not the real one you required but check this article
http://www.svennerberg.com/2008/11/bounding-box-in-google-maps/

Categories