Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Maps API V3 - Prevent ImageMapType from wrapping

Please note:

This question is very similar to this one I found on stackoverflow.

Google Maps v3 ImageMapType Prevent Wrapping

However, the above question and answer did not work for my example / issue as I need to be able to view all of my image at any zoom level and more importantly i need the drawing tools to work correctly.


My Scenario:

I have a custom google map using ImageMapType, it also has the DrawingManager library and tools.

My issue:

At first glance all works nicely, however if you are to draw any markers or polygons and then pan the map the markers / polygons repeat or move across the area of map in view.

The same issue occurs when drawing large polygons on the map, as you are drawing the polygon, you will notice the line you are drawing will suddenly snap to the wrong side of your polygon.

My question:

How do I go about preventing the wrapping issues so that all of the markers do not move, or duplicate, and so that the drawing tools work without snapping to the other side of your polygon?


Online example:

http://jsbin.com/ecujug/5/edit#javascript,live

Video of the issues:

https://dl.dropbox.com/u/14037764/Development/stackoverflow/map-drawing/issue.html

Desired Effect:

http://www.maplib.net/map.php?id=1236

like image 880
Blowsie Avatar asked Jul 10 '12 10:07

Blowsie


2 Answers

Instead of 1-3 zoom levels, you should work in higher levels and choose another origin than (0,0) tile for images. What you need, is just simple Maths.As by default your map will be centered to LatLng(0,0) point(as you have mentioned in your MapOptions), the calculations will be performed around that point.

Theory

At any zoom, there are totally 2^zoom x 2^zoom tiles:

                           zoom
  _______________________ 2
  |_|_|_|_|_|_|_|_|_|_|_|
  |_|_|_|_|_|_|_|_|_|_|_|
  |_|_|_|_|_|_|_|_|_|_|_|          
  |_|_|_|_|_|_|_|_|_|_|_|          
  |_|_|_|_|_|_|_|_|_|_|_|
  |_|_|_|_|_|_|_|_|_|_|_|          
  |_|_|_|_|_|_|_|_|_|_|_|
  |_|_|_|_|_|_|_|_|_|_|_|
  |_|_|_|_|_|_|_|_|_|_|_|
  |_|_|_|_|_|_|_|_|_|_|_| 
  zoom
 2

As LatLng(0,0) is the central GPS point, the tile,which contains that point, should be the central tile of the tile-sheet:

                           zoom
  _______________________ 2
  |                     |
  |                     |
  |                     |           zoom
  |                     |          2         zoom-1
  |          o----------|-------*  ------ = 2
  |          |_|        |            2
  |          |          |
  |          |          |
  |          |          |
  |__________|__________| 
  zoom       |
 2           |  zoom-1
             * 2

So at any zoom level, the central tile has (2^(zoom-1), 2^(zoom-1)) coordinates. That tile will be the origin of the mappings.By subtracting origin coordinates from the current tile's coordinates, we will have such a coordinate-space as when we were working in 1-3 zoom levels and when the origin was the (0,0) tile.

Implementation

First of all, choose higher zoom levels,for example:

var MIN_ZOOM = 11,
    MAX_ZOOM = 13;

Mapping will be done by getNormalizedCoord function:

function getNormalizedCoord(coord, zoom) {
    //Amount of total tiles:
    // MIN_ZOOM    ->     1 tile
    // MIN_ZOOM+1  ->     2 tiles
    // MIN_ZOOM+2  ->     4 tiles
    var totalTiles = 1 << (zoom - MIN_ZOOM),
        y = coord.y,
        x = coord.x;
    var originx = 1 << (zoom-1),
        originy = 1 << (zoom-1);

    if(y < originx || y >= originx + totalTiles ||
        x < originx || x >= originx + totalTiles){
        return null;
    }

    x -= originx;
    y -= originy;

    return { x:x, y:y };
 }

And finally, the ImageMapOptions should be:

var siteMapOptions = {
    getTileUrl: function (coord, zoom) {
         var normalizedCoord = getNormalizedCoord(coord, zoom);
         if (normalizedCoord) {
             return 'https://edocstorage.blob.core.windows.net/siteimages/2fa9fc72-23a7-41ed-86a1-b83a3ba04790/_siteTiles/tile_' + 
                    (zoom-MIN_ZOOM) + '_' + 
                    normalizedCoord.x + '-' + 
                    normalizedCoord.y + '.png';
         } else {
             return 'content/tilecutter/empty.jpg';
         }
    },
    tileSize: new google.maps.Size(256, 256),
    maxZoom: MAX_ZOOM,
    minZoom: MIN_ZOOM,
    radius: 1738000,
    name: "Site Plan"
}; 

Live demo

like image 156
Engineer Avatar answered Oct 21 '22 19:10

Engineer


Seems quite obvious - google maps thinks this is a whole Earth, so that it's rounded. Why do you work on the minimal (Earth-wide) zoom level? Make google maps think this is just a small piece of land which doesn't take more than 1° and you are done.

like image 24
Tomas Avatar answered Oct 21 '22 20:10

Tomas