title: Google Maps v3 using only one's own tiles (converting from v2)
body: <p>I use GMapImageCutter to generate tiles and js for a collage (custom map). Everything worked just fine but that was v2. I added markers, infowindows, etc and the projection worked just fine. Now I am at a loss to move this simple application to v3. Can someone direct me to a site that uses NO MAPS just its own collection of tiles - in v3? This is the GMapImageCutter js</p>
  
  <pre><code>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
  &lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"&gt;
    &lt;head&gt;
      &lt;meta http-equiv="content-type" content="text/html/xml; charset=utf-8"/&gt;
      &lt;meta name="author" content="Richard Milton, Centre for Advanced Spatial Analysis (CASA), University College London (UCL)"&gt;
      &lt;meta name="description" content="Page automatically created by GMapImageCutter created by CASA"&gt;
      &lt;meta name="keywords" content="Google, Maps, Image, Images, Tile, Cutter, GMapImageCutter, GMapCreator"&gt;
  
      &lt;title&gt;Picture Viewer&lt;/title&gt;
  
      &lt;style type="text/css"&gt;
      v\:* {
        behavior:url(#default#VML);
      }
      &lt;/style&gt;
  
  
      &lt;script src="http://maps.google.com/maps?file=api&amp;v=2.x&amp;key=PUTAPIKEYHERE"
              type="text/javascript"&gt;&lt;/script&gt;
      &lt;script type="text/javascript"&gt;
      //&lt;![CDATA[
  
      var centreLat=0.0;
      var centreLon=0.0;
      var initialZoom=2;
      var imageWraps=false; //SET THIS TO false TO PREVENT THE IMAGE WRAPPING AROUND
      var map; //the GMap2 itself
  
  /////////////////////
  //Custom projection
  //pass this zoom level count, wrap Boolean
  /////////////////////
      function CustomProjection(a,b){
  
      this.imageDimension=65536;
  
      this.pixelsPerLonDegree=[];
      this.pixelOrigin=[];
      this.tileBounds=[];
      this.tileSize=256;
      //use original b
      this.isWrapped=b;
      //define a new b
      //why would anyone do this?
      var b=this.tileSize;
  
      var c=1;
      for(var d=0;d&lt;a;d++){
            var e=b/2;
            this.pixelsPerLonDegree.push(b/360);
            this.pixelOrigin.push(new GPoint(e,e));
            this.tileBounds.push(c);
            b*=2;
            c*=2
          }
      }
  
      CustomProjection.prototype=new GProjection();
  
      CustomProjection.prototype.fromLatLngToPixel=function(latlng,zoom){
          var c=Math.round(this.pixelOrigin[zoom].x+latlng.lng()*this.pixelsPerLonDegree[zoom]);
          var d=Math.round(this.pixelOrigin[zoom].y+(-2*latlng.lat())*this.pixelsPerLonDegree[zoom]);
          return new GPoint(c,d)
      };
  
      CustomProjection.prototype.fromPixelToLatLng=function(pixel,zoom,unbounded){
          var d=(pixel.x-this.pixelOrigin[zoom].x)/this.pixelsPerLonDegree[zoom];
          var e=-0.5*(pixel.y-this.pixelOrigin[zoom].y)/this.pixelsPerLonDegree[zoom];
          return new GLatLng(e,d,unbounded)
      };
  
      CustomProjection.prototype.tileCheckRange=function(tile,zoom,tilesize){
          var tileBounds=this.tileBounds[zoom];
      if (tile.y&lt;0 || tile.y &gt;= tileBounds) {return false;}
          if (this.isWrapped) {
          if (tile.x&lt;0 || tile.x&gt;=tileBounds) { 
              tile.x = tile.x%tileBounds; 
              if (tile.x &lt; 0) {tile.x+=tileBounds} 
          }
      }
      else { 
              if (tile.x&lt;0 || tile.x&gt;=tileBounds) {return false;}
      }  
      return true;
      }
  
      CustomProjection.prototype.getWrapWidth=function(zoom) {
          return this.tileBounds[zoom]*this.tileSize;
      }
  ////////////////////////////////////////////////////////////////////////////
  
      function customGetTileURL(a,b) {
        //converts tile x,y into keyhole string
  
        var c=Math.pow(2,b);
  
          var d=a.x;
          var e=a.y;
          var f="t";
          for(var g=0;g&lt;b;g++){
              c=c/2;
              if(e&lt;c){
                  if(d&lt;c){f+="q"}
                  else{f+="r";d-=c}
              }
              else{
                  if(d&lt;c){f+="t";e-=c}
                  else{f+="s";d-=c;e-=c}
              }
          }
          return "sqShelvesFloors03-tiles/"+f+".jpg"
      }
  
  
      function getWindowHeight() {
          if (window.self&amp;&amp;self.innerHeight) {
              return self.innerHeight;
          }
          if (document.documentElement&amp;&amp;document.documentElement.clientHeight) {
              return document.documentElement.clientHeight;
          }
          return 0;
      }
  
      function resizeMapDiv() {
          //Resize the height of the div containing the map.
          //Do not call any map methods here as the resize is called before the map is created.
          var d=document.getElementById("map");
          var offsetTop=0;
          for (var elem=d; elem!=null; elem=elem.offsetParent) {
              offsetTop+=elem.offsetTop;
          }
          var height=getWindowHeight()-offsetTop-16;
          if (height&gt;=0) {
              d.style.height=height+"px";
          }
      }
  
  
      function load() {
        if (GBrowserIsCompatible()) {
          resizeMapDiv();
          //pragmatic extents
          var copyright = new GCopyright(1,
                                new GLatLngBounds(new GLatLng(-90, -180),
                                                  new GLatLng(90, 180)),
                                0,
                                "&lt;a href=\"http://www.casa.ucl.ac.uk\"&gt;CASA&lt;/a&gt;");
          var copyrightCollection = new GCopyrightCollection("GMapImgCutter");
          copyrightCollection.addCopyright(copyright);
  
          //create a custom picture layer
          var pic_tileLayers = [ new GTileLayer(copyrightCollection , 0, 17)];
          pic_tileLayers[0].getTileUrl = customGetTileURL;
          pic_tileLayers[0].isPng = function() { return false; };
          pic_tileLayers[0].getOpacity = function() { return 1.0; };
          var proj=new CustomProjection(5,imageWraps);
          var pic_customMap = new GMapType(pic_tileLayers, proj, "Pic",
              {maxResolution:4, minResolution:0, errorMessage:"Data not available"});
  
  
          //Now create the custom map. Would normally be G_NORMAL_MAP,G_SATELLITE_MAP,G_HYBRID_MAP
          map = new GMap2(document.getElementById("map"),{mapTypes:[pic_customMap]});
          map.addControl(new GLargeMapControl());
          map.addControl(new GMapTypeControl());
          map.addControl(new GOverviewMapControl());
          map.enableDoubleClickZoom();
          map.enableContinuousZoom();
          map.enableScrollWheelZoom();
          map.setCenter(new GLatLng(centreLat, centreLon), initialZoom, pic_customMap);
  
  /////////////////////////////////////////////////////////////////////////////////////
  //Add any markers here e.g.
  //      map.addOverlay(new GMarker(new GLatLng(x,y)));
  /////////////////////////////////////////////////////////////////////////////////////
  
      map.addOverlay(new GMarker(new GLatLng(85,170)));
      map.addOverlay(new GMarker(new GLatLng(85,-170)));
      map.addOverlay(new GMarker(new GLatLng(-85,-170)));
      map.addOverlay(new GMarker(new GLatLng(-85,170)));
        }
      }
  
      //]]&gt;
      &lt;/script&gt;
    &lt;/head&gt;
    &lt;body onresize="resizeMapDiv()" onload="load()" onunload="GUnload()"&gt;
      &lt;div id="map"&gt;&lt;/div&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>