Skip to content

Commit

Permalink
refacto: migrate Tile to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
Desplandis committed Dec 19, 2024
1 parent 3f367b8 commit 88ad67d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 28 deletions.
52 changes: 32 additions & 20 deletions src/Core/Tile/Tile.js → src/Core/Tile/Tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const _tmsCoord = new THREE.Vector2();
const _dimensionTile = new THREE.Vector2();
const r = { row: 0, col: 0, invDiff: 0 };

function _rowColfromParent(/** @type {Tile} */ tile, /** @type {number} */ zoom) {
function _rowColfromParent(tile: Tile, zoom: number) {
const diffLevel = tile.zoom - zoom;
const diff = 2 ** diffLevel;
r.invDiff = 1 / diff;
Expand All @@ -24,6 +24,13 @@ const _extent2 = new Extent('EPSG:4326');
const _c = new Coordinates('EPSG:4326', 0, 0);

class Tile {
readonly isTile: true;

crs: string;
zoom: number;
row: number;
col: number;

/**
* Tile is a geographical bounding rectangle defined by zoom, row and column.

Check warning on line 35 in src/Core/Tile/Tile.ts

View workflow job for this annotation

GitHub Actions / Build bundle, check Linter and generate documentation

This line has a comment length of 81. Maximum allowed is 80
*
Expand All @@ -32,7 +39,7 @@ class Tile {
* @param {number} [row=0] row value

Check warning on line 39 in src/Core/Tile/Tile.ts

View workflow job for this annotation

GitHub Actions / Build bundle, check Linter and generate documentation

tsdoc-param-tag-missing-hyphen: The @param block should be followed by a parameter name and then a hyphen

Check warning on line 39 in src/Core/Tile/Tile.ts

View workflow job for this annotation

GitHub Actions / Build bundle, check Linter and generate documentation

tsdoc-param-tag-with-invalid-type: The @param block should not include a JSDoc-style '{type}'

Check warning on line 39 in src/Core/Tile/Tile.ts

View workflow job for this annotation

GitHub Actions / Build bundle, check Linter and generate documentation

tsdoc-param-tag-with-invalid-optional-name: The @param should not include a JSDoc-style optional name; it must not be enclosed in '[ ]' brackets
* @param {number} [col=0] column value

Check warning on line 40 in src/Core/Tile/Tile.ts

View workflow job for this annotation

GitHub Actions / Build bundle, check Linter and generate documentation

tsdoc-param-tag-missing-hyphen: The @param block should be followed by a parameter name and then a hyphen
*/
constructor(crs, zoom = 0, row = 0, col = 0) {
constructor(crs: string, zoom = 0, row = 0, col = 0) {
this.isTile = true;

this.crs = crs;
Expand All @@ -55,20 +62,20 @@ class Tile {
* @param {Extent} target copy the destination to target.
* @return {Extent}
*/
toExtent(crs, target) {
toExtent(crs: string, target = new Extent('EPSG:4326')) {
CRS.isValid(crs);
target = target || new Extent('EPSG:4326');
const { epsg, globalExtent, globalDimension } = getInfoTms(this.crs);
const countTiles = getCountTiles(this.crs, this.zoom);

_dimensionTile.set(1, 1).divide(countTiles).multiply(globalDimension);

target.west = globalExtent.west + (globalDimension.x - _dimensionTile.x * (countTiles.x - this.col));
target.west = globalExtent.west +
(globalDimension.x - _dimensionTile.x * (countTiles.x - this.col));
target.east = target.west + _dimensionTile.x;
target.south = globalExtent.south + _dimensionTile.y * (countTiles.y - this.row - 1);
target.south = globalExtent.south +
_dimensionTile.y * (countTiles.y - this.row - 1);
target.north = target.south + _dimensionTile.y;
target.crs = epsg;
target.zoom = this.zoom;

return crs == epsg ? target : target.as(crs, target);
}
Expand All @@ -80,14 +87,14 @@ class Tile {
*
* @return {boolean}
*/
isInside(tile) {
isInside(tile: Tile) {
if (this.zoom == tile.zoom) {
return this.row == tile.row &&
this.col == tile.col;
} else if (this.zoom < tile.zoom) {
return false;
} else {
_rowColfromParent(this, tile.zoom);
const r = _rowColfromParent(this, tile.zoom);
return r.row == tile.row && r.col == tile.col;
}
}
Expand All @@ -99,12 +106,12 @@ class Tile {
* @param {THREE.Vector4} target copy the result to target.
* @return {THREE.Vector4} {x: translation on west-east, y: translation on south-north, z: scale on west-east, w: scale on south-north}
*/
offsetToParent(tile, target = new THREE.Vector4()) {
offsetToParent(tile: Tile, target = new THREE.Vector4()) {
if (this.crs != tile.crs) {
throw new Error('unsupported mix');
}

_rowColfromParent(this, tile.zoom);
const r = _rowColfromParent(this, tile.zoom);
return target.set(
this.col * r.invDiff - r.col,
this.row * r.invDiff - r.row,
Expand All @@ -117,9 +124,9 @@ class Tile {
* @param {number} levelParent level of parent.
* @return {Tile}
*/
tiledExtentParent(levelParent) {
tiledExtentParent(levelParent: number) {
if (levelParent && levelParent < this.zoom) {
_rowColfromParent(this, levelParent);
const r = _rowColfromParent(this, levelParent);
return new Tile(this.crs, levelParent, r.row, r.col);
} else {
return this;
Expand Down Expand Up @@ -148,7 +155,7 @@ class Tile {
* @param {Tile} tile
* @return {Tile} copied extent
*/
copy(tile) {
copy(tile: Tile): this {
this.crs = tile.crs;
return this.set(tile.zoom, tile.row, tile.col);
}
Expand All @@ -168,15 +175,16 @@ class Tile {
* @param {string} tms
* @returns {Tile[]}
*/
export function tiledCovering(e, tms) {
export function tiledCovering(e: Extent, tms: string) {
if (e.crs == 'EPSG:4326' && tms == 'EPSG:3857') {
const WMTS_PM = [];
const extent = _extent.copy(e).as(tms, _extent2);
const { globalExtent, globalDimension, sTs } = getInfoTms(tms);
extent.clampByExtent(globalExtent);
extent.planarDimensions(_dimensionTile);

const zoom = (e.zoom + 1) || Math.floor(Math.log2(Math.round(globalDimension.x / (_dimensionTile.x * sTs.x))));
const zoom = Math.floor(Math.log2(
Math.round(globalDimension.x / (_dimensionTile.x * sTs.x))));
const countTiles = getCountTiles(tms, zoom);
const center = extent.center(_c);

Expand All @@ -185,7 +193,8 @@ export function tiledCovering(e, tms) {
_tmsCoord.divide(globalDimension).multiply(countTiles).floor();

// ]N; N+1] => N
const maxRow = Math.ceil((globalExtent.north - extent.south) / globalDimension.x * countTiles.y) - 1;
const maxRow = Math.ceil(
(globalExtent.north - extent.south) / globalDimension.x * countTiles.y) - 1;

for (let r = maxRow; r >= _tmsCoord.y; r--) {
WMTS_PM.push(new Tile(tms, zoom, r, _tmsCoord.x));
Expand All @@ -198,12 +207,15 @@ export function tiledCovering(e, tms) {
const center = e.center(_c);
e.planarDimensions(_dimensionTile);
// Each level has 2^n * 2^n tiles...
// ... so we count how many tiles of the same width as tile we can fit in the layer
// ... so we count how many tiles of the same width as tile we can fit
// in the layer
// ... 2^zoom = tilecount => zoom = log2(tilecount)
const zoom = Math.floor(Math.log2(Math.round(globalDimension.x / (_dimensionTile.x * sTs.x))));
const zoom = Math.floor(Math.log2(
Math.round(globalDimension.x / (_dimensionTile.x * sTs.x))));
const countTiles = getCountTiles(tms, zoom);

// Now that we have computed zoom, we can deduce x and y (or row / column)
// Now that we have computed zoom, we can deduce x and y (or row /
// column)
_tmsCoord.x = center.x - globalExtent.west;
_tmsCoord.y = isInverted ? globalExtent.north - center.y : center.y - globalExtent.south;
_tmsCoord.divide(globalDimension).multiply(countTiles).floor();
Expand Down
19 changes: 11 additions & 8 deletions src/Core/Tile/TileGrid.js → src/Core/Tile/TileGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import Extent from '../Geographic/Extent';
const _countTiles = new THREE.Vector2();
const _dim = new THREE.Vector2();

export const globalExtentTMS = new Map();
export const schemeTiles = new Map();
export const globalExtentTMS: Map<string, Extent> = new Map();
export const schemeTiles: Map<string, THREE.Vector2> = new Map();

const extent4326 = new Extent('EPSG:4326', -180, 180, -90, 90);
globalExtentTMS.set('EPSG:4326', extent4326);
Expand All @@ -17,14 +17,17 @@ const extent3857 = extent4326.as('EPSG:3857');
extent3857.clampSouthNorth(extent3857.west, extent3857.east);
globalExtentTMS.set('EPSG:3857', extent3857);

schemeTiles.set('default', new THREE.Vector2(1, 1));
schemeTiles.set('EPSG:3857', schemeTiles.get('default'));
const defaultScheme = new THREE.Vector2(1, 1);
schemeTiles.set('EPSG:3857', defaultScheme);
schemeTiles.set('EPSG:4326', new THREE.Vector2(2, 1));

export function getInfoTms(/** @type {string} */ crs) {
export function getInfoTms(crs: string) {
const globalExtent = globalExtentTMS.get(crs);
if (!globalExtent) {
throw new Error(`The tile matrix set ${crs} is not defined.`);
}
const globalDimension = globalExtent.planarDimensions(_dim);
const sTs = schemeTiles.get(crs) || schemeTiles.get('default');
const sTs = schemeTiles.get(crs) ?? defaultScheme;
// The isInverted parameter is to be set to the correct value, true or false
// (default being false) if the computation of the coordinates needs to be
// inverted to match the same scheme as OSM, Google Maps or other system.
Expand All @@ -35,8 +38,8 @@ export function getInfoTms(/** @type {string} */ crs) {
return { epsg: crs, globalExtent, globalDimension, sTs, isInverted };
}

export function getCountTiles(/** @type {string} */ crs, /** @type {number} */ zoom) {
const sTs = schemeTiles.get(crs) || schemeTiles.get('default');
export function getCountTiles(crs: string, zoom: number) {
const sTs = schemeTiles.get(crs) || defaultScheme;
const count = 2 ** zoom;
_countTiles.set(count, count).multiply(sTs);
return _countTiles;
Expand Down

0 comments on commit 88ad67d

Please sign in to comment.