I have seen it pretty often so far that for some reason the latitude or longitude values return by getLatitude() are multiplicated with 1E6 in Google-Maps-examples. What's the reason for this? Why 1E6? What's wrong with the raw values returned by those functions ?
I think I've read somewhere that this is related to performance. getLatitute() returns a double which is floating-point datatype. Math on floating point datatypes is slow if the device doesn't support floating-point operations.
So by multiplying the double value with 1E6, degrees become microdegree and so the calculation can be done with integer math without loosing too much resolution.
Its not just Google maps, I work with some maritime chart APIs on Windows PCs & they use a mixture on decimal degrees & 1E7 degrees. It just seems to be the functions were written that way & no one is bothered to unify them all.
The reason they are multiplied by 1E6 is because the GeoPoint class (which is used to plot points on a Google Map) uses microdegree latitude and longitude as integers. Multiplying by 1E6 converts degrees into microdegrees. The reason Google chose to do it this way is up to debate, but it probably has to do with the fact that the Google Maps themselves are not extremely accurate, and using a raw double value to 10 or more decimal places returned by the GPS is an unnecessary level of accuracy to plot a point on a Google Map.
Related
Google Static Maps API Documentation states:
Latitudes and longitudes are defined using numerals within a comma-separated text string that have a precision to 6 decimal places. For example, "40.714728,-73.998672" is a valid geocode value. Precision beyond the 6 decimal places is ignored.
However, I have noted that in many cases, that precision is not enough.
(Edit: Actually, 6 decimal places allows a precision of approximately 2 cms, as 323go comments. See the edit at the bottom for further info)
E.g: Trying to put a marker on the Eiffel Tower (Lat: 48.8583701,Lon: 2.2922926) gets truncated (to Lat: 48.858370, Lon:2.292292) obtaining the following result, which has a non negligible offset:
I use static maps is because in my application I show multiple maps simultaneously inside the items of a RecyclerView.
I currently achieve that by asynchronously injecting the images returned by the Google static maps API via Picasso.
This current approach works well and performs smoothly, the only problem being the lack of precision of the map.
As a workaround, I am considering using the standard MapView in Lite Mode, but I am concerned that it could lead to performance issues, as stated in this question
Is there a way to overcome that limit, even if it requires paying?
Edit
I was using wrong coordinates. I'll explain how I got them, just in case anyone else makes the same mistake.
I was using the coordinates that appear in the URL after loading https://google.com/maps/place/Tour+Eiffel, which in my case is this URL.
When the left side panel of the web version of Google Maps is open (which is the default behaviour), the pin appears to be in the center of the map.
Nevertheless, the coordinates of the URL represent the center of the map including the part under the left panel. This is easy to notice once the left panel is collapsed.
This is what caused the horizontal offset.
Im trying to figure this out but on my side everything is working fine and precise, i noticed you are using different coordinates than mine
For the Eiffel Tower i used:
48.858285, 2.294388
That should give you a better result, also remember you can place a marker with the name of the place or with the full address with Geocoder which is:
Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France
Something like this should help
Geocoder geocoder = new Geocoder(<your context>);
List<Address> addresses;
addresses = geocoder.getFromLocationName(<String address>, 1);
if(addresses.size() > 0) {
double latitude= addresses.get(0).getLatitude();
double longitude= addresses.get(0).getLongitude();
}
I have a data set of different locations, and want to show the nearest locations (within 5 km).
How can I determine the minimum/maximum of latitude and longitude?
f.e.: I need to fill my car up, and am looking for all gas stations in my neighborhood so I can go to the nearest. How do I do this on an Android phone?
I'd like to avoid iterating through all of the locations as well, because I've got about 2500 locations and rising. Any suggestions on that?
Thank you guys in advance for the advice on this!
Update:
Thank you for the feedback you guys gave me, I solved my issue by iterating through all locations on the server and using the Google Distance Matrix API to calculate the distances: http://code.google.com/intl/nl/apis/maps/documentation/distancematrix/
Simplifying, latitude is the angle over/under the equator, longitude is angle right/left of greenwich meridian.
So to calculate (on average) how much for example 1ยบ latitude is, you convert it to radians (multiply by PI/180), and then multiply by Earth's mean radius (6,371.0 km).
For your question, the process is the inverse one: take 5 km and convert it to degrees:
Divide it by Earth's radius
Multiply by 180/PI
This way you will get delta degrees, that is, how much degrees are 5 kms (on average, if you want exactitude, you will need the exact Earth radius differentials over those 5 kms) with which you can build a circle around the given location (just like a compass would).
All the calcuations give and methods are approximations but well within tolerances for what you require.
The earth circumference is approx 40076000 metres.
the distance traveled per degree of latitude is allways the same and is simply a proportion of the earth circ.
the distance travel per degree in longitude however changes depending upon your latitude ( this rings on the glode get smaller nearer the poles ).
so for a given distance m, the corresponing Latitude and Longitude values are
earthcirc = 40076000;
// at Lat and Lon for distance m (in meters)
LatDelta = (m * 360) / earthcirc;
LonDelta = (m * 360) / abs(eathcirc*cos(lat));
This gives you your square lat long deltas for a simple search of your data. but on fingin a candidate your should then do a full distance calc as the corner of the square is quite a bit more than 5 KM away.
distance between 2 lat/longs
distLat = (lat1-lat2) * earthcirc) / 360;
distLong = (long1-long2) * earthcirc * cos((lat1+lat2)/2) / 360;
dist = sqrt( sqr(distLat) + sqr(distLong) );
I know most compilers/languages use radians for cos/sin functions but its easire to explain in degrees.
as for searching your data the simplest way is to order in be either lat or long then you can do a binary search to find the possible location to check instead of a full scan. There are better ways to order the data ( quad trees ) but for 2500 ish entries i wouldnt bother
There are two issues here, 1) how to calculate the distance between two pairs of lat/lon and 2) how to find the point with shortest distance to a given point.
There are formulas on the net, some more accurate than others, for example http://www.movable-type.co.uk/scripts/latlong.html
This is a (geo) spatial indexing problem (http://en.wikipedia.org/wiki/Spatial_index#Spatial_Index ). You can use for example a quad tree with lat/lng as X/Y (I assume your points are not too close to the polars, which complicate things but still doable). The quad tree let you find in Log(N) time the neighborhood of your car without having to iterate over all points.
Not exact code but hopefully it will help.
I have an interesting question. I have a latitude value of 51.445376 and a longitude value of -0.190624 (as an example, say this was recieved by an androids location listener). This particular location (and it's values) is a point of interest and it is stored in my database. I am using a location listener on my android, and I will send the users current location to the server to detect if the user has come within a one kilometre radius of that particular point of interest. Does anyone know what algorithm to use to check if the users current longitude and latitude is within that one kilometre radius of the point of interests longitude and latitude? Or something I can see?
Perhaps someone could help me out, as my math is not the greatest in the world.
For geographic coordinates, use this function (public domain):
public static double distanceInKM(
double latStart,double lonStart,
double latEnd,double lonEnd
){
latStart=Math.toRadians(latStart);
latEnd=Math.toRadians(latEnd);
return 6370.997*Math.acos(
Math.cos(Math.toRadians(lonEnd - lonStart))*Math.cos(latStart)*
Math.cos(latEnd)+Math.sin(latStart)*Math.sin(latEnd));
}
Calculating the shortest geographic path is called the "inverse geodesic problem", and this is discussed in C.F.F. Karney's article "Algorithms for geodesics, 2012. The method above shows a distance function based on the spherical law of cosines, which is a less accurate way to compute this path, especially because it assumes Earth is a perfect sphere.
This post from 2008 might be helpful.
It links to a MovableType description of how to use the Haversine formula to calculate the distance between two points on a sphere. It's important to note that it's not 100% accurate since the Earth is not a perfect sphere (it's equatorial radius is some 20km different from its polar radius) but should be sufficient for your needs.
The MovableType link also describes how to use an equi-rectangular projection (translation of lat/long to rectangular coordinates) and the pythagorean theorem to determine a rougher (but faster) approximation of the distance (good for small distances of ~1-2km.)
A simple solution: Simply find the distance, by first finding dx and dy.
Say I have point 1 (p1) and point 2 (p2)
dx = p2.x - p1.x;
dy = p2.y - p1.y;
Now find the distance d as follows
d = sqrt(dx^2 + dy^2)
In a programming language like java, you can use the following lines:
double d = Math.sqrt(dx*dx + dy*dy);
Hope this helps as your starting point!
Note: x & y must be calculated accordingly for your lat&lon info. I was going to write a short code snippet but I saw someone else has a nice solution (I upvoted his response).
Hi
I am having a little trouble figuring out how to convert between types of coordinates. I have a list of coordinate sets with the following description
"Coordinates are always in the WGS84 system. All coordinates a represented as integer
values x and y where the coordinate value is multiplied with 1,000,000."
An example:
559262 6319512
Well, I need to convert these to long/lat (and back) so i can use these in google maps (android). But this is not as easy as it seams. I have been searching around and did find some code to do this, but it does not seam to work properly. Anyone who can provide some code for doing this? If possible, I would like to avoid a big geo framework (it has to be used in an android application).
thanks.
best regards, kenneth
EDIT:
I did find a solution on my own. I downloaded the class described here:
http://www.ibm.com/developerworks/java/library/j-coordconvert/
And it works fine. Hope someone can find it useful.
I am sorry for posting before having done my homework decently. Thanks to everyone who posted
If you're getting the location from the GPS on android, you will get a Location object that holds Lat/Long as doubles. In order to display a point on Google Maps, you need to turn these double values into a GeoPoint object using:
GeoPoint location = new GeoPoint(
(int) (mLocation.getLatitude()) * 1E6),
(int) (mLocation.getLongitude()) * 1E6)
);
Hope thats helpful.
All GPS systems give their latitude and longitude with respect to the WGS84 model of the Earth. Unless you intend to give the lat/lon with respect to a nation's local model, such as the British OSGB36 model, you should be fine treating the coordinates you have as representing microdegrees. Even here in the Britain, the Admiralty now print their nautical charts with lat/lon relative to WGS84, I expect the Ordnance Survey land maps will follow suit soon, if they haven't already done so.
Does anyone know how to display points, lines etc. (basically every overlay) created in android in standard google maps on website? The android db is synchronized with remote db. I'm getting the points from the database, creating kml file from them and uploading in to the map. The problem is that the areas I've created are not appearing where they should. They're somewhere on the ocean. I thought that's because I'm running this code in android:
Double lat = location.getLatitude()*1E6;
Double lng = location.getLongitude()*1E6;
So basically I'm doing microdegrees here. I thought that dividing lat and long from db by 1E6 would do the trick but it didn't. Can someone please help me on that one? Thanks in advance.
I don't know which format is expected by the map.
If it is normal coordinates, then I guess you would need to do:
float lat = ((float)location.getLatitude()) / 1E6;
Otherwise, if it is expecting it in int format, you don't need to do anything
P.S. Assuming getLatitude() returns an int, the cast to float is important. Otherwise 4539845 will become 45 and not 45.39845
I agree with ltsik, the E6 format is basically the regular latitude multitplied by 1E6 (or 1,000,000 whichever one you prefer) so it makes perfect sense that the variables lat and lng are obtained by dividing and not multiplying