/*global define*/
define([
'../Core/defined',
'../Core/defineProperties',
'../Core/DeveloperError',
'./QuadtreeTileLoadState'
], function(
defined,
defineProperties,
DeveloperError,
QuadtreeTileLoadState) {
"use strict";
/**
* A single tile in a {@link QuadtreePrimitive}.
*
* @alias QuadtreeTile
* @constructor
* @private
*
* @param {Number} options.level The level of the tile in the quadtree.
* @param {Number} options.x The X coordinate of the tile in the quadtree. 0 is the westernmost tile.
* @param {Number} options.y The Y coordinate of the tile in the quadtree. 0 is the northernmost tile.
* @param {TilingScheme} options.tilingScheme The tiling scheme in which this tile exists.
* @param {QuadtreeTile} [options.parent] This tile's parent, or undefined if this is a root tile.
*/
var QuadtreeTile = function QuadtreeTile(options) {
//>>includeStart('debug', pragmas.debug);
if (!defined(options)) {
throw new DeveloperError('options is required.');
}
if (!defined(options.x)) {
throw new DeveloperError('options.x is required.');
} else if (!defined(options.y)) {
throw new DeveloperError('options.y is required.');
} else if (options.x < 0 || options.y < 0) {
throw new DeveloperError('options.x and options.y must be greater than or equal to zero.');
}
if (!defined(options.level)) {
throw new DeveloperError('options.level is required and must be greater than or equal to zero.');
}
if (!defined(options.tilingScheme)) {
throw new DeveloperError('options.tilingScheme is required.');
}
//>>includeEnd('debug');
this._tilingScheme = options.tilingScheme;
this._x = options.x;
this._y = options.y;
this._level = options.level;
this._parent = options.parent;
this._rectangle = this._tilingScheme.tileXYToRectangle(this._x, this._y, this._level);
this._children = undefined;
// QuadtreeTileReplacementQueue gets/sets these private properties.
this._replacementPrevious = undefined;
this._replacementNext = undefined;
// The distance from the camera to this tile, updated when the tile is selected
// for rendering. We can get rid of this if we have a better way to sort by
// distance - for example, by using the natural ordering of a quadtree.
// QuadtreePrimitive gets/sets this private property.
this._distance = 0.0;
/**
* Gets or sets the current state of the tile in the tile load pipeline.
* @type {QuadtreeTileLoadState}
* @default {@link QuadtreeTileLoadState.START}
*/
this.state = QuadtreeTileLoadState.START;
/**
* Gets or sets a value indicating whether or not the tile is currently renderable.
* @type {Boolean}
* @default false
*/
this.renderable = false;
/**
* Gets or set a value indicating whether or not the tile was entire upsampled from its
* parent tile. If all four children of a parent tile were upsampled from the parent,
* we will render the parent instead of the children even if the LOD indicates that
* the children would be preferable.
* @type {Boolean}
* @default false
*/
this.upsampledFromParent = false;
/**
* Gets or sets the additional data associated with this tile. The exact content is specific to the
* {@link QuadtreeTileProvider}.
* @type {Object}
* @default undefined
*/
this.data = undefined;
};
/**
* Creates a rectangular set of tiles for level of detail zero, the coarsest, least detailed level.
*
* @memberof QuadtreeTile
*
* @param {TilingScheme} tilingScheme The tiling scheme for which the tiles are to be created.
* @returns {QuadtreeTile[]} An array containing the tiles at level of detail zero, starting with the
* tile in the northwest corner and followed by the tile (if any) to its east.
*/
QuadtreeTile.createLevelZeroTiles = function(tilingScheme) {
if (!defined(tilingScheme)) {
throw new DeveloperError('tilingScheme is required.');
}
var numberOfLevelZeroTilesX = tilingScheme.getNumberOfXTilesAtLevel(0);
var numberOfLevelZeroTilesY = tilingScheme.getNumberOfYTilesAtLevel(0);
var result = new Array(numberOfLevelZeroTilesX * numberOfLevelZeroTilesY);
var index = 0;
for (var y = 0; y < numberOfLevelZeroTilesY; ++y) {
for (var x = 0; x < numberOfLevelZeroTilesX; ++x) {
result[index++] = new QuadtreeTile({
tilingScheme : tilingScheme,
x : x,
y : y,
level : 0
});
}
}
return result;
};
defineProperties(QuadtreeTile.prototype, {
/**
* Gets the tiling scheme used to tile the surface.
* @memberof QuadtreeTile.prototype
* @type {TilingScheme}
*/
tilingScheme : {
get : function() {
return this._tilingScheme;
}
},
/**
* Gets the tile X coordinate.
* @memberof QuadtreeTile.prototype
* @type {Number}
*/
x : {
get : function() {
return this._x;
}
},
/**
* Gets the tile Y coordinate.
* @memberof QuadtreeTile.prototype
* @type {Number}
*/
y : {
get : function() {
return this._y;
}
},
/**
* Gets the level-of-detail, where zero is the coarsest, least-detailed.
* @memberof QuadtreeTile.prototype
* @type {Number}
*/
level : {
get : function() {
return this._level;
}
},
/**
* Gets the parent tile of this tile.
* @memberof QuadtreeTile.prototype
* @type {QuadtreeTile}
*/
parent : {
get : function() {
return this._parent;
}
},
/**
* Gets the cartographic rectangle of the tile, with north, south, east and
* west properties in radians.
* @memberof QuadtreeTile.prototype
* @type {Rectangle}
*/
rectangle : {
get : function() {
return this._rectangle;
}
},
/**
* An array of tiles that is at the next level of the tile tree.
* @memberof QuadtreeTile.prototype
* @type {QuadtreeTile[]}
*/
children : {
get : function() {
if (!defined(this._children)) {
var tilingScheme = this.tilingScheme;
var level = this.level + 1;
var x = this.x * 2;
var y = this.y * 2;
this._children = [new QuadtreeTile({
tilingScheme : tilingScheme,
x : x,
y : y,
level : level,
parent : this
}), new QuadtreeTile({
tilingScheme : tilingScheme,
x : x + 1,
y : y,
level : level,
parent : this
}), new QuadtreeTile({
tilingScheme : tilingScheme,
x : x,
y : y + 1,
level : level,
parent : this
}), new QuadtreeTile({
tilingScheme : tilingScheme,
x : x + 1,
y : y + 1,
level : level,
parent : this
})];
}
return this._children;
}
},
/**
* Gets a value indicating whether or not this tile needs further loading.
* This property will return true if the {@link QuadtreeTile#state} is
* START
or LOADING
.
* @memberof QuadtreeTile.prototype
* @type {Boolean}
*/
needsLoading : {
get : function() {
return this.state < QuadtreeTileLoadState.DONE;
}
},
/**
* Gets a value indicating whether or not this tile is eligible to be unloaded.
* Typically, a tile is ineligible to be unloaded while an asynchronous operation,
* such as a request for data, is in progress on it. A tile will never be
* unloaded while it is needed for rendering, regardless of the value of this
* property. If {@link QuadtreeTile#data} is defined and has an
* eligibleForUnloading
property, the value of that property is returned.
* Otherwise, this property returns true.
* @memberof QuadtreeTile.prototype
* @type {Boolean}
*/
eligibleForUnloading : {
get : function() {
var result = true;
if (defined(this.data)) {
result = this.data.eligibleForUnloading;
if (!defined(result)) {
result = true;
}
}
return result;
}
}
});
/**
* Frees the resources assocated with this tile and returns it to the START
* {@link QuadtreeTileLoadState}. If the {@link QuadtreeTile#data} property is defined and it
* has a freeResources
method, the method will be invoked.
*
* @memberof QuadtreeTile
*/
QuadtreeTile.prototype.freeResources = function() {
this.state = QuadtreeTileLoadState.START;
this.renderable = false;
this.upsampledFromParent = false;
if (defined(this.data) && defined(this.data.freeResources)) {
this.data.freeResources();
}
if (defined(this._children)) {
for (var i = 0, len = this._children.length; i < len; ++i) {
this._children[i].freeResources();
}
this._children = undefined;
}
};
return QuadtreeTile;
});