I am using google map map API
isLocationOnEdge
var isLocationNear = google.maps.geometry.poly.isLocationOnEdge(latlng, new google.maps.Polyline({
path: google.maps.geometry.encoding.decodePath(result.routes[0].overview_polyline)
}), .00001);
I dnt understand how tolerance is related to km
isLocationOnEdge(point:LatLng, poly:Polygon|Polyline, tolerance?:number)
Let sat i want to detect if a user is within 100m for any polyline drawn on map. How to fix this.
From one of the comments in this post:
tolerance, it is based on the decimal place accuracy desired in terms of latitude and longitude.
Example if say (33.00276, -96.6824) is on the polyline, if the tolerance is 0.00001 then if you change the point to (33.00278, -96.6824) then the point will ont be on the polyline.
So, you can probably use 0.001 as the tolerance value, if you want to find detect a location within about 100m for polyline.
For example, if your location is (1.001, 12), one of the points in polyline is(1, 12), the distance between your location and the polyline will be about 111.319 meters. The tolerance between (1.001, 12) and (1, 12) is 0.001, so the isLocationOnEdge() will return true.
If your location is (1.002, 12), distance to (1, 12), will be about 222.638 meters. The tolerance between them is 0.002, so if you use number 0.001 as the tolerance value for isLocaitonOnEdge(), it will return false.
You can see the sample code from this JSFiddle: https://jsfiddle.net/j7cco3b0/1/
You can also create a custom function to validate in meters for a better precision.
var isLocationOnEdge=function(location,polyline,toleranceInMeters) {
for(var leg of polyline.getPath().b) {
if(google.maps.geometry.spherical.computeDistanceBetween(location,leg) <= toleranceInMeters){
return true;
}
}
return false;
};
The package for isLocationOnEdge which I found is as given below -
com.google.maps.android.PolyUtil.isLocationOnEdge()
It worked for me.
Related
I have a rectangular polygon and I want to extend the boundaries by 10 km for example.
How would I do that ?
I could use extend method, but how Do I find the distance of 10 km in lat lng ?
So far I have :
bounds = new google.maps.LatLngBounds();
pt = new google.maps.LatLng(lat,lng);
bounds.extend(pt)
It depends on how exact an answer you need.
You could use the following approximation:
Latitude: 1 deg = 110.57 km; Longitude: 1 deg = 111.320 km source: http://en.wikipedia.org/wiki/Latitude
For a more exact formula, you need to check http://www.movable-type.co.uk/scripts/latlong.html . It has various formulas and also some code. You are looking for the section called 'Destination point given distance and bearing from start point'
It depends where you are looking at but a longitude is 111km and a latitude 110km:http://en.m.wikipedia.org/wiki/Latitude.
I am working on an user interface that shows many pins on a map.
During the development I am randomly generating 1500 map pins just to be placed on the map to test look/feel/performance etc. issues.
The code which does that looks like this:
for (var i = 0; i <= 1500; i += 1) {
$scope.mapPins.push({
latitude: (Math.random() * 2) + 51,
longitude: (Math.random() * 4) + 3,
icon: themeImages[Math.floor(Math.random() * themeImages.length)],
title: 'Sample title',
infoContent: 'Sample content'
});
}
Naturally the area of the pins covered is a rectangle for latitudes 51-53 and longitudes 3-7. For those who are wondering where it is, it is the area roughly around Netherlands.
Now, there's a little problem that the Netherlands is not a rectangular area and a lot of these coordinates fall over the sea and I would like my coordinates to be only on the land.
Is there a witty mathematical way how I can pool coordinates from a non-rectangular area?
Of course I could make a google.maps polygon object that covers a nonrectangular shape and then via google api test every random generated pin whether it falls within the bounds of this shape etc, but that would be an overkill for UI design phase. Basically my question is whether there is a neat mathematical trick that would allow me to randomly generate coordinates from a non-rectangular space.
Leave your code as it is, the rectangle is the bounding box over your area of interest.
Then add a line
if (isPointInpolygon(polygon, longitudeOrX, latitudeOrY) {
// use this location
}
now you only need to search for a point in polygon function, which is easy to find.
you can directly use the coordinates in (long, lat) order, longitude is related to x coordinate, lat to y.
The polygon has to be filled with the coordinates of the country not insode the water.
If you have islands, then maybe you need multiple such polygons, then iterate over all.
Not to be a stickler but you're actually generating 1501 map pins :)
It is very unlikely that you'll find a simpler solution than using a simple pointinpolygon check.
Use the Google Maps Drawing library (https://developers.google.com/maps/documentation/javascript/drawing#using_the_library) to draw a polygon around the boundary of the Netherlands and save it however you want (e.g., in database, or just copy the string that defines the boundary's coordinates).
Then in your script above, define the google maps polygon (similar to what is done here in the official docs: https://developers.google.com/maps/documentation/javascript/shapes#polygons), then use the containsLocation method in the Google Maps Geometry library (https://developers.google.com/maps/documentation/javascript/examples/poly-containsLocation) to check if your random map pins lie within the boundaries of the Netherlands before adding them to the map.
For example:
var netherlandsCoords = [
// comma-separated list of coordinates defining the Netherlands boundary
];
var netherlandsBoundary = new google.maps.Polygon({
path: netherlandsCoords
});
for (var i = 0; i <= 1500; i += 1) {
var lat = (Math.random() * 2) + 51;
var lng = (Math.random() * 4) + 3;
var latlng = new google.maps.LatLng(lat, lng);
if (google.maps.geometry.poly.containsLocation(latlng, netherlandsBoundary)) {
$scope.mapPins.push({
latitude: lat,
longitude: lng,
icon: themeImages[Math.floor(Math.random() * themeImages.length)],
title: 'Sample title',
infoContent: 'Sample content'
});
}
}
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);
}
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?
Ok pretty self explanatory. I'm using google maps and I'm trying to find out if a lat,long point is within a circle of radius say x (x is chosen by the user).
Bounding box will not work for this. I have already tried using the following code:
distlatLng = new google.maps.LatLng(dist.latlng[0],dist.latlng[1]);
var latLngBounds = circle.getBounds();
if(latLngBounds.contains(distlatLng)){
dropPins(distlatLng,dist.f_addr);
}
This still results in markers being places outside the circle.
I'm guess this is some simple maths requiring the calculation of the curvature or an area but I'm not sure where to begin. Any suggestions?
Unfortunately Pythagoras is no help on a sphere. Thus Stuart Beard's answer is incorrect; longitude differences don't have a fixed ratio to metres but depend on the latitude.
The correct way is to use the formula for great circle distances. A good approximation, assuming a spherical earth, is this (in C++):
/** Find the great-circle distance in metres, assuming a spherical earth, between two lat-long points in degrees. */
inline double GreatCircleDistanceInMeters(double aLong1,double aLat1,double aLong2,double aLat2)
{
aLong1 *= KDegreesToRadiansDouble;
aLat1 *= KDegreesToRadiansDouble;
aLong2 *= KDegreesToRadiansDouble;
aLat2 *= KDegreesToRadiansDouble;
double cos_angle = sin(aLat1) * sin(aLat2) + cos(aLat1) * cos(aLat2) * cos(aLong2 - aLong1);
/*
Inaccurate trig functions can cause cos_angle to be a tiny amount
greater than 1 if the two positions are very close. That in turn causes
acos to give a domain error and return the special floating point value
-1.#IND000000000000, meaning 'indefinite'. Observed on VS2008 on 64-bit Windows.
*/
if (cos_angle >= 1)
return 0;
double angle = acos(cos_angle);
return angle * KEquatorialRadiusInMetres;
}
where
const double KPiDouble = 3.141592654;
const double KDegreesToRadiansDouble = KPiDouble / 180.0;
and
/**
A constant to convert radians to metres for the Mercator and other projections.
It is the semi-major axis (equatorial radius) used by the WGS 84 datum (see http://en.wikipedia.org/wiki/WGS84).
*/
const int32 KEquatorialRadiusInMetres = 6378137;
Use Google Maps API geometry library to calculate distance between circle's center and your marker, and then compare it with your radius.
var pointIsInsideCircle = google.maps.geometry.spherical.computeDistanceBetween(circle.getCenter(), point) <= circle.getRadius();
It's very simple. You just have to calculate distance between centre and given point and compare it to radius. You can Get Help to calculate distance between two lat lang from here
The following code works for me: my marker cannot be dragged outside the circle, instead it just hangs at its edge (in any direction) and the last valid position is preserved.
The function is the eventhandler for the markers 'drag' event.
_markerDragged : function() {
var latLng = this.marker.getPosition();
var center = this.circle.getCenter();
var radius = this.circle.getRadius();
if (this.circleBounds.contains(latLng) &&
(google.maps.geometry.spherical.computeDistanceBetween(latLng, center) <= radius)) {
this.lastMarkerPos = latLng;
this._geocodePosition(latLng);
} else {
// Prevent dragging marker outside circle
// see (comments of) http://unserkaiser.com/code/google-maps-marker-check-if-in-circle/
// see http://www.mvjantzen.com/blog/?p=3190 and source code of http://mvjantzen.com/cabi/trips4q2012.html
this.marker.setPosition(this.lastMarkerPos);
}
},
Thanks to http://unserkaiser.com/code/google-maps-marker-check-if-in-circle/
and http://www.mvjantzen.com/blog/?p=3190 .
I've been a bit silly really. Thinking about it we can use Pythagorus' theorem.
We have a maximum distance away from a point (X miles), and two latitudes and two longitudes. If we form a triangle using these then we can solve for the distance from the point.
So say we know point1 with coordinates lat1,lng1 is the center of the circle and point2 with coordinates lat2,lng2 is the point we are trying to decide is in the circle or not.
We form a right angled triangle using a point determined by point1 and point2. This, point3 would have coordinates lat1,lng2 or lat2,lng1 (it doesn't matter which). We then calculate the differences (or if you prefer) distances - latDiff = lat2-lat1 and lngDiff = lng2-lng1
we then calculate the distance from the center using Pythagorus - dist=sqrt(lngDiff^2+latDiff^2).
We have to translate everything into meters so that it works correctly with google maps so miles are multiplied by 1609 (approx) and degrees of latitude/longitude by 111000 (approx). This isn't exactly accurate but it does an adequate job.
Hope that all makes sense.