3d-tiles-renderer
Version:
https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification
155 lines (108 loc) • 4.34 kB
JavaScript
// Support for XYZ / Slippy tile systems
import { EllipsoidProjectionTilesPlugin } from './EllipsoidProjectionTilesPlugin.js';
import { MathUtils } from 'three';
// https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
export class XYZTilesPlugin extends EllipsoidProjectionTilesPlugin {
constructor( options = {} ) {
const {
levels = 20,
tileDimension = 256,
pixelSize = 1e-5,
...rest
} = options;
super( { pixelSize, ...rest } );
this.name = 'XYZ_TILES_PLUGIN';
this.tileDimension = tileDimension;
this.levels = levels;
this.url = null;
}
async loadRootTileSet() {
// transform the url
const { tiles, tiling, projection, tileDimension, levels } = this;
projection.setScheme( 'EPSG:3857' );
tiling.flipY = true;
tiling.setProjection( projection );
tiling.generateLevels( levels, 1, 1, {
tilePixelWidth: tileDimension,
tilePixelHeight: tileDimension,
} );
// initialize url
let url = tiles.rootURL;
tiles.invokeAllPlugins( plugin => url = plugin.preprocessURL ? plugin.preprocessURL( url, null ) : url );
this.url = url;
return this.getTileset( url );
}
getUrl( x, y, level ) {
return this.url.replace( '{z}', level ).replace( '{x}', x ).replace( '{y}', y );
}
}
// Support for TMS tiles
// https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
// NOTE: Most, if not all, TMS generation implementations do not correctly support the Origin tag
// and tile index offsets, including CesiumJS and Ion.
export class TMSTilesPlugin extends EllipsoidProjectionTilesPlugin {
constructor( ...args ) {
super( ...args );
this.name = 'TMS_TILES_PLUGIN';
this.url = null;
}
loadRootTileSet() {
const url = new URL( 'tilemapresource.xml', this.tiles.rootURL ).toString();
return this.tiles
.invokeOnePlugin( plugin => plugin.fetchData && plugin.fetchData( url, this.tiles.fetchOptions ) )
.then( res => res.text() )
.then( text => {
const { projection, tiling } = this;
// elements
const xml = new DOMParser().parseFromString( text, 'text/xml' );
const boundingBox = xml.querySelector( 'BoundingBox' );
const origin = xml.querySelector( 'Origin' );
const tileFormat = xml.querySelector( 'TileFormat' );
const tileSets = xml.querySelector( 'TileSets' ).querySelectorAll( 'TileSet' );
// tile set definitions
const tileSetList = [ ...tileSets ]
.map( ts => ( {
href: parseInt( ts.getAttribute( 'href' ) ),
unitsPerPixel: parseFloat( ts.getAttribute( 'units-per-pixel' ) ),
order: parseInt( ts.getAttribute( 'order' ) ),
} ) )
.sort( ( a, b ) => {
return a.order - b.order;
} );
// bounding box
const minX = parseFloat( boundingBox.getAttribute( 'minx' ) ) * MathUtils.DEG2RAD;
const maxX = parseFloat( boundingBox.getAttribute( 'maxx' ) ) * MathUtils.DEG2RAD;
const minY = parseFloat( boundingBox.getAttribute( 'miny' ) ) * MathUtils.DEG2RAD;
const maxY = parseFloat( boundingBox.getAttribute( 'maxy' ) ) * MathUtils.DEG2RAD;
// origin in lat / lon
const originX = parseFloat( origin.getAttribute( 'x' ) ) * MathUtils.DEG2RAD;
const originY = parseFloat( origin.getAttribute( 'y' ) ) * MathUtils.DEG2RAD;
// image dimensions in pixels
const tileWidth = parseInt( tileFormat.getAttribute( 'width' ) );
const tileHeight = parseInt( tileFormat.getAttribute( 'height' ) );
const extension = tileFormat.getAttribute( 'extension' );
const srs = xml.querySelector( 'SRS' ).textContent;
// assign settings
this.extension = extension;
this.url = this.tiles.rootURL;
this.tileSets = tileSetList;
// initialize tiling and projection schemes
projection.setScheme( srs );
tiling.setOrigin( originX, originY );
tiling.setBounds( minX, minY, maxX, maxY );
tiling.setProjection( projection );
tileSetList.forEach( ( { order } ) => {
tiling.setLevel( order, {
tileCountX: projection.tileCountX * 2 ** order,
tilePixelWidth: tileWidth,
tilePixelHeight: tileHeight,
} );
} );
return this.getTileset( url );
} );
}
getUrl( x, y, level ) {
const { url, extension, tileSets, tiling } = this;
return new URL( `${ parseInt( tileSets[ level - tiling.minLevel ].href ) }/${ x }/${ y }.${ extension }`, url ).toString();
}
}