@private
@inner
Determines whether the 'last best' tile for the area is better than the
tile in question.

@param {OpenSeadragon.Tile} previousBest
@param {OpenSeadragon.Tile} tile
@returns {OpenSeadragon.Tile} The new best tile.
542958
function compareTiles( previousBest, tile ) {
    if ( !previousBest ) {
        return tile;
    }

    if ( tile.visibility > previousBest.visibility ) {
        return tile;
    } else if ( tile.visibility == previousBest.visibility ) {
        if ( tile.squaredDistance < previousBest.squaredDistance ) {
            return tile;
        }
    }

    return previousBest;
}
747551
function (tileset) {
            var i = 0;
            // first gid

            // tile properties (collidable, etc..)
            this.TileProperties = [];

            // hold reference to each tile image
            this.imageCollection = [];

            this.firstgid = this.lastgid = +tileset.firstgid;

            // check if an external tileset is defined
            if (typeof(tileset.source) !== "undefined") {
                var src = tileset.source;
                var ext = me.utils.file.getExtension(src);
                if (ext === "tsx" || ext === "json") {
                    // load the external tileset (TSX/JSON)
                    tileset = me.loader.getTMX(me.utils.file.getBasename(src));
                    if (!tileset) {
                        throw new Error(src + " external TSX/JSON tileset not found");
                    }
                }
            }

            this.name = tileset.name;
            this.tilewidth = +tileset.tilewidth;
            this.tileheight = +tileset.tileheight;
            this.spacing = +tileset.spacing || 0;
            this.margin = +tileset.margin || 0;

            // set tile offset properties (if any)
            this.tileoffset = new me.Vector2d();

            /**
             * Tileset contains animated tiles
             * @public
             * @type Boolean
             * @name me.TMXTileset#isAnimated
             */
            this.isAnimated = false;

            /**
             * true if the tileset is a "Collection of Image" Tileset
             * @public
             * @type Boolean
             * @name me.TMXTileset#isCollection
             */
            this.isCollection = false;

            /**
             * Tileset animations
             * @private
             * @type Map
             * @name me.TMXTileset#animations
             */
            this.animations = new Map();

            /**
             * Remember the last update timestamp to prevent too many animation updates
             * @private
             * @type Map
             * @name me.TMXTileset#_lastUpdate
             */
            this._lastUpdate = 0;

            var tiles = tileset.tiles;
            for (i in tiles) {
                if (tiles.hasOwnProperty(i)) {
                    if ("animation" in tiles[i]) {
                        this.isAnimated = true;
                        this.animations.set(+i + this.firstgid, {
                            dt      : 0,
                            idx     : 0,
                            frames  : tiles[i].animation,
                            cur     : tiles[i].animation[0]
                        });
                    }
                    // set tile properties, if any (XML format)
                    if ("properties" in tiles[i]) {
                        this.setTileProperty(+i + this.firstgid, tiles[i].properties);
                    }
                    if ("image" in tiles[i]) {
                        var image = me.loader.getImage(tiles[i].image);
                        if (!image) {
                            throw new Error("melonJS: '" + tiles[i].image + "' file for tile '" + (+i + this.firstgid) + "' not found!");
                        }
                        this.imageCollection[+i + this.firstgid] = image;
                    }
                }
            }

            this.isCollection = this.imageCollection.length > 0;

            var offset = tileset.tileoffset;
            if (offset) {
                this.tileoffset.x = +offset.x;
                this.tileoffset.y = +offset.y;
            }

            // set tile properties, if any (JSON format)
            var tileInfo = tileset.tileproperties;
            if (tileInfo) {
                for (i in tileInfo) {
                    if (tileInfo.hasOwnProperty(i)) {
                        this.setTileProperty(+i + this.firstgid, tileInfo[i]);
                    }
                }
            }

            // if not a tile image collection
            if (this.isCollection === false) {

                // get the global tileset texture
                this.image = me.loader.getImage(tileset.image);

                if (!this.image) {
                    throw new Error("melonJS: '" + tileset.image + "' file for tileset '" + this.name + "' not found!");
                }

                // create a texture atlas for the given tileset
                this.texture = me.video.renderer.cache.get(this.image, {
                    framewidth : this.tilewidth,
                    frameheight : this.tileheight,
                    margin : this.margin,
                    spacing : this.spacing
                });
                this.atlas = this.texture.getAtlas();

                // calculate the number of tiles per horizontal line
                var hTileCount = +tileset.columns || ~~(this.image.width / (this.tilewidth + this.spacing));
                var vTileCount = ~~(this.image.height / (this.tileheight + this.spacing));
                // compute the last gid value in the tileset
                this.lastgid = this.firstgid + (((hTileCount * vTileCount) - 1) || 0);
                if (tileset.tilecount && this.lastgid - this.firstgid + 1 !== +tileset.tilecount) {
                    console.warn(
                        "Computed tilecount (" + (this.lastgid - this.firstgid + 1) +
                        ") does not match expected tilecount (" + tileset.tilecount + ")"
                    );
                }
            }
        }
302987
function topLevelNodeBefore(node, top) {
    while (!node.previousSibling && node.parentNode != top)
      node = node.parentNode;
    return topLevelNodeAt(node.previousSibling, top);
  }
513380
function (template, new_previous_template, current_templates) {

		var current_previous_index = this._current_templates.indexOf(template) - 1,
			current_previous_template = null;

		if (Lava.schema.DEBUG && current_previous_index == -2) Lava.t();

		// skip removed templates
		while (current_previous_index > -1 && current_templates.indexOf(this._current_templates[current_previous_index]) == -1) {
			current_previous_index--;
		}

		if (current_previous_index > -1) {
			current_previous_template = this._current_templates[current_previous_index];
		}

		if (new_previous_template != current_previous_template) {

			Firestorm.DOM.moveRegionAfter(
				this._getEndElement(new_previous_template),
				this._getStartElement(template),
				this._getEndElement(template)
			);

			// move it in local _current_templates array
			Firestorm.Array.exclude(this._current_templates, template);

			var previous_index = this._current_templates.indexOf(new_previous_template);
			if (Lava.schema.DEBUG && previous_index == -1) Lava.t();
			this._current_templates.splice(previous_index + 1, 0, template);

		}

	}
354037
private void checkTransitives(Collection<Tile> resolved, Tile tile)
    {
        boolean isTransitive = false;
        for (final Tile neighbor : map.getNeighbors(tile))
        {
            final String group = mapGroup.getGroup(tile);
            final String neighborGroup = mapGroup.getGroup(neighbor);
            final Collection<GroupTransition> transitives = getTransitives(group, neighborGroup);

            if (transitives.size() > 1 && (getTransition(neighbor, group) == null || isCenter(neighbor)))
            {
                final int iterations = transitives.size() - 3;
                int i = 0;
                for (final GroupTransition transitive : transitives)
                {
                    updateTransitive(resolved, tile, neighbor, transitive);
                    isTransitive = true;
                    i++;
                    if (i > iterations)
                    {
                        break;
                    }
                }
            }
        }
        // Restore initial tile once transition solved by transitive
        if (isTransitive)
        {
            map.setTile(tile);
        }
    }
415810
private void updateTile(Collection<Tile> resolved,
                            Collection<Tile> toResolve,
                            Tile tile,
                            Tile neighbor,
                            Transition transition)
    {
        final Iterator<TileRef> iterator = getTiles(transition).iterator();
        if (iterator.hasNext())
        {
            final TileRef ref = iterator.next();
            final Tile newTile = map.createTile(ref.getSheet(), ref.getNumber(), neighbor.getX(), neighbor.getY());
            map.setTile(newTile);
            resolved.add(newTile);
        }
        else
        {
            final Tile newTile = map.createTile(tile.getSheet(), tile.getNumber(), neighbor.getX(), neighbor.getY());
            final String groupA = mapGroup.getGroup(tile);
            final String groupB = mapGroup.getGroup(neighbor);

            // Used to fix transitions not found
            if (!neighbor.equals(newTile)
                && (!isCenter(neighbor)
                    || groupA.equals(groupB)
                    || groupLinks.contains(new GroupTransition(groupA, groupB))))
            {
                map.setTile(newTile);
                toResolve.add(newTile);
            }
            resolved.add(newTile);
        }
    }
1294784
@Override
    public Tile getTile(int x, int y, int zoom)
    {
        return new Tile(x, y, zoom)
        {
            @Override
            public synchronized boolean isLoaded()
            {
                return true;
            }

            @Override
            public BufferedImage getImage()
            {
                return emptyTile;
            }

        };
    }
147713
function(evt) {
        var tile = evt.object;
        var img = this.tileCache[tile.url];
        if (img) {
          // if image is on its layer's backbuffer, remove it from backbuffer
          if (img.parentNode &&
                  OpenLayers.Element.hasClass(img.parentNode, 'olBackBuffer')) {
              img.parentNode.removeChild(img);
              img.id = null;
          }
          // only use image from cache if it is not on a layer already
          if (!img.parentNode) {
              img.style.visibility = 'hidden';
              img.style.opacity = 0;
              tile.setImage(img);
              // LRU - move tile to the end of the array to mark it as the most
              // recently used
              OpenLayers.Util.removeItem(this.tileCacheIndex, tile.url);
              this.tileCacheIndex.push(tile.url);
          }
        }
    }
1247036
function createTile(coords, done) {
    let key = this._tileCoordsToKey(coords);
    // console.log('Need:', key);
    
    if ( key in this._freshTiles ) {
      let tile = this._freshTiles[ key ].pop();
      if ( !this._freshTiles[ key ].length ) {
        delete this._freshTiles[ key ];
      }
      L.Util.requestAnimFrame(done);
      // 			console.log('Got ', key, ' from _freshTiles');
      return tile;
    }
    let tileContainer = L.DomUtil.create("div");
    this._tileCallbacks[ key ] = this._tileCallbacks[ key ] || [];
    this._tileCallbacks[ key ].push(
      (function(c /* , k*/) {
        return function(imgNode) {
          let parent = imgNode.parentNode;
          if ( parent ) {
            parent.removeChild(imgNode);
            parent.removeChild = L.Util.falseFn;
            // 						imgNode.parentNode.replaceChild(L.DomUtil.create('img'), imgNode);
          }
          c.appendChild(imgNode);
          done();
          // 					console.log('Sent ', k, ' to _tileCallbacks');
        };
      })(tileContainer /* , key*/)
    );
    
    return tileContainer;
  }
1073626
function(tile, tileUrl, existingRevision, done) {
		if (!this.options.saveToCache) {
			return;
		}

		var canvas = document.createElement("canvas");
		canvas.width = tile.naturalWidth || tile.width;
		canvas.height = tile.naturalHeight || tile.height;

		var context = canvas.getContext("2d");
		context.drawImage(tile, 0, 0);

		var format = this.options.cacheFormat;

		canvas.toBlob(
			function(blob) {
				this._db
					.put({
						_id: tileUrl,
						_rev: existingRevision,
						timestamp: Date.now(),
					})
					.then(
						function(status) {
							return this._db.putAttachment(
								tileUrl,
								"tile",
								status.rev,
								blob,
								format
							);
						}.bind(this)
					)
					.then(function(resp) {
						if (done) {
							done();
						}
					})
					.catch(function() {
						// Saving the tile to the cache might have failed, 
						// but the tile itself has been loaded.
						if (done) {
							done();
						}
					});
			}.bind(this),
			format
		);
	}
494679
@Override
    public Tile getTile(int x, int y, int zoom)
    {
        return getTile(x, y, zoom, true);
    }
1112013
function _getParent(tile) {
  if (tile[2] < z) throw new Error('input tile zoom < ' + z);
  if (tile[2] > z) return _getParent(tilebelt.getParent(tile));
  else return tile;
}
543240
public long addTile(MeshData data, int flags, long lastRef) {
        // Make sure the data is in right format.
        MeshHeader header = data.header;

        // Make sure the location is free.
        if (getTileAt(header.x, header.y, header.layer) != null) {
            throw new RuntimeException("Tile already exists");
        }

        // Allocate a tile.
        MeshTile tile = null;
        if (lastRef == 0) {
            if (m_nextFree != null) {
                tile = m_nextFree;
                m_nextFree = tile.next;
                tile.next = null;
                m_tileCount++;
            }
        } else {
            // Try to relocate the tile to specific index with same salt.
            int tileIndex = decodePolyIdTile(lastRef);
            if (tileIndex >= m_maxTiles) {
                throw new RuntimeException("Tile index too high");
            }
            // Try to find the specific tile id from the free list.
            MeshTile target = m_tiles[tileIndex];
            MeshTile prev = null;
            tile = m_nextFree;
            while (tile != null && tile != target) {
                prev = tile;
                tile = tile.next;
            }
            // Could not find the correct location.
            if (tile != target) {
                throw new RuntimeException("Could not find tile");
            }
            // Remove from freelist
            if (prev == null) {
                m_nextFree = tile.next;
            } else {
                prev.next = tile.next;
            }

            // Restore salt.
            tile.salt = decodePolyIdSalt(lastRef);
        }

        // Make sure we could allocate a tile.
        if (tile == null) {
            throw new RuntimeException("Could not allocate a tile");
        }

        tile.data = data;
        tile.flags = flags;
        tile.links.clear();

        // Insert tile into the position lut.
        int h = computeTileHash(header.x, header.y, m_tileLutMask);
        tile.next = m_posLookup[h];
        m_posLookup[h] = tile;

        // Patch header pointers.

        // If there are no items in the bvtree, reset the tree pointer.
        if (tile.data.bvTree != null && tile.data.bvTree.length == 0) {
            tile.data.bvTree = null;
        }

        // Init tile.

        connectIntLinks(tile);
        // Base off-mesh connections to their starting polygons and connect connections inside the tile.
        baseOffMeshLinks(tile);
        connectExtOffMeshLinks(tile, tile, -1);

        // Connect with layers in current tile.
        List<MeshTile> neis = getTilesAt(header.x, header.y);
        for (int j = 0; j < neis.size(); ++j) {
            if (neis.get(j) == tile) {
                continue;
            }
            connectExtLinks(tile, neis.get(j), -1);
            connectExtLinks(neis.get(j), tile, -1);
            connectExtOffMeshLinks(tile, neis.get(j), -1);
            connectExtOffMeshLinks(neis.get(j), tile, -1);
        }

        // Connect with neighbour tiles.
        for (int i = 0; i < 8; ++i) {
            neis = getNeighbourTilesAt(header.x, header.y, i);
            for (int j = 0; j < neis.size(); ++j) {
                connectExtLinks(tile, neis.get(j), i);
                connectExtLinks(neis.get(j), tile, oppositeTile(i));
                connectExtOffMeshLinks(tile, neis.get(j), i);
                connectExtOffMeshLinks(neis.get(j), tile, oppositeTile(i));
            }
        }

        return getTileRef(tile);
    }
308725
function (renderer, layer, rect) {
            var incX = 1, incY = 1;

            // get top-left and bottom-right tile position
            var start = this.pixelToTileCoords(
                Math.max(rect.pos.x - (layer.maxTileSize.width - layer.tilewidth), 0),
                Math.max(rect.pos.y - (layer.maxTileSize.height - layer.tileheight), 0),
                me.pool.pull("me.Vector2d")
            ).floorSelf();

            var end = this.pixelToTileCoords(
                rect.pos.x + rect.width + this.tilewidth,
                rect.pos.y + rect.height + this.tileheight,
                me.pool.pull("me.Vector2d")
            ).ceilSelf();

            //ensure we are in the valid tile range
            end.x = end.x > this.cols ? this.cols : end.x;
            end.y = end.y > this.rows ? this.rows : end.y;

            switch (layer.renderorder) {
                case "right-up" :
                    // swapping start.y and end.y
                    end.y = start.y + (start.y = end.y) - end.y;
                    incY = -1;
                    break;
                case "left-down" :
                    // swapping start.x and end.x
                    end.x = start.x + (start.x = end.x) - end.x;
                    incX = -1;
                    break;
                case "left-up" :
                    // swapping start.x and end.x
                    end.x = start.x + (start.x = end.x) - end.x;
                    // swapping start.y and end.y
                    end.y = start.y + (start.y = end.y) - end.y;
                    incX = -1;
                    incY = -1;
                    break;
                default: // right-down
                    break;
            }

            // main drawing loop
            for (var y = start.y; y !== end.y; y+= incY) {
                for (var x = start.x; x !== end.x; x+= incX) {
                    var tmxTile = layer.layerData[x][y];
                    if (tmxTile) {
                        this.drawTile(renderer, x, y, tmxTile);
                    }
                }
            }

            me.pool.push(start);
            me.pool.push(end);
        }
944023
function (tiles) {
		const maxDist = 5;
		
		let t, tile, i;
		
		let topLeft = Vector._temp[0],
			topRight = Vector._temp[1],
			bottomLeft = Vector._temp[2],
			bottomRight = Vector._temp[3];
		
		// Calculate initial boundary edges
		for (t = 0; t < tiles.length; t++) {
			tile = tiles[t];
			
			// Skip over irrelevant tiles
			if (isIrrelevant(tile)) {
				continue;
			}
			
			let body = tile.physics.matterBody.body;
			let vertices = body.vertices;
			
			let left = tile.pixelX;
			let right = tile.pixelX + tile.width;
			let top = tile.pixelY;
			let bottom = tile.pixelY + tile.height;
			
			topLeft.y = top;
			topLeft.x = left;
			topRight.y = top;
			topRight.x = right;
			bottomLeft.y = bottom;
			bottomLeft.x = left;
			bottomRight.y = bottom;
			bottomRight.x = right;
			
			// Identify solid boundary edges
			for (i = 0; i < vertices.length; i++) {
				let firstVertex = vertices[i];
				let secondVertex = vertices[(i + 1) % vertices.length];
				
				// Top
				if (distance(firstVertex, topLeft) < maxDist && distance(secondVertex, topRight) < maxDist) {
					tile.physics.slopes.edges.top = Constants.SOLID;
				}
				
				// Bottom
				if (distance(firstVertex, bottomRight) < maxDist && distance(secondVertex, bottomLeft) < maxDist) {
					tile.physics.slopes.edges.bottom = Constants.SOLID;
				}
				
				// Left
				if (distance(firstVertex, bottomLeft) < maxDist && distance(secondVertex, topLeft) < maxDist) {
					tile.physics.slopes.edges.left = Constants.SOLID;
				}
				
				// Right
				if (distance(firstVertex, topRight) < maxDist && distance(secondVertex, bottomRight) < maxDist) {
					tile.physics.slopes.edges.right = Constants.SOLID;
				}
			}
		}
		
		// Compare neighbouring boundary edges
		for (t = 0; t < tiles.length; t++) {
			tile = tiles[t];
			
			// Skip over irrelevant tiles
			if (isIrrelevant(tile)) {
				continue;
			}
			
			let tileEdges = tile.physics.slopes.edges;
			let neighbours = tile.physics.slopes.neighbours;
			
			let up = neighbours.up;
			let down = neighbours.down;
			let left = neighbours.left;
			let right = neighbours.right;
			
			// Identify empty edges
			if (!isIrrelevant(up)) {
				tileEdges.top = this.compareBoundaryEdges(tileEdges.top, up.physics.slopes.edges.bottom);
				tile.collideUp = tileEdges.top !== Constants.EMPTY;
			}
			
			if (!isIrrelevant(down)) {
				tileEdges.bottom = this.compareBoundaryEdges(tileEdges.bottom, down.physics.slopes.edges.top);
				tile.collideDown = tileEdges.bottom !== Constants.EMPTY;
			}
			
			if (!isIrrelevant(left)) {
				tileEdges.left = this.compareBoundaryEdges(tileEdges.left, left.physics.slopes.edges.right);
				tile.collideLeft = tileEdges.left !== Constants.EMPTY;
			}
			
			if (!isIrrelevant(right)) {
				tileEdges.right = this.compareBoundaryEdges(tileEdges.right, right.physics.slopes.edges.left);
				tile.collideRight = tileEdges.right !== Constants.EMPTY;
			}
		}
	}
1073130
private String getNeighborGroup(Tile tile, Tile neighbor)
    {
        final String neighborGroup;
        if (isTransition(neighbor))
        {
            if (isTransition(tile))
            {
                neighborGroup = getOtherGroup(tile, neighbor);
            }
            else
            {
                neighborGroup = null;
            }
        }
        else
        {
            neighborGroup = mapGroup.getGroup(neighbor);
        }
        return neighborGroup;
    }
405695
def update_tile_extent_bounds(self):
        

        if self.tile_bounds_policy == NO_BOUNDS:
            self.tile_beg_min = self.array_start - self.halo[:, 0]
            self.tile_end_max = self.array_start + self.array_shape + self.halo[:, 1]
        elif self.tile_bounds_policy == ARRAY_BOUNDS:
            self.tile_beg_min = self.array_start
            self.tile_end_max = self.array_start + self.array_shape