/** * MapData contains the informations about how * a Map has to be interpreted. What are the bounds of the * map and how to translate coordinates into * image positions. * * @class * @see {@link mapdata.html} */ export class MapData { /** * Creates instance of MapData * * @constructor * @param {Projection}[projection] - Specifies the projection of the map (e.g. Mercator Projection). * @param {object}[opts] - Addiditonal options. * @param {[[minLat, minLng],[maxLat, maxLng]]}[opts.bounds] - Describes the minimum and maximum coordinates on the map * @param {Point}[opts.translate] - Defines a translation, when clipping is not an option (e.g. when the whole world is shown, but translated.) */ constructor(projection, opts = {}) { this.opts = Object.assign( { translate: { x: 0, y: 0 } }, opts ) this.projection = projection if (this.opts.clip) { let _cmin = this.projection.forward(this.opts.clip.min) let _cmax = this.projection.forward(this.opts.clip.max) // Swaps the y values, Mercator has it's origin bottom right, // browser coordinates start top right. let cmin = { x: _cmin.x, y: _cmax.y } let cmax = { x: _cmax.x, y: _cmin.y } this.clipExt = { coords: { min: this.opts.clip.min, max: this.opts.clip.max }, point: { min: cmin, max: cmax } } } } /** * Transforms a pixel point on the map to a geographical coordinate. * * @param {{x,y} | PIXI.Point} point - A pixel position on the map. * @returns {{x,y} | PIXI.Point} - A geographical coordinate. * @memberof MapData */ toCoordinates(point) { if (this.opts.clip) { let min = this.clipExt.point.min let max = this.clipExt.point.max let width = max.x - min.x let height = max.y - min.y point.x *= width point.y *= height point.x += min.x point.y += min.y } let coordinates = this.projection.backward(point) if (this.opts.translate) { coordinates.x -= this.opts.translate.x coordinates.y -= this.opts.translate.y } return coordinates } /** * Transform a geographical coordinate to a pixel point on the map. * * @param {{x,y} | PIXI.Point} coordinates - A point in the form of {x:lat,y:lng}. * @returns {{x,y} | PIXI.Point} point - A pixel position on the map. * @memberof MapData */ toPixel(coordinates) { let coords = { x: coordinates.x, y: coordinates.y } if (this.opts.translate) { coords.x += this.opts.translate.x coords.y += this.opts.translate.y } let point = this.projection.forward(coords) if (this.opts.clip) { let min = this.clipExt.point.min let max = this.clipExt.point.max let clippedPoint = { x: point.x - min.x, y: point.y - min.y } let width = max.x - min.x let height = max.y - min.y point.x = clippedPoint.x / width point.y = clippedPoint.y / height } return point } get clip() { let unclipped = { min: { x: 0, y: 0 }, max: { x: 1, y: 1 } } return this.opts.clip ? this.opts.clip : unclipped } /** * Bounds to pixel transforms some bounds in form of {min:{x:minLat, y:minLng},max:{x:maxLat, y:maxLng}} * to pixel coordinates. * */ getBoundaries() { // let min = this.toPixel(bounds.min) // let max = this.toPixel(bounds.max) // Y values needs to be swapped, as PIXI has it's origin // in the top-left corner and a regular map in the bottom-left corner. let boundaries = { min: { x: 0, y: 0 }, max: { x: 1, y: 1 } } return boundaries } get maxViewport() { return this.opts.clip ? this.opts.clip : this.projection.maxViewport } } export class DeepZoomMapData extends MapData { constructor(projection, tilesConfig, opts = {}) { if (tilesConfig.clip) { opts.clip = { min: { x: tilesConfig.clip.bounds.min[0], y: tilesConfig.clip.bounds.min[1] }, max: { x: tilesConfig.clip.bounds.max[0], y: tilesConfig.clip.bounds.max[1] } } } super(projection, opts) this.app = opts.app } }