I have a latitude/longitude value and distance value. I need to calculate a bounding box with the given location as the center. so if the distance was 200 meters then the rectangle box should be 200 meters in front, behind, to left and right.
How do I go about doing this using JavaScript?
You need to translate your coordinate lat/long to a x/y-value in the map projection you are using, then you can calculate your bounding box.
I don't know the Google Maps API well, and I don't know exactly what you want to do with your box. But maybe GBounds, GMercatorProjection and GLatLngBounds can be helpful. And if Google Maps API doesn't support calculations for the map projection you are using, then it can be helpful to use Proj4js. And maybe you want to read up about Map projections. Google Maps is by default using Mercator projection.
Here are a number of useful javascript functions for working with latitude and longitude:
http://www.movable-type.co.uk/scripts/latlong.html
For bounding box around a point, a simple modification using the above javascript library might be:
LatLon.prototype.boundingBox = function (distance)
{
return [
this.destinationPoint(-90, distance)._lon,
this.destinationPoint(180, distance)._lat,
this.destinationPoint(90, distance)._lon,
this.destinationPoint(0, distance)._lat,
];
}
(This uses the "Destination point given distance and bearing from start point" calculation.)
If you're using the V3 API, you can make use of Rectangle and Circle. See this blogger's brief description and examples:
http://apitricks.blogspot.com/2010/02/rectangle-and-circle-of-v3.html
Related
I am new to leaflet and I want the restrict the panning of a world map horizontally and not vertically (longitude but not latitude) because this map will display pictures when I click on them and I cant see well the image when i restrict the panning horizontally AND vertically. The map by itself it not a picture, it's a real world map. But when I click on certain location, a small picture will appear on the map.
I try to play with maxBounds and setMaxbounds. The normal maxBounds (to view the world map) is :
maxBounds: [[-85, -180.0],[85, 180.0]],
When i try to put the latitude to
[[-150, -180.0],[150, 180.0]]
, the vertical panning is still restricted. Can somebody help please? Thank you.
This sounds similar to a (quite obscure) issue in the Leaflet issue tracker a
while back: see https://github.com/Leaflet/Leaflet/issues/3081
However, that issue was dealing with infinite horizontal bounds, not vertical bounds in a CRS that already has some preset limits.
If you set the map's maxBounds to a value larger than 85 (the value for MAX_LATITUDE of L.Projection.Spherical) and run a debugger, the call stack goes through the map's _panInsideMapBounds(), then panInsideBounds(), then _limitCenter(), then _getBoundsOffset, then project(), then through the map CRS's latLngToPoint, then untimately L.Projection.Spherical's project(). L.Projection.Spherical.project() projects the bounds' limits into pixel coordinates, and clamps the projected point to be inside the projection's limits.
There are a lot of reasons behind this, one of them being to prevent users from putting markers outside the area covered with tiles:
(This is particularly important when a user confuses lat-lng with lng-lat and tries to use a value outside the [-90,90] range for latitude, and the projection code starts returning Infinity values everywhere)
How to get around this? Well, we can always specify the map's CRS, and we can create a CRS with a hacked projection which enforces a different limit. Please be aware that this changes how the pixelOrigin works internally (as explained in the Leaflet tutorial about extending layers), so stuff (particularly plugins) might break.
So something like:
var hackedSphericalMercator = L.Util.extend(L.Projection.SphericalMercator, {
MAX_LATITUDE: 89.999
});
var hackedEPSG3857 = L.Util.extend(L.CRS.EPSG3857, {
projection: hackedSphericalMercator
});
var map = new L.Map('mapcontainer', {
crs: hackedEPSG3857,
});
Of course, then you can set up your own maxBounds:
var map = new L.Map('mapcontainer', {
crs: hackedEPSG3857,
maxBounds: [[-Infinity, -10], [Infinity, 10]]
});
In this case, the bounds' limits would still be clamped to hackedSphericalMercator.MAX_LATITUDE, but you should have enough wiggle room for your application.
As a side note: A radically different approach to this problem would be to use a different map projection. We're used to a spherical cylindrical projection, but that's not the only way to flatten the earth.
In particular, a Transverse Mercator projection (or pretty much any other transverse cylindrical projection, for that matter) works pretty much in the same way, but wraps vertically instead of horizontally, and it's the projected longitudes, not latitudes, the ones which approach infinity asymptotically when approaching the [-180, 180] range. Let me borrow an image from its wikipedia article:
This implies a different set of challenges (namely finding some raster tiles appropriate for your application, including which prime meridian to use, and making proj4leaflet play nice), but it's definitely doable.
I just want to clarify whether my way of understanding is correct. In my Google Maps app I would like to show to my users markers from particular continents.
Question: Am I right that a bound in Google Map API is an area made from NOT MORE AND NOT LESS than two points (markers)?
From math lessons, to draw 2D area I just need two points. Right? So to show to my users all markers from Europe should I just find two coordinates, one from Iceland (top, left) and second from let's say south-east Turkey? (For USA I would pick Seattle and Miami).
So, below JS code works perfectly. My question is - could you confirm that my way of understanding and the approach I've chosen is correct? Does it make any sense?
var bounds = new google.maps.LatLngBounds();
bounds.extend(new google.maps.LatLng('66.057878', '-22.579047')); // Iceland
bounds.extend(new google.maps.LatLng('37.961952', '43.878878')); // Turkey
this.map.fitBounds(bounds);
Yes, you are mostly correct. Except a 'bound' in Google maps case can include multiple points, for example if you had a point to the far right in the middle of the square in your image above and another at the bottom of the square in the middle you would still get an area the same as you have drawn above but with 3 points as in the edited map.
Obligatory link to the docs :)
https://developers.google.com/maps/documentation/javascript/reference?hl=en
You should not think about "top-left" and "bottom-right" but as south-west and north-east (so bottom-left and top-right if you like), as these are the coordinates used to create and/or retrieve the bounds object.
See the documentation and the getNorthEast and getSouthWest methods.
These two points are LatLng objects, and not markers. As an example, a marker is positioned on the map using a LatLng object.
I don't know your use case and your way of storing the data, but there might be a more precise way to display "Europe" markers. You could for example save the region along with each marker so that you can just query for "EU" markers and not others...
If I have stored in my DB several latlng points, and I want to compare those points with my actual latlng position( giving me the distance between each latlng points with my actual latlng), how would that be posible with google maps API? or it's something that it would be easier using my database?
Computing the distance between two points on a sphere requires the use of the haversine formula, which requires a pretty solid understanding of trigonometry.
The easier way would be to leverage the Google Maps API which has the handy function computeDistanceBetween in the google.maps.geometry.spherical namespace.
Here's some sample code for using computeDistanceBetween:
var home = ['London', new google.maps.LatLng(51.5, -0.1167)];
var pts = [
['Prague', new google.maps.LatLng(50.08, 14.43)],
['Paris', new google.maps.LatLng(48.856614, 2.3522219000000177)],
['Berlin', new google.maps.LatLng(52.5200065999, 13.404953999999975)]
];
// provide a shortcut for the distance function
var dist = google.maps.geometry.spherical.computeDistanceBetween;
pts.forEach(function(pt){
var d = dist(home[1], pt[1])/1000;
// d is now the distance (in km) between the home coordinate and the point
});
See working example here: http://jsfiddle.net/aJTK2/5/
If you intend to use your database for this sort of work, you might want to think about using PostGIS for this. With PostGIS installed:
CREATE EXTENSION postgis;
SELECT ST_Distance(
ST_GeographyFromText('POINT(115.764286 -31.746416)'),
ST_GeographyFromText('POINT(151.036606 -33.906896)')
);
Produces:
st_distance
------------------
3295294.42439749
(1 row)
Compared to Google Maps output, which thinks it's about 3700 km (walking, not crow-flies).
So that seems about right, distance wise.
Note that this is spheroid distance, i.e over the earth's surface, not point-to-point through it.
Watch out for the co-ordinate order in PostGIS vs Google Maps.
To learn more about PostGIS:
Introduction to PostGIS
Introduction to PostGIS - Geography
PostGIS.net
Hello everybody o/
I know that this is more a math question than gmap, but I suppose that someone already pass through this =)
In my map, I have circle (actually I have several of them, but this not change the question), like this: http://code.google.com/intl/pt-BR/apis/maps/articles/mvcfun/step6.html
How do I know if a marker (with latitude X and longitude Y) is inside this circle?
Sorry for the bad english, I'm brazillian =p
In Google Maps JavaScript API v3 you can use geometry library. To enable it you have to slightly change the script URL:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry"></script>
The library contains utility functions for the computation of geometric data on sphere. You can utilize it to compute the distance of two points given by their latLngs this way:
var distanceInMetres = google.maps.geometry.spherical.computeDistanceBetween(latLngCircleCenter, latLngPoint);
Now you can easily check if the point is inside the circle (suppose R is in metres):
if(distanceInMetres < R)
alert("in the circle");
If (lat1, lon1) and (lat2, lon2) are your two points and R is the radius of the circle around your first point, then the distance between the points is given by the haversine formula (or the Great-circle distance). But I believe that for your problem, the angles are small enough to use this approximation:
and then check whether d^2 is less than the radius R^2.
But if your latitude and longitude differences are larger than a few degrees, you'll want to use the full haversine formula.
I Recommend you read http://www.movable-type.co.uk/scripts/latlong.html. It provides a number of algorithms for computations of this kind. It includes JavaScript code for the computations.
Basically if you have the coords of circle center (cX,cY) and radius R, and some marker at X,Y you can do the following calculations:
var distanceQuad = (X-cX)*(X-cX)+(Y-cY)*(Y-cY)
if (distanceQuad<=(R*R))
{
alert("Marker inside circle!");
}
This is from trigonometry. You calculate distance as sqrt(sqr(deltaX)+sqr(deltaY)) and compare it with circle Radius. Given code is a bit optimized to get rid of calculating square root.
It's much easier than you'd expect. Read this answer including a working jsFiddle example.
I can do this to convert a lat/lng to pixel coordinates in Google maps:
var xy = map.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(lat, lng));
Now I'm wondering, how do I get a distance in pixels from that point? Say I want to draw a circle with a radius of 5 miles around that. How do I do that?
In v3 there is the circle object
The best way to draw a circle around a given point is to draw a GPolygon with many points, simulating a circle.
You can find a good example of this here. Look for the drawCircle function in the source (you will need to download the attached circle.html to check it out.