UNPKG

@quartic/bokehjs

Version:

Interactive, novel data visualization

409 lines (367 loc) 14.1 kB
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; import { TileSource } from "./tile_source"; import * as p from "core/properties"; export var MercatorTileSource = (function(superClass) { extend(MercatorTileSource, superClass); function MercatorTileSource() { return MercatorTileSource.__super__.constructor.apply(this, arguments); } MercatorTileSource.prototype.type = 'MercatorTileSource'; MercatorTileSource.define({ wrap_around: [p.Bool, true] }); MercatorTileSource.override({ x_origin_offset: 20037508.34, y_origin_offset: 20037508.34, initial_resolution: 156543.03392804097 }); MercatorTileSource.prototype.initialize = function(options) { var z; MercatorTileSource.__super__.initialize.call(this, options); return this._resolutions = (function() { var j, results; results = []; for (z = j = 0; j <= 30; z = ++j) { results.push(this.get_resolution(z)); } return results; }).call(this); }; MercatorTileSource.prototype._computed_initial_resolution = function() { if (this.initial_resolution != null) { return this.initial_resolution; } else { return 2 * Math.PI * 6378137 / this.tile_size; } }; MercatorTileSource.prototype.is_valid_tile = function(x, y, z) { if (!this.wrap_around) { if (x < 0 || x >= Math.pow(2, z)) { return false; } } if (y < 0 || y >= Math.pow(2, z)) { return false; } return true; }; MercatorTileSource.prototype.retain_children = function(reference_tile) { var key, max_zoom, min_zoom, quadkey, ref, results, tile; quadkey = reference_tile.quadkey; min_zoom = quadkey.length; max_zoom = min_zoom + 3; ref = this.tiles; results = []; for (key in ref) { tile = ref[key]; if (tile.quadkey.indexOf(quadkey) === 0 && tile.quadkey.length > min_zoom && tile.quadkey.length <= max_zoom) { results.push(tile.retain = true); } else { results.push(void 0); } } return results; }; MercatorTileSource.prototype.retain_neighbors = function(reference_tile) { var key, neighbor_radius, neighbor_x, neighbor_y, ref, ref1, ref2, ref3, results, tile, tx, ty, tz, x, y; neighbor_radius = 4; ref = reference_tile.tile_coords, tx = ref[0], ty = ref[1], tz = ref[2]; neighbor_x = (function() { var j, ref1, ref2, results; results = []; for (x = j = ref1 = tx - neighbor_radius, ref2 = tx + neighbor_radius; ref1 <= ref2 ? j <= ref2 : j >= ref2; x = ref1 <= ref2 ? ++j : --j) { results.push(x); } return results; })(); neighbor_y = (function() { var j, ref1, ref2, results; results = []; for (y = j = ref1 = ty - neighbor_radius, ref2 = ty + neighbor_radius; ref1 <= ref2 ? j <= ref2 : j >= ref2; y = ref1 <= ref2 ? ++j : --j) { results.push(y); } return results; })(); ref1 = this.tiles; results = []; for (key in ref1) { tile = ref1[key]; if (tile.tile_coords[2] === tz && (ref2 = tile.tile_coords[0], indexOf.call(neighbor_x, ref2) >= 0) && (ref3 = tile.tile_coords[1], indexOf.call(neighbor_y, ref3) >= 0)) { results.push(tile.retain = true); } else { results.push(void 0); } } return results; }; MercatorTileSource.prototype.retain_parents = function(reference_tile) { var key, quadkey, ref, results, tile; quadkey = reference_tile.quadkey; ref = this.tiles; results = []; for (key in ref) { tile = ref[key]; results.push(tile.retain = quadkey.indexOf(tile.quadkey) === 0); } return results; }; MercatorTileSource.prototype.children_by_tile_xyz = function(x, y, z) { var b, child_tile_xyz, i, j, quad_key, ref, ref1, ref2, world_x; world_x = this.calculate_world_x_by_tile_xyz(x, y, z); if (world_x !== 0) { ref = this.normalize_xyz(x, y, z), x = ref[0], y = ref[1], z = ref[2]; } quad_key = this.tile_xyz_to_quadkey(x, y, z); child_tile_xyz = []; for (i = j = 0; j <= 3; i = j += 1) { ref1 = this.quadkey_to_tile_xyz(quad_key + i.toString()), x = ref1[0], y = ref1[1], z = ref1[2]; if (world_x !== 0) { ref2 = this.denormalize_xyz(x, y, z, world_x), x = ref2[0], y = ref2[1], z = ref2[2]; } b = this.get_tile_meter_bounds(x, y, z); if (b != null) { child_tile_xyz.push([x, y, z, b]); } } return child_tile_xyz; }; MercatorTileSource.prototype.parent_by_tile_xyz = function(x, y, z) { var parent_quad_key, quad_key; quad_key = this.tile_xyz_to_quadkey(x, y, z); parent_quad_key = quad_key.substring(0, quad_key.length - 1); return this.quadkey_to_tile_xyz(parent_quad_key); }; MercatorTileSource.prototype.get_resolution = function(level) { return this._computed_initial_resolution() / Math.pow(2, level); }; MercatorTileSource.prototype.get_resolution_by_extent = function(extent, height, width) { var x_rs, y_rs; x_rs = (extent[2] - extent[0]) / width; y_rs = (extent[3] - extent[1]) / height; return [x_rs, y_rs]; }; MercatorTileSource.prototype.get_level_by_extent = function(extent, height, width) { var i, j, len, r, ref, resolution, x_rs, y_rs; x_rs = (extent[2] - extent[0]) / width; y_rs = (extent[3] - extent[1]) / height; resolution = Math.max(x_rs, y_rs); i = 0; ref = this._resolutions; for (j = 0, len = ref.length; j < len; j++) { r = ref[j]; if (resolution > r) { if (i === 0) { return 0; } if (i > 0) { return i - 1; } } i += 1; } }; MercatorTileSource.prototype.get_closest_level_by_extent = function(extent, height, width) { var closest, resolution, ress, x_rs, y_rs; x_rs = (extent[2] - extent[0]) / width; y_rs = (extent[3] - extent[1]) / height; resolution = Math.max(x_rs, y_rs); ress = this._resolutions; closest = this._resolutions.reduce(function(previous, current) { if (Math.abs(current - resolution) < Math.abs(previous - resolution)) { return current; } return previous; }); return this._resolutions.indexOf(closest); }; MercatorTileSource.prototype.snap_to_zoom = function(extent, height, width, level) { var desired_res, desired_x_delta, desired_y_delta, x_adjust, xmax, xmin, y_adjust, ymax, ymin; desired_res = this._resolutions[level]; desired_x_delta = width * desired_res; desired_y_delta = height * desired_res; xmin = extent[0], ymin = extent[1], xmax = extent[2], ymax = extent[3]; x_adjust = (desired_x_delta - (xmax - xmin)) / 2; y_adjust = (desired_y_delta - (ymax - ymin)) / 2; return [xmin - x_adjust, ymin - y_adjust, xmax + x_adjust, ymax + y_adjust]; }; MercatorTileSource.prototype.tms_to_wmts = function(x, y, z) { 'Note this works both ways'; return [x, Math.pow(2, z) - 1 - y, z]; }; MercatorTileSource.prototype.wmts_to_tms = function(x, y, z) { 'Note this works both ways'; return [x, Math.pow(2, z) - 1 - y, z]; }; MercatorTileSource.prototype.pixels_to_meters = function(px, py, level) { var mx, my, res; res = this.get_resolution(level); mx = px * res - this.x_origin_offset; my = py * res - this.y_origin_offset; return [mx, my]; }; MercatorTileSource.prototype.meters_to_pixels = function(mx, my, level) { var px, py, res; res = this.get_resolution(level); px = (mx + this.x_origin_offset) / res; py = (my + this.y_origin_offset) / res; return [px, py]; }; MercatorTileSource.prototype.pixels_to_tile = function(px, py) { var tx, ty; tx = Math.ceil(px / parseFloat(this.tile_size)); tx = tx === 0 ? tx : tx - 1; ty = Math.max(Math.ceil(py / parseFloat(this.tile_size)) - 1, 0); return [tx, ty]; }; MercatorTileSource.prototype.pixels_to_raster = function(px, py, level) { var mapSize; mapSize = this.tile_size << level; return [px, mapSize - py]; }; MercatorTileSource.prototype.meters_to_tile = function(mx, my, level) { var px, py, ref; ref = this.meters_to_pixels(mx, my, level), px = ref[0], py = ref[1]; return this.pixels_to_tile(px, py); }; MercatorTileSource.prototype.get_tile_meter_bounds = function(tx, ty, level) { var ref, ref1, xmax, xmin, ymax, ymin; ref = this.pixels_to_meters(tx * this.tile_size, ty * this.tile_size, level), xmin = ref[0], ymin = ref[1]; ref1 = this.pixels_to_meters((tx + 1) * this.tile_size, (ty + 1) * this.tile_size, level), xmax = ref1[0], ymax = ref1[1]; if ((xmin != null) && (ymin != null) && (xmax != null) && (ymax != null)) { return [xmin, ymin, xmax, ymax]; } else { return void 0; } }; MercatorTileSource.prototype.get_tile_geographic_bounds = function(tx, ty, level) { var bounds, maxLat, maxLon, minLat, minLon, ref; bounds = this.get_tile_meter_bounds(tx, ty, level); ref = this.utils.meters_extent_to_geographic(bounds), minLon = ref[0], minLat = ref[1], maxLon = ref[2], maxLat = ref[3]; return [minLon, minLat, maxLon, maxLat]; }; MercatorTileSource.prototype.get_tiles_by_extent = function(extent, level, tile_border) { var j, k, ref, ref1, ref2, ref3, ref4, ref5, tiles, tx, txmax, txmin, ty, tymax, tymin, xmax, xmin, ymax, ymin; if (tile_border == null) { tile_border = 1; } xmin = extent[0], ymin = extent[1], xmax = extent[2], ymax = extent[3]; ref = this.meters_to_tile(xmin, ymin, level), txmin = ref[0], tymin = ref[1]; ref1 = this.meters_to_tile(xmax, ymax, level), txmax = ref1[0], tymax = ref1[1]; txmin -= tile_border; tymin -= tile_border; txmax += tile_border; tymax += tile_border; tiles = []; for (ty = j = ref2 = tymax, ref3 = tymin; j >= ref3; ty = j += -1) { for (tx = k = ref4 = txmin, ref5 = txmax; k <= ref5; tx = k += 1) { if (this.is_valid_tile(tx, ty, level)) { tiles.push([tx, ty, level, this.get_tile_meter_bounds(tx, ty, level)]); } } } tiles = this.sort_tiles_from_center(tiles, [txmin, tymin, txmax, tymax]); return tiles; }; MercatorTileSource.prototype.quadkey_to_tile_xyz = function(quadKey) { 'Computes tile x, y and z values based on quadKey.'; var i, j, mask, ref, tileX, tileY, tileZ, value; tileX = 0; tileY = 0; tileZ = quadKey.length; for (i = j = ref = tileZ; j > 0; i = j += -1) { value = quadKey.charAt(tileZ - i); mask = 1 << (i - 1); switch (value) { case '0': continue; case '1': tileX |= mask; break; case '2': tileY |= mask; break; case '3': tileX |= mask; tileY |= mask; break; default: throw new TypeError("Invalid Quadkey: " + quadKey); } } return [tileX, tileY, tileZ]; }; MercatorTileSource.prototype.tile_xyz_to_quadkey = function(x, y, z) { 'Computes quadkey value based on tile x, y and z values.'; var digit, i, j, mask, quadKey, ref; quadKey = ''; for (i = j = ref = z; j > 0; i = j += -1) { digit = 0; mask = 1 << (i - 1); if ((x & mask) !== 0) { digit += 1; } if ((y & mask) !== 0) { digit += 2; } quadKey += digit.toString(); } return quadKey; }; MercatorTileSource.prototype.children_by_tile_xyz = function(x, y, z) { var b, child_tile_xyz, i, j, quad_key, ref; quad_key = this.tile_xyz_to_quadkey(x, y, z); child_tile_xyz = []; for (i = j = 0; j <= 3; i = j += 1) { ref = this.quadkey_to_tile_xyz(quad_key + i.toString()), x = ref[0], y = ref[1], z = ref[2]; b = this.get_tile_meter_bounds(x, y, z); if (b != null) { child_tile_xyz.push([x, y, z, b]); } } return child_tile_xyz; }; MercatorTileSource.prototype.parent_by_tile_xyz = function(x, y, z) { var parent_quad_key, quad_key; quad_key = this.tile_xyz_to_quadkey(x, y, z); parent_quad_key = quad_key.substring(0, quad_key.length - 1); return this.quadkey_to_tile_xyz(parent_quad_key); }; MercatorTileSource.prototype.get_closest_parent_by_tile_xyz = function(x, y, z) { var quad_key, ref, ref1, ref2, world_x; world_x = this.calculate_world_x_by_tile_xyz(x, y, z); ref = this.normalize_xyz(x, y, z), x = ref[0], y = ref[1], z = ref[2]; quad_key = this.tile_xyz_to_quadkey(x, y, z); while (quad_key.length > 0) { quad_key = quad_key.substring(0, quad_key.length - 1); ref1 = this.quadkey_to_tile_xyz(quad_key), x = ref1[0], y = ref1[1], z = ref1[2]; ref2 = this.denormalize_xyz(x, y, z, world_x), x = ref2[0], y = ref2[1], z = ref2[2]; if (this.tile_xyz_to_key(x, y, z) in this.tiles) { return [x, y, z]; } } return [0, 0, 0]; }; MercatorTileSource.prototype.normalize_xyz = function(x, y, z) { var tile_count; if (this.wrap_around) { tile_count = Math.pow(2, z); return [((x % tile_count) + tile_count) % tile_count, y, z]; } else { return [x, y, z]; } }; MercatorTileSource.prototype.denormalize_xyz = function(x, y, z, world_x) { return [x + world_x * Math.pow(2, z), y, z]; }; MercatorTileSource.prototype.denormalize_meters = function(meters_x, meters_y, level, world_x) { return [meters_x + world_x * 2 * Math.PI * 6378137, meters_y]; }; MercatorTileSource.prototype.calculate_world_x_by_tile_xyz = function(x, y, z) { return Math.floor(x / Math.pow(2, z)); }; return MercatorTileSource; })(TileSource);