mirror of
https://github.com/rastapasta/mapscii.git
synced 2024-11-28 11:03:35 +01:00
Translate to ESM (ECMAScript Module)
This commit is contained in:
parent
76f541db46
commit
034f561fa4
@ -1,22 +1,23 @@
|
||||
module.exports = {
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"es2021": true,
|
||||
"jest": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:jest/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
2,
|
||||
{
|
||||
"SwitchCase": 1
|
||||
"SwitchCase": 1
|
||||
}
|
||||
],
|
||||
"linebreak-style": [
|
||||
@ -33,4 +34,4 @@ module.exports = {
|
||||
"always"
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
10
main.js
10
main.js
@ -7,11 +7,11 @@
|
||||
|
||||
TODO: params parsing and so on
|
||||
#*/
|
||||
'use strict';
|
||||
const config = require('./src/config');
|
||||
const Mapscii = require('./src/Mapscii');
|
||||
const argv = require('yargs')
|
||||
.option('latitude', {
|
||||
import config from './src/config.js';
|
||||
import Mapscii from './src/Mapscii.js';
|
||||
import yargs from 'yargs';
|
||||
|
||||
const argv = yargs().option('latitude', {
|
||||
alias: 'lat',
|
||||
description: 'Latitude of initial centre',
|
||||
default: config.initialLat,
|
||||
|
9541
package-lock.json
generated
9541
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@ -3,10 +3,11 @@
|
||||
"version": "0.3.1",
|
||||
"description": "MapSCII is a Braille & ASCII world map renderer for your console, based on OpenStreetMap",
|
||||
"main": "main.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"lint": "eslint src",
|
||||
"start": "node main",
|
||||
"test": "jest"
|
||||
"test": "NODE_OPTIONS=--experimental-vm-modules jest"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -32,21 +33,21 @@
|
||||
"dependencies": {
|
||||
"@mapbox/vector-tile": "^1.3.1",
|
||||
"bresenham": "0.0.4",
|
||||
"earcut": "^2.2.2",
|
||||
"env-paths": "^2.2.0",
|
||||
"earcut": "^2.2.3",
|
||||
"env-paths": "^3.0.0",
|
||||
"keypress": "^0.2.1",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-fetch": "^3.2.4",
|
||||
"pbf": "^3.2.1",
|
||||
"rbush": "^3.0.1",
|
||||
"simplify-js": "^1.2.4",
|
||||
"string-width": "^4.2.0",
|
||||
"string-width": "^5.1.2",
|
||||
"term-mouse": "^0.2.2",
|
||||
"x256": "0.0.2",
|
||||
"yargs": "^15.4.1"
|
||||
"yargs": "^17.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^7.8.1",
|
||||
"eslint-plugin-jest": "^24.0.0",
|
||||
"jest": "^26.4.2"
|
||||
"eslint": "^8.14.0",
|
||||
"eslint-plugin-jest": "^26.1.5",
|
||||
"jest": "^28.0.3"
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,9 @@
|
||||
|
||||
Will either be merged into node-drawille or become an own module at some point
|
||||
*/
|
||||
'use strict';
|
||||
const stringWidth = require('string-width');
|
||||
const config = require('./config');
|
||||
const utils = require('./utils');
|
||||
import stringWidth from 'string-width';
|
||||
import config from './config.js';
|
||||
import * as utils from './utils.js';
|
||||
|
||||
const asciiMap = {
|
||||
// '▬': [2+32, 4+64],
|
||||
@ -29,7 +28,7 @@ const asciiMap = {
|
||||
};
|
||||
const termReset = '\x1B[39;49m';
|
||||
|
||||
class BrailleBuffer {
|
||||
export default class BrailleBuffer {
|
||||
constructor(width, height) {
|
||||
this.brailleMap = [[0x1, 0x8],[0x2, 0x10],[0x4, 0x20],[0x40, 0x80]];
|
||||
|
||||
@ -207,5 +206,3 @@ class BrailleBuffer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BrailleBuffer;
|
||||
|
@ -11,11 +11,11 @@
|
||||
Will most likely be turned into a stand alone module at some point
|
||||
*/
|
||||
'use strict';
|
||||
const bresenham = require('bresenham');
|
||||
const earcut = require('earcut');
|
||||
const BrailleBuffer = require('./BrailleBuffer');
|
||||
import bresenham from 'bresenham';
|
||||
import earcut from 'earcut';
|
||||
import BrailleBuffer from './BrailleBuffer.js';
|
||||
|
||||
class Canvas {
|
||||
export default class Canvas {
|
||||
constructor(width, height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
@ -198,5 +198,3 @@ class Canvas {
|
||||
}
|
||||
|
||||
Canvas.prototype.stack = [];
|
||||
|
||||
module.exports = Canvas;
|
||||
|
@ -5,11 +5,10 @@
|
||||
Using 2D spatial indexing to avoid overlapping labels and markers
|
||||
and to find labels underneath a mouse cursor's position
|
||||
*/
|
||||
'use strict';
|
||||
const RBush = require('rbush');
|
||||
const stringWidth = require('string-width');
|
||||
import RBush from 'rbush';
|
||||
import stringWidth from 'string-width';
|
||||
|
||||
module.exports = class LabelBuffer {
|
||||
export default class LabelBuffer {
|
||||
|
||||
constructor() {
|
||||
this.tree = new RBush();
|
||||
@ -54,4 +53,4 @@ module.exports = class LabelBuffer {
|
||||
maxY: y+margin/2,
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -4,17 +4,16 @@
|
||||
|
||||
UI and central command center
|
||||
*/
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
const keypress = require('keypress');
|
||||
const TermMouse = require('term-mouse');
|
||||
import fs from 'fs';
|
||||
import keypress from 'keypress';
|
||||
import TermMouse from 'term-mouse';
|
||||
|
||||
const Renderer = require('./Renderer');
|
||||
const TileSource = require('./TileSource');
|
||||
const utils = require('./utils');
|
||||
let config = require('./config');
|
||||
import Renderer from './Renderer.js';
|
||||
import TileSource from './TileSource.js';
|
||||
import * as utils from './utils.js';
|
||||
import MapsciiConfig from './config.js';
|
||||
|
||||
class Mapscii {
|
||||
export default class Mapscii {
|
||||
constructor(options) {
|
||||
this.width = null;
|
||||
this.height = null;
|
||||
@ -32,16 +31,19 @@ class Mapscii {
|
||||
|
||||
this.zoom = 0;
|
||||
this.minZoom = null;
|
||||
config = Object.assign(config, options);
|
||||
this.config = {
|
||||
...MapsciiConfig,
|
||||
...options,
|
||||
};
|
||||
|
||||
this.center = {
|
||||
lat: config.initialLat,
|
||||
lon: config.initialLon
|
||||
lat: this.config.initialLat,
|
||||
lon: this.config.initialLon,
|
||||
};
|
||||
}
|
||||
|
||||
async init() {
|
||||
if (!config.headless) {
|
||||
if (!this.config.headless) {
|
||||
this._initKeyboard();
|
||||
this._initMouse();
|
||||
}
|
||||
@ -54,23 +56,23 @@ class Mapscii {
|
||||
|
||||
_initTileSource() {
|
||||
this.tileSource = new TileSource();
|
||||
this.tileSource.init(config.source);
|
||||
this.tileSource.init(this.config.source);
|
||||
}
|
||||
|
||||
_initKeyboard() {
|
||||
keypress(config.input);
|
||||
if (config.input.setRawMode) {
|
||||
config.input.setRawMode(true);
|
||||
keypress(this.config.input);
|
||||
if (this.config.input.setRawMode) {
|
||||
this.config.input.setRawMode(true);
|
||||
}
|
||||
config.input.resume();
|
||||
this.config.input.resume();
|
||||
|
||||
config.input.on('keypress', (ch, key) => this._onKey(key));
|
||||
this.config.input.on('keypress', (ch, key) => this._onKey(key));
|
||||
}
|
||||
|
||||
_initMouse() {
|
||||
this.mouse = TermMouse({
|
||||
input: config.input,
|
||||
output: config.output,
|
||||
input: this.config.input,
|
||||
output: this.config.output,
|
||||
});
|
||||
this.mouse.start();
|
||||
|
||||
@ -80,21 +82,21 @@ class Mapscii {
|
||||
}
|
||||
|
||||
_initRenderer() {
|
||||
const style = JSON.parse(fs.readFileSync(config.styleFile, 'utf8'));
|
||||
this.renderer = new Renderer(config.output, this.tileSource, style);
|
||||
const style = JSON.parse(fs.readFileSync(this.config.styleFile, 'utf8'));
|
||||
this.renderer = new Renderer(this.config.output, this.tileSource, style);
|
||||
|
||||
config.output.on('resize', () => {
|
||||
this.config.output.on('resize', () => {
|
||||
this._resizeRenderer();
|
||||
this._draw();
|
||||
});
|
||||
|
||||
this._resizeRenderer();
|
||||
this.zoom = (config.initialZoom !== null) ? config.initialZoom : this.minZoom;
|
||||
this.zoom = (this.config.initialZoom !== null) ? this.config.initialZoom : this.minZoom;
|
||||
}
|
||||
|
||||
_resizeRenderer() {
|
||||
this.width = config.size && config.size.width ? config.size.width * 2 : config.output.columns >> 1 << 2;
|
||||
this.height = config.size && config.size.height ? config.size.height * 4 : config.output.rows * 4 - 4;
|
||||
this.width = this.config.size && this.config.size.width ? this.config.size.width * 2 : this.config.output.columns >> 1 << 2;
|
||||
this.height = this.config.size && this.config.size.height ? this.config.size.height * 4 : this.config.output.rows * 4 - 4;
|
||||
|
||||
this.minZoom = 4-Math.log(4096/this.width)/Math.LN2;
|
||||
|
||||
@ -142,7 +144,7 @@ class Mapscii {
|
||||
const targetMouseLonLat = this._colrow2ll(event.x, event.y);
|
||||
|
||||
// zoom toward the center
|
||||
this.zoomBy(config.zoomStep * (event.button === 'up' ? 1 : -1));
|
||||
this.zoomBy(this.config.zoomStep * (event.button === 'up' ? 1 : -1));
|
||||
|
||||
// the location the pointer ended up after zooming
|
||||
const offsetMouseLonLat = this._colrow2ll(event.x, event.y);
|
||||
@ -171,7 +173,7 @@ class Mapscii {
|
||||
if (event.x < 0 || event.x > this.width/2 || event.y < 0 || event.y > this.height/4) {
|
||||
return;
|
||||
}
|
||||
if (config.mouseCallback && !config.mouseCallback(event)) {
|
||||
if (this.config.mouseCallback && !this.config.mouseCallback(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -207,25 +209,25 @@ class Mapscii {
|
||||
}
|
||||
|
||||
_onKey(key) {
|
||||
if (config.keyCallback && !config.keyCallback(key)) return;
|
||||
if (this.config.keyCallback && !this.config.keyCallback(key)) return;
|
||||
if (!key || !key.name) return;
|
||||
|
||||
// check if the pressed key is configured
|
||||
let draw = true;
|
||||
switch (key.name) {
|
||||
case 'q':
|
||||
if (config.quitCallback) {
|
||||
config.quitCallback();
|
||||
if (this.config.quitCallback) {
|
||||
this.config.quitCallback();
|
||||
} else {
|
||||
process.exit(0);
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
this.zoomBy(config.zoomStep);
|
||||
this.zoomBy(this.config.zoomStep);
|
||||
break;
|
||||
case 'y':
|
||||
case 'z':
|
||||
this.zoomBy(-config.zoomStep);
|
||||
this.zoomBy(-this.config.zoomStep);
|
||||
break;
|
||||
case 'left':
|
||||
case 'h':
|
||||
@ -244,7 +246,7 @@ class Mapscii {
|
||||
this.moveBy(-6/Math.pow(2, this.zoom), 0);
|
||||
break;
|
||||
case 'c':
|
||||
config.useBraille = !config.useBraille;
|
||||
this.config.useBraille = !this.config.useBraille;
|
||||
break;
|
||||
default:
|
||||
draw = false;
|
||||
@ -277,22 +279,22 @@ class Mapscii {
|
||||
}
|
||||
|
||||
notify(text) {
|
||||
config.onUpdate && config.onUpdate();
|
||||
if (!config.headless) {
|
||||
this.config.onUpdate && this.config.onUpdate();
|
||||
if (!this.config.headless) {
|
||||
this._write('\r\x1B[K' + text);
|
||||
}
|
||||
}
|
||||
|
||||
_write(output) {
|
||||
config.output.write(output);
|
||||
this.config.output.write(output);
|
||||
}
|
||||
|
||||
zoomBy(step) {
|
||||
if (this.zoom+step < this.minZoom) {
|
||||
return this.zoom = this.minZoom;
|
||||
}
|
||||
if (this.zoom+step > config.maxZoom) {
|
||||
return this.zoom = config.maxZoom;
|
||||
if (this.zoom+step > this.config.maxZoom) {
|
||||
return this.zoom = this.config.maxZoom;
|
||||
}
|
||||
|
||||
this.zoom += step;
|
||||
@ -309,5 +311,3 @@ class Mapscii {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Mapscii;
|
||||
|
@ -5,16 +5,16 @@
|
||||
The Console Vector Tile renderer - bäm!
|
||||
*/
|
||||
'use strict';
|
||||
const x256 = require('x256');
|
||||
const simplify = require('simplify-js');
|
||||
import x256 from 'x256';
|
||||
import simplify from 'simplify-js';
|
||||
|
||||
const Canvas = require('./Canvas');
|
||||
const LabelBuffer = require('./LabelBuffer');
|
||||
const Styler = require('./Styler');
|
||||
const utils = require('./utils');
|
||||
const config = require('./config');
|
||||
import Canvas from './Canvas.js';
|
||||
import LabelBuffer from './LabelBuffer.js';
|
||||
import Styler from './Styler.js';
|
||||
import * as utils from './utils.js';
|
||||
import config from './config.js';
|
||||
|
||||
class Renderer {
|
||||
export default class Renderer {
|
||||
constructor(output, tileSource, style) {
|
||||
this.output = output;
|
||||
this.tileSource = tileSource;
|
||||
@ -331,5 +331,3 @@ Renderer.prototype.lastDrawAt = 0;
|
||||
Renderer.prototype.labelBuffer = null;
|
||||
Renderer.prototype.tileSource = null;
|
||||
Renderer.prototype.tilePadding = 64;
|
||||
|
||||
module.exports = Renderer;
|
||||
|
@ -8,9 +8,8 @@
|
||||
Compiles layer filter instructions into a chain of true/false returning
|
||||
anonymous functions to improve rendering speed compared to realtime parsing.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
class Styler {
|
||||
export default class Styler {
|
||||
constructor(style) {
|
||||
this.styleById = {};
|
||||
this.styleByLayer = {};
|
||||
@ -129,5 +128,3 @@ class Styler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Styler;
|
||||
|
27
src/Tile.js
27
src/Tile.js
@ -4,17 +4,16 @@
|
||||
|
||||
Handling of and access to single VectorTiles
|
||||
*/
|
||||
'use strict';
|
||||
const VectorTile = require('@mapbox/vector-tile').VectorTile;
|
||||
const Protobuf = require('pbf');
|
||||
const zlib = require('zlib');
|
||||
const RBush = require('rbush');
|
||||
const x256 = require('x256');
|
||||
import { VectorTile } from '@mapbox/vector-tile';
|
||||
import Protobuf from 'pbf';
|
||||
import zlib from 'zlib';
|
||||
import RBush from 'rbush';
|
||||
import x256 from 'x256';
|
||||
|
||||
const config = require('./config');
|
||||
const utils = require('./utils');
|
||||
import config from './config.js';
|
||||
import * as utils from './utils.js';
|
||||
|
||||
class Tile {
|
||||
export default class Tile {
|
||||
constructor(styler) {
|
||||
this.styler = styler;
|
||||
}
|
||||
@ -122,10 +121,10 @@ class Tile {
|
||||
}
|
||||
|
||||
_addBoundaries(deep, data) {
|
||||
let minX = 2e308;
|
||||
let maxX = -2e308;
|
||||
let minY = 2e308;
|
||||
let maxY = -2e308;
|
||||
let minX = 2e307;
|
||||
let maxX = -2e307;
|
||||
let minY = 2e307;
|
||||
let maxY = -2e307;
|
||||
const points = (deep ? data.points[0] : data.points);
|
||||
for (const p of points) {
|
||||
if (p.x < minX) minX = p.x;
|
||||
@ -163,5 +162,3 @@ class Tile {
|
||||
}
|
||||
|
||||
Tile.prototype.layers = {};
|
||||
|
||||
module.exports = Tile;
|
||||
|
@ -6,15 +6,14 @@
|
||||
* remote TileServer
|
||||
* local MBTiles and VectorTiles
|
||||
*/
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const fetch = require('node-fetch');
|
||||
const envPaths = require('env-paths');
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import fetch from 'node-fetch';
|
||||
import envPaths from 'env-paths';
|
||||
const paths = envPaths('mapscii');
|
||||
|
||||
const Tile = require('./Tile');
|
||||
const config = require('./config');
|
||||
import Tile from './Tile.js';
|
||||
import config from './config.js';
|
||||
|
||||
// https://github.com/mapbox/node-mbtiles has native build dependencies (sqlite3)
|
||||
// To maximize MapSCII’s compatibility, MBTiles support must be manually added via
|
||||
@ -30,7 +29,7 @@ const modes = {
|
||||
HTTP: 3,
|
||||
};
|
||||
|
||||
class TileSource {
|
||||
export default class TileSource {
|
||||
init(source) {
|
||||
this.source = source;
|
||||
|
||||
@ -109,8 +108,9 @@ class TileSource {
|
||||
promise = Promise.resolve(persistedTile);
|
||||
} else {
|
||||
promise = fetch(this.source + [z,x,y].join('/') + '.pbf')
|
||||
.then((res) => res.buffer())
|
||||
.then((buffer) => {
|
||||
.then((res) => res.arrayBuffer())
|
||||
.then((arrayBuffer) => {
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
if (config.persistDownloadedTiles) {
|
||||
this._persistTile(z, x, y, buffer);
|
||||
return buffer;
|
||||
@ -174,5 +174,3 @@ class TileSource {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TileSource;
|
||||
|
@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
const TileSource = require('./TileSource');
|
||||
import TileSource from './TileSource.js';
|
||||
|
||||
describe('TileSource', () => {
|
||||
describe('with a HTTP source', () => {
|
||||
|
@ -1,4 +1,10 @@
|
||||
module.exports = {
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
export default {
|
||||
language: 'en',
|
||||
|
||||
// TODO: adapt to osm2vectortiles successor openmaptiles v3)
|
||||
@ -7,7 +13,7 @@ module.exports = {
|
||||
|
||||
//source: __dirname+"/../mbtiles/regensburg.mbtiles",
|
||||
|
||||
styleFile: __dirname+'/../styles/dark.json',
|
||||
styleFile: __dirname + '/../styles/dark.json',
|
||||
|
||||
initialZoom: null,
|
||||
maxZoom: 18,
|
||||
|
175
src/utils.js
175
src/utils.js
@ -4,100 +4,95 @@
|
||||
|
||||
methods used all around
|
||||
*/
|
||||
'use strict';
|
||||
const config = require('./config');
|
||||
import config from './config.js';
|
||||
|
||||
const constants = {
|
||||
RADIUS: 6378137,
|
||||
};
|
||||
|
||||
const utils = {
|
||||
clamp: (num, min, max) => {
|
||||
if (num <= min) {
|
||||
return min;
|
||||
} else if (num >= max) {
|
||||
return max;
|
||||
} else {
|
||||
return num;
|
||||
}
|
||||
},
|
||||
|
||||
baseZoom: (zoom) => {
|
||||
return Math.min(config.tileRange, Math.max(0, Math.floor(zoom)));
|
||||
},
|
||||
|
||||
tilesizeAtZoom: (zoom) => {
|
||||
return config.projectSize * Math.pow(2, zoom-utils.baseZoom(zoom));
|
||||
},
|
||||
|
||||
deg2rad: (angle) => {
|
||||
// (angle / 180) * Math.PI
|
||||
return angle * 0.017453292519943295;
|
||||
},
|
||||
|
||||
ll2tile: (lon, lat, zoom) => {
|
||||
return {
|
||||
x: (lon+180)/360*Math.pow(2, zoom),
|
||||
y: (1-Math.log(Math.tan(lat*Math.PI/180)+1/Math.cos(lat*Math.PI/180))/Math.PI)/2*Math.pow(2, zoom),
|
||||
z: zoom,
|
||||
};
|
||||
},
|
||||
|
||||
tile2ll: (x, y, zoom) => {
|
||||
const n = Math.PI - 2*Math.PI*y/Math.pow(2, zoom);
|
||||
|
||||
return {
|
||||
lon: x/Math.pow(2, zoom)*360-180,
|
||||
lat: 180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))),
|
||||
};
|
||||
},
|
||||
|
||||
metersPerPixel: (zoom, lat = 0) => {
|
||||
return (Math.cos(lat * Math.PI/180) * 2 * Math.PI * constants.RADIUS) / (256 * Math.pow(2, zoom));
|
||||
},
|
||||
|
||||
hex2rgb: (color) => {
|
||||
if (typeof color !== 'string') return [255, 0, 0];
|
||||
|
||||
if (!/^#[a-fA-F0-9]{3,6}$/.test(color)) {
|
||||
throw new Error(`${color} isn't a supported hex color`);
|
||||
}
|
||||
|
||||
color = color.substr(1);
|
||||
const decimal = parseInt(color, 16);
|
||||
|
||||
if (color.length === 3) {
|
||||
const rgb = [decimal>>8, (decimal>>4)&15, decimal&15];
|
||||
return rgb.map((c) => {
|
||||
return c + (c<<4);
|
||||
});
|
||||
} else {
|
||||
return [(decimal>>16)&255, (decimal>>8)&255, decimal&255];
|
||||
}
|
||||
},
|
||||
|
||||
digits: (number, digits) => {
|
||||
return Math.floor(number*Math.pow(10, digits))/Math.pow(10, digits);
|
||||
},
|
||||
|
||||
normalize: (ll) => {
|
||||
if (ll.lon < -180) ll.lon += 360;
|
||||
if (ll.lon > 180) ll.lon -= 360;
|
||||
|
||||
if (ll.lat > 85.0511) ll.lat = 85.0511;
|
||||
if (ll.lat < -85.0511) ll.lat = -85.0511;
|
||||
|
||||
return ll;
|
||||
},
|
||||
|
||||
population: (val) => {
|
||||
let bits = 0;
|
||||
while (val > 0) {
|
||||
bits += val & 1;
|
||||
val >>= 1;
|
||||
}
|
||||
return bits;
|
||||
},
|
||||
export const clamp = (num, min, max) => {
|
||||
if (num <= min) {
|
||||
return min;
|
||||
} else if (num >= max) {
|
||||
return max;
|
||||
} else {
|
||||
return num;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = utils;
|
||||
export const baseZoom = (zoom) => {
|
||||
return Math.min(config.tileRange, Math.max(0, Math.floor(zoom)));
|
||||
};
|
||||
|
||||
export const tilesizeAtZoom = (zoom) => {
|
||||
return config.projectSize * Math.pow(2, zoom-baseZoom(zoom));
|
||||
};
|
||||
|
||||
export const deg2rad = (angle) => {
|
||||
// (angle / 180) * Math.PI
|
||||
return angle * 0.017453292519943295;
|
||||
};
|
||||
|
||||
export const ll2tile = (lon, lat, zoom) => {
|
||||
return {
|
||||
x: (lon+180)/360*Math.pow(2, zoom),
|
||||
y: (1-Math.log(Math.tan(lat*Math.PI/180)+1/Math.cos(lat*Math.PI/180))/Math.PI)/2*Math.pow(2, zoom),
|
||||
z: zoom,
|
||||
};
|
||||
};
|
||||
|
||||
export const tile2ll = (x, y, zoom) => {
|
||||
const n = Math.PI - 2*Math.PI*y/Math.pow(2, zoom);
|
||||
|
||||
return {
|
||||
lon: x/Math.pow(2, zoom)*360-180,
|
||||
lat: 180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))),
|
||||
};
|
||||
};
|
||||
|
||||
export const metersPerPixel = (zoom, lat = 0) => {
|
||||
return (Math.cos(lat * Math.PI/180) * 2 * Math.PI * constants.RADIUS) / (256 * Math.pow(2, zoom));
|
||||
};
|
||||
|
||||
export const hex2rgb = (color) => {
|
||||
if (typeof color !== 'string') return [255, 0, 0];
|
||||
|
||||
if (!/^#[a-fA-F0-9]{3,6}$/.test(color)) {
|
||||
throw new Error(`${color} isn't a supported hex color`);
|
||||
}
|
||||
|
||||
color = color.substr(1);
|
||||
const decimal = parseInt(color, 16);
|
||||
|
||||
if (color.length === 3) {
|
||||
const rgb = [decimal>>8, (decimal>>4)&15, decimal&15];
|
||||
return rgb.map((c) => {
|
||||
return c + (c<<4);
|
||||
});
|
||||
} else {
|
||||
return [(decimal>>16)&255, (decimal>>8)&255, decimal&255];
|
||||
}
|
||||
};
|
||||
|
||||
export const digits = (number, digits) => {
|
||||
return Math.floor(number*Math.pow(10, digits))/Math.pow(10, digits);
|
||||
};
|
||||
|
||||
export const normalize = (ll) => {
|
||||
if (ll.lon < -180) ll.lon += 360;
|
||||
if (ll.lon > 180) ll.lon -= 360;
|
||||
|
||||
if (ll.lat > 85.0511) ll.lat = 85.0511;
|
||||
if (ll.lat < -85.0511) ll.lat = -85.0511;
|
||||
|
||||
return ll;
|
||||
};
|
||||
|
||||
export const population = (val) => {
|
||||
let bits = 0;
|
||||
while (val > 0) {
|
||||
bits += val & 1;
|
||||
val >>= 1;
|
||||
}
|
||||
return bits;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
import * as utils from './utils.js';
|
||||
|
||||
describe('utils', () => {
|
||||
describe('hex2rgb', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user