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.
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 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).
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.
I have in my android application a database table with geo pointes (lat and lon are decimal degree values), about 1000 points. And I need to select 20 nearest point to some given geo point.
I've found at Stackoverflow the answer how to compute distance between two geo points and was very happy, till I tried to write my query. I've found out, that it's not possible to use trignometrical functions in built-in sqlite of android.
But then I've got an Idea. I don't really need to compute a distance. The near a point is to another one the smaller difference in their geo coordinates should be.
How could I use this fact? Would it be enough to order saved points by (lat_0 - lat_n)^2 + (lon0-lon_n)^2, where lat_0 and lon_0 are geo coordinates of a given point?
Thank you,
Mur
UPD
So, the best way to get an answer for my question was to test approach I describe above.
It works pretty well but not really exactly compared to exact distance.
So if you just need to compute a distance, this solution is ok, but in my case I also needed to order stations by distance and couldn't use this solution.
My thanks go on John at CashCommons and Philip. Thank you guys
If your points are separated within a city (more or less), that approximation will work fine. The approximation falls apart if you go worldwide, though.
EDIT: Based on Philip's comment below, you should scale one of the components. Germany is about 50 degrees north latitude, so multiplying the longitude by (cos 50 deg) will do better.
Yes. :-) The actual distance is sqrt( (lat_0 - lat_n)^2 + (lon0-lon_n)^2 ) but ordering by (lat_0 - lat_n)^2 + (lon0-lon_n)^2 is sufficient.
Hmm... I'm not sure how that ordering would work? Wouldn't you need a different order for each point to indicate it's neighbors.
The simplest solution is to just iterate through all the points and compute the geometrical distance between the points. For 1000 points this should happen fairly fast.
The most optimized solution (in terms of retrieval speed) is to compute the neighbors of each point when you insert them in the database. For example you can keep the list of ids as a comma separate string and insert in the database?. Then when you need someones neighbors you do directly to them. However this is going to become a pain if you need to insert new points. Basically you'll need to re-compute the neighbors.
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