I need to retrieve a destination's coordinates using the google maps api directions service. I already have the starting point coordinates, however instead of specifying an ending point in coordinates, I wish to retrieve the coordinates by specifying a distance (in km).
So I guess my question is the following: is it possible to retrieve the destination latlong coordinates (based/calculated on the road's distance and not directional/straight line) by specifying a distance (amount in km) with the directions service or perhaps any alternative way?
I have an image illustration, however unfortunately am unable to attach to this question as I do not have enough reputation. If my question is unclear in any way, or you wish to see the illustration then please contact me and I'll send it off.
I don't think you can do this as the request parameters say that origin and destination parameters are required.
I beliave it will help someone.
There is a method to get coordinates in the google maps library:
google.maps.geometry.spherical.computeOffset(fromCoordinates, distanceInMeters, headingInDegrees)
I believe you are correct. There doesn't seem to be any current method in the api which would allow you to do the following.
Instead I looped through the coordinates returned from the directions service call, and used a function to calculate the distance between coordinates. However even this was not accurate enough as the coordinates returned also seemed to be aggregated and doesn't return an accurate value/distance when calculating the distances between each coordinate as they are aggregated and therefore each coordinate is not necessary along the road.
To work around the above issue, I ended up adding a click event, and plotted the coordinates along the road myself and then stored them in a local json file which I cache and call using an xmlhttprequest.
Fortunately, for my situation I only need to calculate the distance between point A & B on one individual road, so my alternative won't work in cases when you're using multiple or generic roads/locations. You could instead use the first method described, given that you're happy to live with the aggregated data and an in-accurate calculation.
Below are the functions used to calculate the distances between coordinates and then also the final calculation to find the point & coordinates between the final two points. Please note this code relies on and uses jQuery methods.
1. Calculate distance (in meters) between two coordinates
function pointDistance( begin, end )
{
var begin = { lat: begin[0], long: begin[1] },
end = { lat: end[0], long: end[1] };
// General calculations
var earthRadius = 6371, //km
distanceLat = (end.lat - begin.lat).toRad(),
distanceLong = (end.long - begin.long).toRad();
// Convert lats to radiants
begin.lat = begin.lat.toRad();
end.lat = end.lat.toRad();
// Calculation
var a = Math.sin(distanceLat / 2) * Math.sin(distanceLat / 2) +
Math.sin(distanceLong / 2) * Math.sin(distanceLong / 2) * Math.cos(begin.lat) * Math.cos(end.lat);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var distance = (earthRadius * c) - 0.000536;
return (distance * 1000);
}
2. Fetch coordinate of final A-B coordinate (based on percentage remaining). The 'matrix' variable is a json array of coordinates.
function getCoordinates( totalDistance )
{
var lastPoint = { lat: null, long: null },
total = parseFloat(0),
position = { start: null, end: null, distance: 0 };
$(matrix).each(function()
{
if ( lastPoint.lat == null )
{
lastPoint = { lat: this[0], long: this[1] };
return;
}
var distance = pointDistance([lastPoint.lat, lastPoint.long], [this[0], this[1]]);
total = total + distance;
if ( (total / 1000) >= totalDistance )
{
position.start = new google.maps.LatLng(lastPoint.lat, lastPoint.long);
position.end = new google.maps.LatLng(this[0], this[1]);
position.distance = total;
return false;
}
lastPoint = { lat: this[0], long: this[1] };
});
return position;
}
3. Convert numeric degrees to radians
if ( typeof(Number.prototype.toRad) === 'undefined' ) {
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
}
Hope the following helps any one with the same or simular problem. I haven't investigated this as I've had no need to, but, perhaps if you're dealing with google's paid services, they don't aggregate the data returned by the call?
Related
I'm trying to calculate distances between two geographic points using MySQL, but I think ST_Distance_Sphere function is incorrect or is not using Haversine formula.
To describe this problem, I'll use these two points and this Earth radius:
Point A: 41.8902142, 12.4900422
Point B: 48.8583736, 2.2922926
Earth radius: 6378000
I've made this script in JavaScript that uses Haversine formula:
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
const sin2 = (x) => {
return Math.pow( Math.sin(x), 2 );
}
function computeDistanceBetween(x1, y1, x2, y2, rad = 6378000) {
const x_diff = x2 - x1;
const y_diff = y2 - y1;
let a = sin2(x_diff.toRad() / 2) + Math.cos(x1.toRad()) * Math.cos(x2.toRad()) * sin2(y_diff.toRad() / 2);
a = 2 * rad * Math.asin(Math.sqrt(a))
return a;
}
console.log(
computeDistanceBetween(
41.8902142, 12.4900422,
48.8583736, 2.2922926
) / 1000 // Convert to Km
);
This script gives me this result: 1110.6415064d524447, if I check this in Google Maps, the result is approximately the same (1,109.43 km)
Now, MySQL is the problem, I'm trying to do the same with exactly that two points, but the result is very different:
SELECT
ST_Distance_Sphere(
POINT(41.8902142, 12.4900422), POINT(48.8583736, 2.2922926), 6378000
) / 1000 as distances
It gives me 1370.65792958018 as result, there are 260 Km of difference, so the result is very wrong, note that I'm using exactly the same points and the same radius in both cases, so MySQL is wrong or something? How can I get the same result as in JavaScript, but using spatial functions in MySQL? Thanks a lot for your help
Ok, this was very tricky, the function POINT receives first the longitude parameter and after receives the latitude parameter, so, the correct query should be this:
SELECT ST_Distance_Sphere(POINT(12.4900422, 41.8902142),
POINT( 2.2922926, 48.8583736),
6378000 ) /1000 as distances
So this returns me 1110.641506452445 which is correct result.
New to GeoTools and GIS and I am trying to calculate distance between Mumbai and Durban using GeoTools library. I am getting close to accurate results for small distances but when i go for bigger ones,the calculation is way too offcourse by 2000 km, i dont completely understand the CRS system .Below is my Code to calculate the distance between Mumbai and Durban
Coordinate source = new Coordinate(19.0760, 72.8777); ///Mumbai Lat Long
Coordinate destination1 = new Coordinate(-29.883333, 31.049999); //Durban Lat Long
GeometryFactory geometryFactory = new GeometryFactory();
Geometry point1 = geometryFactory.createPoint(source);
Geometry point2 = geometryFactory.createPoint(destination1);
CoordinateReferenceSystem auto = auto = CRS.decode("AUTO:42001,13.45,52.3");
MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);
Geometry g3 = JTS.transform(point1, transform);
Geometry g4 = JTS.transform(point2, transform);
double distance = g3.distance(g4);
This is what happens when you copy code blindly from stackexchange questions without reading the question it was based on which explains why.
All the times I've answered that question (and posted code like that) the questioner is trying to use lat/lon coordinates in degrees to measure a short distance in metres. The trick shown in your question creates an automatic UTM projection centred on the position specified after the "AUTO:42001," bit (in your case 52N 13E) - this needs to be the centre of the area you are interested in, so in your case those values are probably wrong anyway.
But you aren't interested in a small region Mumbai to Durban is a significant way around the Earth so you need to allow for the curvature of the Earth's surface. Also you aren't trying to do something difficult for which JTS is the only source of process (e.g buffering). In this case you should use the GeodeticCalculator which takes the shape of the Earth into account using the library from C. F. F. Karney, Algorithms for geodesics, J. Geodesy 87, 43–55 (2013).
Anyway enough explanation that no one will read in the future, here's the code:
public static void main(String[] args) {
DefaultGeographicCRS crs = DefaultGeographicCRS.WGS84;
if (args.length != 4) {
System.err.println("Need 4 numbers lat_1 lon_1 lat_2 lon_2");
return;
}
GeometryFactory geomFactory = new GeometryFactory();
Point[] points = new Point[2];
for (int i = 0, k = 0; i < 2; i++, k += 2) {
double x = Double.valueOf(args[k]);
double y = Double.valueOf(args[k + 1]);
if (CRS.getAxisOrder(crs).equals(AxisOrder.NORTH_EAST)) {
System.out.println("working with a lat/lon crs");
points[i] = geomFactory.createPoint(new Coordinate(x, y));
} else {
System.out.println("working with a lon/lat crs");
points[i] = geomFactory.createPoint(new Coordinate(y, x));
}
}
double distance = 0.0;
GeodeticCalculator calc = new GeodeticCalculator(crs);
calc.setStartingGeographicPoint(points[0].getX(), points[0].getY());
calc.setDestinationGeographicPoint(points[1].getX(), points[1].getY());
distance = calc.getOrthodromicDistance();
double bearing = calc.getAzimuth();
Quantity<Length> dist = Quantities.getQuantity(distance, SI.METRE);
System.out.println(dist.to(MetricPrefix.KILO(SI.METRE)).getValue() + " Km");
System.out.println(dist.to(USCustomary.MILE).getValue() + " miles");
System.out.println("Bearing " + bearing + " degrees");
}
Giving:
working with a lon/lat crs
POINT (72.8777 19.076)
POINT (31.049999 -29.883333)
7032.866960793305 Km
4370.020928274692 miles
Bearing -139.53428618565218 degrees
I am trying to get smooth route for below route path using road API in Roads Inspector but not getting smooth route.Google road api failing to provide smooth route.Some portion of route is not smooth with actual road route e.g at turns, at bridges etc. Please have look for below route path and provide solution to get smooth route/more accurate route along actual road.
Points:
42.04144333333333,-88.060575|42.04123666666667,-88.06014333333333|42.04119166666667,-88.06017166666666|42.040835,-88.05990166666666|42.03982666666667,-88.05242333333334|42.03903666666667,-88.04572333333333|42.03903833333333,-88.04572|42.038495,-88.04141833333334|42.03774666666666,-88.03593833333333|42.037683333333334,-88.03549|42.034861666666664,-88.03204166666667|42.02808,-88.031215|42.02045666666667,-88.03131166666667|42.012881666666665,-88.02988833333333|42.00522333333333,-88.02747666666667|41.997353333333336,-88.02500333333333|41.98961333333333,-88.02349333333333|41.982191666666665,-88.02351333333333|41.97412833333333,-88.02447333333333|41.96599,-88.02588166666666|41.95825833333333,-88.027075|41.952605,-88.03345|41.945281666666666,-88.0377|41.937595,-88.03779333333334|41.92935,-88.037845|41.92084333333333,-88.03799166666667|41.91231,-88.038075|41.90379,-88.038145|41.89564,-88.03784166666667|41.887255,-88.036495|41.87881,-88.03291666666667|41.87096833333333,-88.03694333333334|41.863101666666665,-88.04085166666667|41.85484833333334,-88.04049166666667|41.848978333333335,-88.03315166666667|41.842145,-88.02940833333334|41.83407,-88.02922|41.826135,-88.029025|41.820256666666666,-88.02674333333333|41.813515,-88.02884833333333|41.80965333333333,-88.03722166666667|41.810065,-88.04824833333333|41.8104,-88.06018333333333|41.81016666666667,-88.07216833333334|41.80704166666666,-88.08223833333334|41.80573666666667,-88.09275|41.80591166666667,-88.10409166666666|41.80608,-88.11518333333333|41.80625166666667,-88.12632166666667|41.806415,-88.13737333333333|41.80649666666667,-88.14849166666667|41.80653,-88.15959333333333|41.80652666666667,-88.17042666666667|41.805715,-88.181295|41.80482833333333,-88.19194333333333|41.803918333333336,-88.202765|41.80304666666667,-88.212815|41.802146666666665,-88.22354833333333|41.801383333333334,-88.23485666666667|41.80068833333333,-88.24686666666666|41.8,-88.25845333333334|41.799368333333334,-88.26976833333333|41.798743333333334,-88.28041666666667|41.80003166666667,-88.28312833333334|41.795566666666666,-88.28211666666667|41.79022,-88.28205833333334|41.785465,-88.28198|41.784135,-88.28193833333333|41.782473333333336,-88.283865|41.78230833333333,-88.28874666666667|41.782226666666666,-88.288225|41.781863333333334,-88.287305|41.78176833333333,-88.28751333333334|41.78176833333333,-88.28751333333334
points in the "inspector"
Your points don't look like the full output of a GPS tracker (the use case for which this API is designed), and thus you have stretches that are too far apart. Please increase the resolution of your GPS recording to get better output.
Google maps seems not to snap far points,
(if the distance between is longer than 300m - 400m).
As a solution I added some fake points between points that too far apart.
And now Google Maps snapping my route correctly.
List<LatLon> extendedPointsList = new List<LatLon>();
var lastLatLon = OrigionalRoute[0];
extendedPointsList.Add(lastLatLon);
indexesBeforeAddingPoints.Add(0);
for (int i = 1; i < OrigionalRoute.Count; i++)
{
var currentLatlon = OrigionalRoute[i];
double estimatedDistance =
getEstimatedDistanceBetweenPoints(currentLatlon, lastLatLon);
//estimated 400 meters
if (estimatedDistance > 0.004)
{
//estimated 340 meters
int countOfPoints = (int)Math.Round(estimatedDistance / 0.0034);
if (countOfPoints > 1)
{
var latDiff = (currentLatlon.Lat - lastLatLon.Lat) / countOfPoints;
var lonDiff = (currentLatlon.Lon - lastLatLon.Lon) / countOfPoints;
for (int j = 1; j < countOfPoints; j++)
{
var aveLat = lastLatLon.Lat + (latDiff * j);
var aveLon = lastLatLon.Lon + (lonDiff * j);
indexesBeforeAddingPoints.Add(i - 1);
extendedPointsList.Add(new LatLon(aveLat, aveLon));
}
}
}
indexesBeforeAddingPoints.Add(i);
extendedPointsList.Add(currentLatlon);
lastLatLon = currentLatlon;
}
OrigionalRoute = extendedPointsList;
The method to estimate distance (I ignored earth's sphere and projection).
private static double getEstimatedDistanceBetweenPoints(LatLon pointA, LatLon pointB)
{
return Math.Sqrt(Math.Pow((pointA.Lat - pointB.Lat), 2) + Math.Pow((pointA.Lon - pointB.Lon), 2));
}
I'm experimenting with System.Data.Spatial.DbGeography, that I want to use to determine the distance from one coordinate to another (going to be stored in SQL server).
My coordinates are in lat/long, and I got them from Bing Maps (I've tried with coordinates from Google Maps too, with the same result).
var osloCentralStation = DbGeography.FromText("POINT(59.9109 10.7523)", 4326);
var drammen = DbGeography.FromText("POINT(59.7378 10.2050)", 4326);
Console.WriteLine("Distance: {0}km", osloCentralStation.Distance(drammen) / 1000);
Returns:
Distance: 63,4340839088124km
The returned distance is approximately double what it should be.
https://maps.google.com/maps?saddr=59.9109+10.7523&daddr=59.7378+10.2050
Does anybody have any idea as to what's going on?
You're not declaring the element in WKT in the right order.
WKT should be in your case:
POINT(10.2050 59.7378)
See OGC standard here:
http://msdn.microsoft.com/en-us/library/bb933834.aspx
http://en.wikipedia.org/wiki/Well-known_text
And then it has to be declared like:
POINT(LONGITUDE LATITUDE)
Also keep in mind that it won't be the driving distance but the distance by air.
It turns out that lat/long are given as long/lat when creating new DbGeography objects.
I've written a little helper method so that I don't get it wrong again in the future:
private static DbGeography CreateDbGeography(double latitude, double longitude, int srid = 0)
{
var text = string.Format(CultureInfo.InvariantCulture.NumberFormat, "POINT({0} {1})", longitude, latitude);
if (srid > 0)
{
return DbGeography.FromText(text, srid);
}
return DbGeography.FromText(text);
}
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Calculate “as the crow flies” distance php
I am trying to develop a GoogleMaps page where I can get the user location and show custom marker points from an XML file that fells within the calculated area around the user.
To make things more clear :
I have a radius parameter from WebConfig file, say 5000 (in meters)
I've found the user location on map,
Using the xml list that I own (xml has the Lat-Long values of
each store) I want to put custom markers on map which fell within
the 5 km^2 area range with the user's location as center.
Is there a way to achieve this goal?
How do I calculate a point's Lat & Long values by only passing user's location coordinates and a distance parameter (say 5000 in my case)?
Edit :
My XML doc is kinda huge including whitegoods stores all around the
country. My main problem is to filter these rows of data (long,latt)
using user's current location.
I need something like:
func distanceCale(int long, int latt, int radius)
to return me some values that can help me filter my XML data.
I guess my question was not clear enough at the firs place. :)
You can achieve this using the Haversine formula. This formula has been used in a Demo from an XML file showing markers within a given radius.
For your application the javascript code is used to generate markers from XML file.
function deg2rad(degrees){
radians = degrees * (Math.PI/180);
//document.write(radians);
return radians;
}
function Haversine(lat1,lon1,lat2,lon2) {
deltaLat = lat2 - lat1 ;
deltaLon = lon2 - lon1 ;
earthRadius = 3959; // in miles 6371 in meters.
alpha = deltaLat/2;
beta = deltaLon/2;
a = Math.sin(deg2rad(alpha)) * Math.sin(deg2rad(alpha)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(deg2rad(beta)) * Math.sin(deg2rad(beta)) ;
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
distance = earthRadius * c;
return distance.toFixed(2);
}
The Haversine function is used when parsing XML
var radius = document.getElementById('radiusSelect').value;
for (var i = 0; i < markerNodes.length; i++) {
var lat = parseFloat(markerNodes[i].getAttribute("lat"));
var lng = parseFloat(markerNodes[i].getAttribute("lng"));
var latlng = new google.maps.LatLng(
lat,
lng);
var distance = Haversine(center.lat(),center.lng(),lat,lng);
if(distance<=radius) {
createOption(name, distance, i);
createMarker(latlng, name, distance);
bounds.extend(latlng);
}