OpenLayers: Get distance from gpx - javascript

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.

Related

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

How to convert exact Latitude and Longitude coordinates to X,Y coordinates

I have a world map drawn in a canvas using Java script. How can I convert the exact latitude,longitude coordinates of any place into X,Y coordinates so that I can project those converted X,Y coordinates on my Canvas Map?
I have tried different solutions provided earlier, but they are not pointing to exact X,Y coordinates on my Canvas Map. Also I have tried using basic conversion formulas, but they haven't been useful as well.
For example,
var y = ((-1 * lat) + 90) * (MAP_HEIGHT / 180);
var x = (lon + 180) * (MAP_WIDTH / 360);
OR
function plot_point(lat, lng) {
// longitude_shift = number of pixels your map's prime meridian is off-center.
// Mercator projection
// longitude: just scale and shift
x = (map_width * (180 + lng) / 360) % map_width + longitude_shift;
// latitude: using the Mercator projection
lat = lat * Math.PI / 180; // convert from degrees to radians
y = Math.log(Math.tan((lat/2) + (Math.PI/4)));
y = (map_height / 2) - (map_width * y / (2 * Math.PI)) + y_pos;
I am using the following map : Map
P.S. If anybody can provide a Java script code, that would be very helpful.
EDIT Since I cannot obtain exact coordinates, thanks to explanation of
#Aki Suihkonen, please suggest a method so that I can get X,Y coordinates nearest to its true location in the map. Thanks in advance.

Lat/Long equation in 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

Google Maps - How to get the distance between two point in metre?

I have these coordinate :
(45.463688, 9.18814)
(46.0438317, 9.75936230000002)
and I need (trought Google API V3, I think) to get the distance between those 2 points in metre. How can I do it?
If you're looking to use the v3 google maps API, here is a function to use:
Note: you must add &libraries=geometry to your script source
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry"></script>
<script>
var p1 = new google.maps.LatLng(45.463688, 9.18814);
var p2 = new google.maps.LatLng(46.0438317, 9.75936230000002);
alert(calcDistance(p1, p2));
//calculates distance between two points in km's
function calcDistance(p1, p2) {
return (google.maps.geometry.spherical.computeDistanceBetween(p1, p2) / 1000).toFixed(2);
}
</script>
I think you could do without any specific API, and calculate distance with plain Javascript:
This site has good info about geographical calculations and Javascript sample for distance calculation.
Ok, quick glance at Google API page and it seems, you could do it by:
Call DirectionsService().route() to get DirectionsResult with routes
For one or each route go through its legs property and calculate sum of distances
http://www.csgnetwork.com/gpsdistcalc.html
Has nothing to do with coding btw
EDIT
if you're looking for some code
Calculate distance between two points in google maps V3
This is primarily done with math outside of the google api, so you shouldn't need to use the API for anything other than finding the correct coordinates.
Knowing that, here's a link to a previously answered question relating to Javascript.
Calculate distance between 2 GPS coordinates
Try this
CLLocationCoordinate2D coord1;
coord1.latitude = 45.463688;
coord1.longitude = 9.18814;
CLLocation *loc1 = [[[CLLocation alloc] initWithLatitude:coord1.latitude longitude:coord1.longitude] autorelease];
CLLocationCoordinate2D coord2;
coord2.latitude = 46.0438317;
coord2.longitude = 9.75936230000002;
CLLocation *loc2 = [[[CLLocation alloc] initWithLatitude:46.0438317 longitude:9.75936230000002] autorelease];
CLLocationDistance d1 = [loc1 distanceFromLocation:loc2];
Try this:
const const toRadians = (val) => {
return val * Math.PI / 180;
}
const toDegrees = (val) => {
return val * 180 / Math.PI;
}
// Calculate a point winthin a circle
// circle ={center:LatLong, radius: number} // in metres
const pointInsideCircle = (point, circle) => {
let center = circle.center;
let distance = distanceBetween(point, center);
//alert(distance);
return distance < circle.radius;
};
const distanceBetween = (point1, point2) => {
//debugger;
var R = 6371e3; // metres
var φ1 = toRadians(point1.latitude);
var φ2 = toRadians(point2.latitude);
var Δφ = toRadians(point2.latitude - point1.latitude);
var Δλ = toRadians(point2.longitude - point1.longitude);
var a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
References: http://www.movable-type.co.uk/scripts/latlong.html
Are you referring to distance as in length of the entire path or you want to know only the displacement (straight line distance)? I see no one is pointing the difference between distance and displacement here. For distance calculate each route point given by JSON/XML data, as for displacement there is a built-in solution using Spherical class.
Are you referring to distance as in length of the entire path or you want to know only the displacement (straight line distance)? I see no one is pointing the difference between distance and displacement here. For distance calculate each route point given by JSON/XML data, as for displacement there is a built-in solution using Spherical class. The idea is if your are referring to distance then you just use the computeDistanceBetween on each path point and concatenate it.
//calculates distance between two points in km's
function calcDistance(p1, p2) {
return (google.maps.geometry.spherical.computeDistanceBetween(p1, p2) / 1000).toFixed(2);
}

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