I'm creating Google Static Maps with a path between markers and have come across certain coordinate combinations that break the path.
The path breaks in this example (markers # Beijing, SF, NY, Azores, Rome):
http://maps.google.com/maps/api/staticmap?path=color:0xff0000cc|weight:3|39.904214,116.407413|37.77493,-122.419416|40.714353,-74.005973|38.721642,-27.220577|41.89052,12.494249&markers=39.904214,116.407413|37.77493,-122.419416|40.714353,-74.005973|38.721642,-27.220577|41.89052,12.494249&maptype=terrain&sensor=false&size=640x404
And works in this example (marker # Rome removed)
http://maps.google.com/maps/api/staticmap?path=color:0xff0000cc|weight:3|39.904214,116.407413|37.77493,-122.419416|40.714353,-74.005973|38.721642,-27.220577&markers=39.904214,116.407413|37.77493,-122.419416|40.714353,-74.005973|38.721642,-27.220577&maptype=terrain&sensor=false&size=640x404
The cause is not crossing over the Greenwich Meridian as I initially thought. It breaks even if I add a marker before that, seemingly any a point East of the automatically calculated centerpoint of the map...but only when the path starts on the other side of -180 longitude.
To prove that, you can see that the Beijing, SF, NY, Azores, Rome path displays correctly when I set the map centerpoint to -170,35
http://maps.google.com/maps/api/staticmap?path=color:0xff0000cc|weight:3|39.904214,116.407413|37.77493,-122.419416|40.714353,-74.005973|38.721642,-27.220577|41.89052,12.494249&markers=39.904214,116.407413|37.77493,-122.419416|40.714353,-74.005973|38.721642,-27.220577|41.89052,12.494249&maptype=terrain&sensor=false&size=640x404¢er=-170,35
Unfortunately, I can't programmatically set center like this because I never know the collection of points I'm going to get, and it would be next to impossible to detect that the passed points would cause a line break.
Any ideas?
First: you can calculate the center even if you don't know the collection of points (locations) at compile time: at runtime you know all the points (otherwise it would be not possible to insert the coordinates into the URL), therefore you can easily iterate over all the points and compute the center. You can computing the average of all coordinates and you get the geometric center (also called centroid): this is the easier way. Another way to do is to check the most distant pair of locations (for both, latitude and longitude) and then set the middle point as center: this requires slightly more coding (for instance to compute the longitude distance you need to take into account the you have to compute the distance in two directions, since it is possible to go 'around the world) and it has an higher complexity.
I don't go deeper in this topic because, even if you compute correctly the center of your points, this does NOT resolve the problem, and moreover the center provided automatically by the Google static map API is always correct: again the center is related to the problem, but it is not the (couse of the) problem.
An aspect that is trivial but important to keep in mind: Google static map draws a path between two locations always by considering the shortest path, i.e. by drawing the shortest straight line.
Therefore if you are in a situation where your path has to go from a location A to a location B, and the shortest path between A and B goes 'around the world' (or better, it goes out from one side of the image), then the path appears 'borken' as in maps that you have shown. In practice A and B are near the left and right margins of the map, and the map can not be centered in some point along the shortest path between A and B because of the others point of the path. And this is what happen when you remove 'Rome': without Rome the map can be centered in a way that the path is not borken.
Formally, I think that the problem appears (i.e. the path is broken), when the projection of the path on the equator is longer than 360 degree of longitudes, and the path always goes in the same direction (i.e. always west to east or always east to west).
Google static map in this situation simply adds another world map next to the first one: if you set the zoom to the minimum, you can see up to three world maps. This is really impractical for several reasons:
you can not zoom out infinitely;
if you want also insert markers into the map they will be drawn only on the 'main' map;
potentially you can have a path that goes around the world (passing in sequence from America, Europe, Asia, and America again and so on...) many times, and it would be really terrible to have so many little maps one after each other;
I googled a lot about this problem, and I didn't find any solution, there is a bug open on the bug tracker, but it is unsolved.
In my opinion the 'right' way to do is simply the following: at most one map and if a path has to goes out from one margin of the map/image, then it should appear on the opposite margin and continues to the destination, drawn on the same map.
So I found a first workaround:
you draw your path, and with the same style (line's color, etc) you also draw the path in a reversed way (Google static map allows to draws multiple paths in the same map), i.e. path=A|B|C&path=C|B|A and this will solve the problem in many situations (i.e. the path exits from one side of the image and enters from the other). Unfortunately this not works always: if you have a path that cross the image margin two consecutive times, then you lose a portion of your path
To solve this problem I found a second workaround:
- not draw simply the path and its reverse, but draw a different path for every pair of locations of the path (and reversed), i.e. for a path A->B->C then: path:A|B,path=B|C,path=C|B,path=B|A and this works always
The drawback is that in this way the URL becomes very long and the limit of 2048 characters for URLs is easily reached.
The best solution would be to compute manually the center, check manually where the path will cross the margin, and only for this portion of the path draw an additional path going between the two locations at the margin (and maybe also the reverse), but I do not think it really worth, although I do not think Google ever will solve this problem.
Related
I'm working on a project where I am showing 8,000+ lat/long coordinates on a Google Map. Works great.
Today I uploaded another 3,000+, and now the Google Map shows a world view of the globe, repeated horizontally, with a lot of gray space on top.
I've looked through the 3,000+ entries, and do not see any where alpha characters, missing lat/long values, etc - something obvious.
The only thing that I can think of is that a lat/long entry is incorrect, and thus the Google Map zoom breaks? Reviewing questions on SO show hacks such as setting minZoom or zoom levels - but I feel that isn't the right path to go across to solve this, since it was working before and something is happening with my new records. I've checked that no pins are on the map outside USA which may cause the entire world view to show.
I'm reaching out to the community to see if anyone smarter than me has a tip or suggestion to help edge case occurrences like this, and/or if my assumption of a wrong lat/long is breaking the Map?
One of your lat/long is incorrect. Instead of Google Maps API failing and alerting, it just breaks the map. I'd advise you to run your locations to confirm decimals exists per each record.
I'm trying to show a broad view of the globe with several markers scattered with polylines connecting them. My map's view is locked so one can't rotate/zoom/pan/move or anything like that. Look at this screenshot:
http://gyazo.com/b81336ff514d76e95ac721aa5381d6c1
The polylines merely take the shortest route which in this case, involves going off the map. I want the lines to all go across the center of the map. Is there a way to do this within the API?
To detect it you must take a look at the longitudes of the 2 points of the path.
When one longitude is greater than 0 and the other is smaller than 0 and the difference between both longitudes is greater than 180 you must add an additional point in the middle of the path.
Sample-code:
//path is an array of 2 LatLng's
if(
((path[0].lng()>=0)!=(path[1].lng()>=0))
&&
(Math.abs(path[0].lng())+Math.abs(path[1].lng())>=180)){
console.log(123)
path=[ path[0],
new google.maps.LatLng((path[0].lat()+path[1].lat())/2,
(path[0].lng()+path[1].lng())/2),
path[1]]
}
Given an address, is there a way to fetch a static Google map with certain parameters in order to show the entire block including the surrounding streets?
This is the result I'm trying to achieve (I just centered and zoomed manually from Google Maps to make the screenshot):
But when requesting via Static Maps API, using zoom 17 is too far:
and using zoom=18 is too close:
Not to mention that I can't figure out how to do the right centering of the map.
I don't think there's an out-of-the-box way of doing this. There are plenty of possibilities for which block you want to show.
Some complications (there are more, I bet) include:
if you're in a street corner, which of the 4 blocks should the sprite be panned to?
if the address is a park?
if your block has an irregular shape? (even with the rectangular-like blocks in NYC it is complex enough due to their rotation on North axis)
If you have the origin latitude and longitude instead of the address, you could try using the &visible=latLng2 argument for the Static Maps URL, where latLng2 is a modified version of origin including a delta (probably ~0.002 degrees) to make it look similar to your idea. This argument cannot be used with a given zoom.
Before:
After:
Maybe your best option is to go with some calculations in the middle (like Google Geo services to know which is the street around the corner, etc)
Re,
I have this strange problem... one track refuses to show in Google Earth. It displays the distance, elevation, everything, but there are no visible track lines. Importing it into Google Maps works fine.
Basically, I have a file with over 350k points. When assembling it, I separated tracks by dates and am now trying to merge them together (manually, by editing the KML file). It appears that when I try to merge placemarks with thousands of coordinates, they stop displaying in Google Earth; as if there is a limit as to how many coordinates a placemark (linestring) can contain.
Here's the file: http://www.upl.co/upload/s4Co0Gc2Q
Thanks in advance.
You need to use the <tessellate> element on the linestring. This specifies whether to allow the LineString to follow the terrain. To enable tessellation, the altitude mode must be clampToGround or clampToSeaFloor. Very large LineStrings should enable tessellation so that they follow the curvature of the earth (otherwise, they may go underground and be hidden).
The other option is to use the <gx:altitudeOffset> element. This is A KML extension, in the Google extension namespace, that modifies how the altitude values are rendered. This offset allows you to move an entire LineString up or down as a unit without modifying all the individual coordinate values that make up the LineString . (Although the LineString is displayed using the altitude offset value, the original altitude values are preserved in the KML file.) Units are in meters.
Something like this should work.
<LineString id="ID">
<extrude>1</extrude>
<tessellate>1</tessellate>
<altitudeMode>clampToGround</altitudeMode>
<coordinates><!-- lon,lat[,alt] --></coordinates>
</LineString>
I have a LineString with about 96000 coordinates, and see the same effect that I can load the KML in google-earth, and see everything correct, except for the LineString (lines are not displayed), as if I had execeeded a certain limit.
The coordinates do not have an altitude. I tried with and without tesselation and alitudeMode clampToGround.
Solution for me was to split the LineString up with a MultiGeometry, splitting it in half was sufficient (each LineString now has less than 64000k coordinates).
I'm using a static google map, but really this problem could apply to any maps project. I want to divide a map into multiple quadrants (of say 50x50 pixels) and label the columns as A, B, C.... and the rows as 1, 2, 3...
Next I plan to do something like,
1) Find the markers which are the farthest north, east, south, and west
2) Use that info to to define the bounding boxes of each row and column box
3) Classify each marker by its row and column (Example Marker 1 = [A,2])
A few requirements,
I don't know the zoom level because I let Google set the zoom level appropriately for me and I would rather not use an algorithm that is dependent on a zoom level. I do however know the locations of all of the markers that are shown on the map.
Here is an example of a map that I would like to classify the markers for,
static map example link.
I found these which look like a good start,
Resource 1, Resource 2
But I think I'm still in need of some help getting started. Can anyone help write out some pseudo code or post a few more resources? I'm kind of in a rut at the moment.
Thanks! Much appreciated of any help!
Ok two days into this I finally got it. Thought I would share my thoughts with people who stumble upon this later.
Following the PHP code on this site and for translating lat,lng pairs to pixel coordinates, I was able to classify the individual pixel row by the x value and the column by the pixels y value.
To calculate the zoom level, I determine the maxLat, maxLng, minLat, and minLng values defined by the collection of markers. Then I calculated the bounds of the map at a given zoom level. Finally I used a brute force method of checking if the new bounds of the map determined by the zoom level would include the bounds defined by the max,min lat,lng values of the collection of markers. Starting at zoom level 21 (max zoom on google maps) I decrement the zoom level until I find a zoom level that includes all the markers.
It seems, that the zoom level that is calculated in this method matches Google's preset zoom level selected automatically if you do not provide a zoom level for a static map.
In PHP there is a nice library to do all of this here.