I have divided the my google map display in to numbers of parts, Now I want of find it out if any markers are positioned inside a/any particulate cell.
Any Help ?
Farther Explained :
I have got the map bounds by
map.getBounds();
method and then farther divide it into numbers of sub-bounds.
also I have putted markers as
map.addOverlay(markerObject);
Now , I want find if of the cells (which I got by dividing the map by bounds) is containing any markers or not .
I have divide the entire map bounds into numbers of sub bounds
So keep all markers in array. Each marker has a method called get_position( ). After you have finished division of map bound into small sub bounds, you just need to iterate over the sub bounds and check whenever the marker within it.
PS. Also take a look on it, in some cases could be useful.
Suppose you on sub bound cell:
var sub_bounds = new Array();
// here you've pushed into an array the sub bounds
for ( var i = 0; i<sub_bounds.length; ++i)
{
for ( var j = 0; j < markers.length; ++j)
{
var lat = markers[j].get_position( ).lat;
var lng = markers[j].get_position( ).lng;
if ( sub_bounds[i].sw.lat<lat && lat<sub_bounds[i].ne.lat &&
sub_bounds[i].sw.lng<lng && lng<sub_bounds[i].ne.lng)
// marker within cell, do whatever you need to do
}
}
Here is an alternative to the above solution without re-iteration:
First - how big are your sub_bounds? Say 10 latitude and longitude degrees each.
Second - The position of the marker is (floor(marker.lat / 10), floor(marker.lng / 10))
Third - Each marker is added to the map and dropped in a bucket for that subdomain.
so (40, -78) would lie in bucket (4,7) i.e. bucket["4~7"]
Correction: would lie in bucket (4,-7) i.e. bucket["4~-7"]
which would contain all markers between 40 and 50 lat and -70 and -80 lng.
You can use GLatLngBounds as the object that holds all these markers in each bucket, which would give you a good set of methods to use, such as calculating center of the bucket depending on the markers currently in it.
Probably the best solution is given here: how to find out whether a point is inside a polygone:
How to detect that a point is inside a Polygon using Google Maps?
Related
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'
});
}
}
My application allows a user to select two points on the map and find a route between them using the Directions Service of the Google maps Apiv3. Then the coordinates along this route has to be saved to the database. I could successfully write all the code to accomplish this. However I am left out with an issue.
I know that there are several other questions in StackOverflow- One, Two on the same, but I think surely either they or me has missed out something here.
Sample Code:
function getCoordinates(result) {
var currentRouteArray = result.routes[0]; //Returns a complex object containing the results of the current route
var currentRoute = currentRouteArray.overview_path; //Returns a simplified version of all the coordinates on the path
obj_newPolyline = new google.maps.Polyline({ map: map }); //a polyline just to verify my code is fetching the coordinates
var path = obj_newPolyline.getPath();
for (var x = 0; x < currentRoute.length; x++) {
var pos = new google.maps.LatLng(currentRoute[x].kb, currentRoute[x].lb)
latArray[x] = currentRoute[x].kb; //Returns the latitude
lngArray[x] = currentRoute[x].lb; //Returns the longitude
path.push(pos);
}
}
The above code works perfect except that the kb and lb properties of the overview path which seem to hold the lat and lng coordinates are not always the same. The last time I made the code, it was kb and lb for few days, and later it changed to mb, nb and today jb and kb.
I dont see any other properties in the object that can provide me the latlng's other than the above. Answers to other similar questions dint mention this issue. Am I missing something here? Any reliable solutions please.
do not use kb and lb which are minified names and undocumented. Use only the documented properties .lat() and .lng()
Another option is to decode the "points" string:
http://home.provide.net/~bratliff/routes/
It is a lot faster than using the lat() / lng() methods for every individual point.
I have an app that adds a 50mi radius around the current/clicked marker (from mapMarkers[]). I know the selected marker's index number and its LatLng position as "myPosition" and the other markers' LatLng position as mapMarkers[i].point.
After the circle is drawn on the map, I call the following simple function to step thru all the mapMarkers[] to compute the distance from the current marker, and then count how many markers actually fall within the 50mi radius. Simple, right?
Problem: The following routine does not produce any result upon first iteration (i.e., first click) for the current marker. But DOES produce the expected result upon the 2nd and subsequent clicks on the current marker.
function inCircle() {
var j = 0;
var myDistance = 0;
for (var i = 0; i < mapMarkers.length; i++) {
myDistance = google.maps.geometry.spherical.computeDistanceBetween(myPosition, mapMarkers[i].point);
myDistance = parseInt(myDistance/1609.34) //meters to miles
if (myDistance <= 50) {
j = j + 1;
//Do more stuff...
}
}
alert("Markers inside circle: " + j);
}
I call this function just after I BIND the circle to the selected marker. "myPosition" is declared as the map loads. Commenting-out the distance calculations produces results on the first iteration for the current marker.
Any thoughts what might be causing this issue?
WRT my comment above: I think, the geometry library is only loading because you made a request. see here developers.google.com/maps/documentation/javascript/libraries. Include the geometry-spherical library when you call the google maps js(during page load).
Eg:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&libraries=drawing,geometry,weather"></script>
Do anybody know how the google map bound calculation can be done without using any UI element and Javascript.
I have set of points and different zoom level. I can probably add the screen size and I need to calculate the bounds for provided coordinate and zoom level. I am trying to do this in the plain C# code.
Please help.
as for calculating bounds - you can do it easily by walking array of your coordinates and extend bounds rectangle if point falls out. First coord is a start. I don't familiar with C# but there is the algo using pseudocode:
points = Array of coord(lat, lng)
bounds = object {
top: null
left: null
right: null
bottom: null
function extend(coord: (lat, lng))
{
if (this.top == null) // empty
{
this.top = coord.lat; this.bottom = coord.lat;
this.left = coord.lng; this.right = coord.lng;
}
else
{
if (coord.lng < this.left) this.left = coord.lng;
if (coord.lat < this.bottom) this.bottom = coord.lat;
if (coord.lng > this.right) this.right = coord.lng;
if (coord.lat > this.top) this.top = coord.lat;
}
}
}
But of course much simplier way is to use already written google functionality.
Zoom level can be calculated somehow from the size of bounding box (for example you can find a table with rates in km or miles per pixel, or approximate width or map), but most comfortable way is map.fitBounds(bounds)
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.