I have to implement Google Maps in website that would display a lot of markers globally. A good comparison would be geocaching.com (with exception that I wouldn't have that many markers).
Let's say that database consists of 100 000 markers. It would be insane to request for all of those markers as user would see only small part of them. When I observe sites like geocaching.com markers are displayed only around centre of map and more are added when when user drags maps away. In this way response does not take long and there is no overkill for clients device to display relatively small amount of markers.
The easiest way to accomplish this would be to send centre coordinates of map to server and use haversine formula to calculate bounding square coordinates for some distance, query the database (it shouldn't be to expensive with correct indexes on lat, lng fields) and send that to server. Then in client side add event listener on drag and zoom to catch when bounds of map window is outside from area where markers are and request new markers. However this is not very efficient.
My idea of more efficient way goes like this:
- Divide whole map in equal squares(or at least in sectors) that could be identified by unique index. Below is rough visualizer for this.
I could detect in which section user currently is (by checking map centre coordinates) and make AJAX call asking for markers in this section. Benefit would be that response could be cached (I am going with Varnish). Great thing about this is that when Europe sleeps and USA is awake most of USE section are cached, and vice versa.
- After first batch of markers is received send 8 more request for section next to this. Below again is rough visualizer.
- Set min zoom level so that user couldn't zoom out of all 9 section area. The idea behind this is that I don't want client device to handle to many markers so there will always be only markers that are in corresponding 9 sections. If user would want to navigate for example from USA to Belgium he would have to use geolocation input.
- Catch whenever the bounds of map window goes outside of 9 section and request for new markers. In this example map centre was in section#5 but now it is in section#4. I request there more section, add those markers to map and remove markers from sections #3, #6 and #9.
I am not 100% sure about this design, especially about how to divide whole earth in section? Earth in spherical, map is 2D plane. Should I divide by lat, lng coords or use haversine?
I looked more into how Google Maps transfer spherical globe to plane and found this great example. It can be observed that the longitude lines are actually parallel so I could introduce a constant step for longitude.
Lets say we are aiming for section square to be 5x5 km. Made simple calculation with length of equator 40 075 km and got that for 5km we should use longitude step approx. 0.045
deltaLon = (360/P)*d, where:
deltaLon = step for longitude in degrees
P - length of equator in km
d - size if section square we are aiming in km
Knowing the step we can easily calculate number of section in longitudinal directions and get longitudinal index from given longitude coordinate. This index can be sent to server where we would create to longitude bounds and run MySQL query WHERE longitude>min_bound AND longitude<=max_bound
The problem is with latitude. In example provided above it can be observed that a change of one degree in latitude have bigger impact on change in km on map when moving further away from equator.
My question is what would be the mathematical expression for latitude step if we are aiming for section square size of d? (I don't care about poles, for all I care we can simply forbid to add markers near to poles and start counting our latitude index from lets say +/-80 degrees)