title: Map tiles are mis-positioned on custom Google overlay
body: <p>We're trying to overlay custom tiles on a Google map using v.3 of the API. We have based our work on Google's example at <a href="https://developers.google.com/maps/documentation/javascript/maptypes#ImageMapTypes" rel="nofollow">https://developers.google.com/maps/documentation/javascript/maptypes#ImageMapTypes</a>.</p>
  
  <p>Basic functionality is working and our tiles are appearing, except that they are mis-positioned a little, and changing the zoom level progressively makes them even more mis-positioned.</p>
  
  <p>For example, the map loads at zoom 15. Zooming in one stop to level 16 results in the map re-centering improperly, according to what the tiles show. The map is actually centered properly (as indicated by our custom markers), but the tiles drawn at the new zoom level are ones that should be down and left of the map's center if the proper set of tiles was being drawn for the new zoom.</p>
  
  <p>What is causing this, and how can we fix it?</p>
  
  <p>Are our tiles poorly generated? Do we need to specify map bounds? </p>
  
  <p>Our map page: <a href="http://www.cornell.edu/maps2/" rel="nofollow">http://www.cornell.edu/maps2/</a></p>
  
  <p>Our slightly adjusted Google-example code (if we use the "bound" variable as in the Google example no tiles load because their filenames don't match):</p>
  
  <pre><code>var customTypeOptions = {
  getTileUrl: function(coord, zoom) {
      var normalizedCoord = getNormalizedCoord(coord, zoom);
      if (!normalizedCoord) {
          return null;
      }
      var bound = Math.pow(2, zoom);
  
      //var imageURL = "http://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw" + "/" + zoom + "/" + normalizedCoord.x + "/" + (bound - normalizedCoord.y - 1) + ".jpg";
  
      var imageURL = "http://www.cornell.edu/maps/tiles/x" + (normalizedCoord.x + 1) + "y" + (normalizedCoord.y - 1) + "z" + zoom + ".gif";
  
      return imageURL;
   },
   tileSize: new google.maps.Size(256, 256),
   maxZoom: 18,
   minZoom: 13,
   name: "Custom"
   };
  
  var customMapType = new google.maps.ImageMapType(customTypeOptions);
  
  function getNormalizedCoord(coord, zoom) {
  var y = coord.y;
  var x = coord.x;
  
  // tile range in one direction range is dependent on zoom level
  // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
  var tileRange = 1 &lt;&lt; zoom;
  
  // don't repeat across y-axis (vertically)
  if (y &lt; 0 || y &gt;= tileRange) {
      return null;
  }
  
  // repeat across x-axis
  if (x &lt; 0 || x &gt;= tileRange) {
      x = (x % tileRange + tileRange) % tileRange;
  }
  
  //console.debug(coord.x, coord.y, tileRange, zoom, x, y);
  return {
      x: x,
      y: y
  };
   }
  </code></pre>