Skip to content

Instantly share code, notes, and snippets.

@mollymerp
Last active August 16, 2018 00:26
Show Gist options
  • Save mollymerp/8c8c939f651b49d235fdd3df75733e09 to your computer and use it in GitHub Desktop.
Save mollymerp/8c8c939f651b49d235fdd3df75733e09 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>Frame rate capture demo</title>
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.css' />
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; width: 100%;}
.changeStyle {
position: absolute;
top: 10px;
right: 10px;
}
button {
float: right;
display: block;
padding: 5px;
margin: 0 10px;
background: #fff;
}
.mapboxgl-ctrl-fps {
padding: 5px;
}
</style>
</head>
<body>
<div id='map'></div>
<div class="changeStyle">
<button id="light">Light</button>
<button id="outdoors">Outdoors</button>
<button id="satellite-streets">Satellite Streets</button>
</div>
<script src='mapbox-gl-dev.js'></script>
<script>
mapboxgl.accessToken = "pk.eyJ1IjoibW9sbHltZXJwIiwiYSI6ImNpazdqbGtiZTAxbGNocm0ybXJ3MnNzOHAifQ.5_kJrEENbBWtqTZEv7g1-w";
var map = window.map = new mapboxgl.Map({
container: 'map',
zoom: 12.5,
center: [-77.01866, 38.888],
style: 'mapbox://styles/mapbox/streets-v10',
hash: true
});
const fps = new mapboxgl.FramerateControl();
map.addControl(fps);
const buttons = document.querySelectorAll('button');
const styleURLs = {
"satellite-streets": "mapbox://styles/mapbox/satellite-streets-v10",
"light": "mapbox://styles/mapbox/light-v9",
"outdoors": "mapbox://styles/mapbox/outdoors-v10"
}
buttons.forEach(el => {
el.addEventListener('click', ()=>{
if (styleURLs[el.id]) {
map.removeControl(fps);
map.setStyle(styleURLs[el.id]);
map.addControl(fps);
}
})
})
</script>
</body>
</html>
This file has been truncated, but you can view the full file.
/* Mapbox GL JS is licensed under the 3-Clause BSD License. Full text of license: https://github.com/mapbox/mapbox-gl-js/blob/v0.47.0/LICENSE.txt */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.mapboxgl = factory());
}(this, (function () { 'use strict';
/* eslint-disable */
var shared, worker, mapboxgl;
// define gets called three times: one for each chunk. we rely on the order
// they're imported to know which is which
function define(_, chunk) {
if (!shared) {
shared = chunk;
} else if (!worker) {
worker = chunk;
} else {
var workerBundleString = 'var sharedChunk = {}; (' + shared + ')(sharedChunk); (' + worker + ')(sharedChunk);'
var sharedChunk = {};
shared(sharedChunk);
mapboxgl = chunk(sharedChunk);
mapboxgl.workerUrl = window.URL.createObjectURL(new Blob([workerBundleString], { type: 'text/javascript' }));
}
}
define(['exports'], function (exports) { 'use strict';
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function commonjsRequire () {
throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
}
function unwrapExports (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var isBufferBrowser = function isBuffer(arg) {
return arg && typeof arg === 'object'
&& typeof arg.copy === 'function'
&& typeof arg.fill === 'function'
&& typeof arg.readUInt8 === 'function';
};
var inherits_browser = createCommonjsModule(function (module) {
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
var TempCtor = function () {};
TempCtor.prototype = superCtor.prototype;
ctor.prototype = new TempCtor();
ctor.prototype.constructor = ctor;
};
}
});
var util = createCommonjsModule(function (module, exports) {
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
var arguments$1 = arguments;
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments$1[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function(x) {
if (x === '%%') { return '%'; }
if (i >= len) { return x; }
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
exports.deprecate = function(fn, msg) {
// Allow for deprecating things in the process of starting up.
if (isUndefined(global.process)) {
return function() {
return exports.deprecate(fn, msg).apply(this, arguments);
};
}
if (process.noDeprecation === true) {
return fn;
}
var warned = false;
function deprecated() {
if (!warned) {
if (process.throwDeprecation) {
throw new Error(msg);
} else if (process.traceDeprecation) {
console.trace(msg);
} else {
console.error(msg);
}
warned = true;
}
return fn.apply(this, arguments);
}
return deprecated;
};
var debugs = {};
var debugEnviron;
exports.debuglog = function(set) {
if (isUndefined(debugEnviron))
{ debugEnviron = process.env.NODE_DEBUG || ''; }
set = set.toUpperCase();
if (!debugs[set]) {
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
var pid = process.pid;
debugs[set] = function() {
var msg = exports.format.apply(exports, arguments);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function() {};
}
}
return debugs[set];
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) { ctx.depth = arguments[2]; }
if (arguments.length >= 4) { ctx.colors = arguments[3]; }
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) { ctx.showHidden = false; }
if (isUndefined(ctx.depth)) { ctx.depth = 2; }
if (isUndefined(ctx.colors)) { ctx.colors = false; }
if (isUndefined(ctx.customInspect)) { ctx.customInspect = true; }
if (ctx.colors) { ctx.stylize = stylizeWithColor; }
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold' : [1, 22],
'italic' : [3, 23],
'underline' : [4, 24],
'inverse' : [7, 27],
'white' : [37, 39],
'grey' : [90, 39],
'black' : [30, 39],
'blue' : [34, 39],
'cyan' : [36, 39],
'green' : [32, 39],
'magenta' : [35, 39],
'red' : [31, 39],
'yellow' : [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
array.forEach(function(val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value)
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
return formatError(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
{ return ctx.stylize('undefined', 'undefined'); }
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value))
{ return ctx.stylize('' + value, 'number'); }
if (isBoolean(value))
{ return ctx.stylize('' + value, 'boolean'); }
// For some reason typeof null is "object", so special case here.
if (isNull(value))
{ return ctx.stylize('null', 'null'); }
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
keys.forEach(function(key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = output.reduce(function(prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) { numLinesEst++; }
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = isBufferBrowser;
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function() {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = inherits_browser;
exports._extend = function(origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) { return origin; }
var keys = Object.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
});
var util_1 = util.format;
var util_2 = util.deprecate;
var util_3 = util.debuglog;
var util_4 = util.inspect;
var util_5 = util.isArray;
var util_6 = util.isBoolean;
var util_7 = util.isNull;
var util_8 = util.isNullOrUndefined;
var util_9 = util.isNumber;
var util_10 = util.isString;
var util_11 = util.isSymbol;
var util_12 = util.isUndefined;
var util_13 = util.isRegExp;
var util_14 = util.isObject;
var util_15 = util.isDate;
var util_16 = util.isError;
var util_17 = util.isFunction;
var util_18 = util.isPrimitive;
var util_19 = util.isBuffer;
var util_20 = util.log;
var util_21 = util.inherits;
var util_22 = util._extend;
var assert_1 = createCommonjsModule(function (module) {
'use strict';
// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js
// original notice:
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
function compare(a, b) {
if (a === b) {
return 0;
}
var x = a.length;
var y = b.length;
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
if (a[i] !== b[i]) {
x = a[i];
y = b[i];
break;
}
}
if (x < y) {
return -1;
}
if (y < x) {
return 1;
}
return 0;
}
function isBuffer(b) {
if (global.Buffer && typeof global.Buffer.isBuffer === 'function') {
return global.Buffer.isBuffer(b);
}
return !!(b != null && b._isBuffer);
}
// based on node assert, original notice:
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var hasOwn = Object.prototype.hasOwnProperty;
var pSlice = Array.prototype.slice;
var functionsHaveNames = (function () {
return function foo() {}.name === 'foo';
}());
function pToString (obj) {
return Object.prototype.toString.call(obj);
}
function isView(arrbuf) {
if (isBuffer(arrbuf)) {
return false;
}
if (typeof global.ArrayBuffer !== 'function') {
return false;
}
if (typeof ArrayBuffer.isView === 'function') {
return ArrayBuffer.isView(arrbuf);
}
if (!arrbuf) {
return false;
}
if (arrbuf instanceof DataView) {
return true;
}
if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) {
return true;
}
return false;
}
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.
var assert = module.exports = ok;
// 2. The AssertionError is defined in assert.
// new assert.AssertionError({ message: message,
// actual: actual,
// expected: expected })
var regex = /\s*function\s+([^\(\s]*)\s*/;
// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js
function getName(func) {
if (!util.isFunction(func)) {
return;
}
if (functionsHaveNames) {
return func.name;
}
var str = func.toString();
var match = str.match(regex);
return match && match[1];
}
assert.AssertionError = function AssertionError(options) {
this.name = 'AssertionError';
this.actual = options.actual;
this.expected = options.expected;
this.operator = options.operator;
if (options.message) {
this.message = options.message;
this.generatedMessage = false;
} else {
this.message = getMessage(this);
this.generatedMessage = true;
}
var stackStartFunction = options.stackStartFunction || fail;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, stackStartFunction);
} else {
// non v8 browsers so we can have a stacktrace
var err = new Error();
if (err.stack) {
var out = err.stack;
// try to strip useless frames
var fn_name = getName(stackStartFunction);
var idx = out.indexOf('\n' + fn_name);
if (idx >= 0) {
// once we have located the function frame
// we need to strip out everything before it (and its line)
var next_line = out.indexOf('\n', idx + 1);
out = out.substring(next_line + 1);
}
this.stack = out;
}
}
};
// assert.AssertionError instanceof Error
util.inherits(assert.AssertionError, Error);
function truncate(s, n) {
if (typeof s === 'string') {
return s.length < n ? s : s.slice(0, n);
} else {
return s;
}
}
function inspect(something) {
if (functionsHaveNames || !util.isFunction(something)) {
return util.inspect(something);
}
var rawname = getName(something);
var name = rawname ? ': ' + rawname : '';
return '[Function' + name + ']';
}
function getMessage(self) {
return truncate(inspect(self.actual), 128) + ' ' +
self.operator + ' ' +
truncate(inspect(self.expected), 128);
}
// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.
// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided. All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
function fail(actual, expected, message, operator, stackStartFunction) {
throw new assert.AssertionError({
message: message,
actual: actual,
expected: expected,
operator: operator,
stackStartFunction: stackStartFunction
});
}
// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;
// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
function ok(value, message) {
if (!value) { fail(value, true, message, '==', assert.ok); }
}
assert.ok = ok;
// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);
assert.equal = function equal(actual, expected, message) {
if (actual != expected) { fail(actual, expected, message, '==', assert.equal); }
};
// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
assert.notEqual = function notEqual(actual, expected, message) {
if (actual == expected) {
fail(actual, expected, message, '!=', assert.notEqual);
}
};
// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
assert.deepEqual = function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected, false)) {
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
}
};
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
if (!_deepEqual(actual, expected, true)) {
fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual);
}
};
function _deepEqual(actual, expected, strict, memos) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
} else if (isBuffer(actual) && isBuffer(expected)) {
return compare(actual, expected) === 0;
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
} else if (util.isDate(actual) && util.isDate(expected)) {
return actual.getTime() === expected.getTime();
// 7.3 If the expected value is a RegExp object, the actual value is
// equivalent if it is also a RegExp object with the same source and
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
} else if (util.isRegExp(actual) && util.isRegExp(expected)) {
return actual.source === expected.source &&
actual.global === expected.global &&
actual.multiline === expected.multiline &&
actual.lastIndex === expected.lastIndex &&
actual.ignoreCase === expected.ignoreCase;
// 7.4. Other pairs that do not both pass typeof value == 'object',
// equivalence is determined by ==.
} else if ((actual === null || typeof actual !== 'object') &&
(expected === null || typeof expected !== 'object')) {
return strict ? actual === expected : actual == expected;
// If both values are instances of typed arrays, wrap their underlying
// ArrayBuffers in a Buffer each to increase performance
// This optimization requires the arrays to have the same type as checked by
// Object.prototype.toString (aka pToString). Never perform binary
// comparisons for Float*Arrays, though, since e.g. +0 === -0 but their
// bit patterns are not identical.
} else if (isView(actual) && isView(expected) &&
pToString(actual) === pToString(expected) &&
!(actual instanceof Float32Array ||
actual instanceof Float64Array)) {
return compare(new Uint8Array(actual.buffer),
new Uint8Array(expected.buffer)) === 0;
// 7.5 For all other Object pairs, including Array objects, equivalence is
// determined by having the same number of owned properties (as verified
// with Object.prototype.hasOwnProperty.call), the same set of keys
// (although not necessarily the same order), equivalent values for every
// corresponding key, and an identical 'prototype' property. Note: this
// accounts for both named and indexed properties on Arrays.
} else if (isBuffer(actual) !== isBuffer(expected)) {
return false;
} else {
memos = memos || {actual: [], expected: []};
var actualIndex = memos.actual.indexOf(actual);
if (actualIndex !== -1) {
if (actualIndex === memos.expected.indexOf(expected)) {
return true;
}
}
memos.actual.push(actual);
memos.expected.push(expected);
return objEquiv(actual, expected, strict, memos);
}
}
function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}
function objEquiv(a, b, strict, actualVisitedObjects) {
if (a === null || a === undefined || b === null || b === undefined)
{ return false; }
// if one is a primitive, the other must be same
if (util.isPrimitive(a) || util.isPrimitive(b))
{ return a === b; }
if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b))
{ return false; }
var aIsArgs = isArguments(a);
var bIsArgs = isArguments(b);
if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
{ return false; }
if (aIsArgs) {
a = pSlice.call(a);
b = pSlice.call(b);
return _deepEqual(a, b, strict);
}
var ka = objectKeys(a);
var kb = objectKeys(b);
var key, i;
// having the same number of owned properties (keys incorporates
// hasOwnProperty)
if (ka.length !== kb.length)
{ return false; }
//the same set of keys (although not necessarily the same order),
ka.sort();
kb.sort();
//~~~cheap key test
for (i = ka.length - 1; i >= 0; i--) {
if (ka[i] !== kb[i])
{ return false; }
}
//equivalent values for every corresponding key, and
//~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects))
{ return false; }
}
return true;
}
// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
if (_deepEqual(actual, expected, false)) {
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
}
};
assert.notDeepStrictEqual = notDeepStrictEqual;
function notDeepStrictEqual(actual, expected, message) {
if (_deepEqual(actual, expected, true)) {
fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual);
}
}
// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
assert.strictEqual = function strictEqual(actual, expected, message) {
if (actual !== expected) {
fail(actual, expected, message, '===', assert.strictEqual);
}
};
// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
if (actual === expected) {
fail(actual, expected, message, '!==', assert.notStrictEqual);
}
};
function expectedException(actual, expected) {
if (!actual || !expected) {
return false;
}
if (Object.prototype.toString.call(expected) == '[object RegExp]') {
return expected.test(actual);
}
try {
if (actual instanceof expected) {
return true;
}
} catch (e) {
// Ignore. The instanceof check doesn't work for arrow functions.
}
if (Error.isPrototypeOf(expected)) {
return false;
}
return expected.call({}, actual) === true;
}
function _tryBlock(block) {
var error;
try {
block();
} catch (e) {
error = e;
}
return error;
}
function _throws(shouldThrow, block, expected, message) {
var actual;
if (typeof block !== 'function') {
throw new TypeError('"block" argument must be a function');
}
if (typeof expected === 'string') {
message = expected;
expected = null;
}
actual = _tryBlock(block);
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
(message ? ' ' + message : '.');
if (shouldThrow && !actual) {
fail(actual, expected, 'Missing expected exception' + message);
}
var userProvidedMessage = typeof message === 'string';
var isUnwantedException = !shouldThrow && util.isError(actual);
var isUnexpectedException = !shouldThrow && actual && !expected;
if ((isUnwantedException &&
userProvidedMessage &&
expectedException(actual, expected)) ||
isUnexpectedException) {
fail(actual, expected, 'Got unwanted exception' + message);
}
if ((shouldThrow && actual && expected &&
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
throw actual;
}
}
// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
assert.throws = function(block, /*optional*/error, /*optional*/message) {
_throws(true, block, error, message);
};
// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
_throws(false, block, error, message);
};
assert.ifError = function(err) { if (err) { throw err; } };
var objectKeys = Object.keys || function (obj) {
var keys = [];
for (var key in obj) {
if (hasOwn.call(obj, key)) { keys.push(key); }
}
return keys;
};
});
/*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Ported from Webkit
* http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/UnitBezier.h
*/
var unitbezier = UnitBezier;
function UnitBezier(p1x, p1y, p2x, p2y) {
// Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
this.cx = 3.0 * p1x;
this.bx = 3.0 * (p2x - p1x) - this.cx;
this.ax = 1.0 - this.cx - this.bx;
this.cy = 3.0 * p1y;
this.by = 3.0 * (p2y - p1y) - this.cy;
this.ay = 1.0 - this.cy - this.by;
this.p1x = p1x;
this.p1y = p2y;
this.p2x = p2x;
this.p2y = p2y;
}
UnitBezier.prototype.sampleCurveX = function(t) {
// `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
return ((this.ax * t + this.bx) * t + this.cx) * t;
};
UnitBezier.prototype.sampleCurveY = function(t) {
return ((this.ay * t + this.by) * t + this.cy) * t;
};
UnitBezier.prototype.sampleCurveDerivativeX = function(t) {
return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx;
};
UnitBezier.prototype.solveCurveX = function(x, epsilon) {
var this$1 = this;
if (typeof epsilon === 'undefined') { epsilon = 1e-6; }
var t0, t1, t2, x2, i;
// First try a few iterations of Newton's method -- normally very fast.
for (t2 = x, i = 0; i < 8; i++) {
x2 = this$1.sampleCurveX(t2) - x;
if (Math.abs(x2) < epsilon) { return t2; }
var d2 = this$1.sampleCurveDerivativeX(t2);
if (Math.abs(d2) < 1e-6) { break; }
t2 = t2 - x2 / d2;
}
// Fall back to the bisection method for reliability.
t0 = 0.0;
t1 = 1.0;
t2 = x;
if (t2 < t0) { return t0; }
if (t2 > t1) { return t1; }
while (t0 < t1) {
x2 = this$1.sampleCurveX(t2);
if (Math.abs(x2 - x) < epsilon) { return t2; }
if (x > x2) {
t0 = t2;
} else {
t1 = t2;
}
t2 = (t1 - t0) * 0.5 + t0;
}
// Failure.
return t2;
};
UnitBezier.prototype.solve = function(x, epsilon) {
return this.sampleCurveY(this.solveCurveX(x, epsilon));
};
//
/**
* A coordinate is a column, row, zoom combination, often used
* as the data component of a tile.
*
* @param {number} column
* @param {number} row
* @param {number} zoom
* @private
*/
var Coordinate = function Coordinate(column , row , zoom ) {
this.column = column;
this.row = row;
this.zoom = zoom;
};
/**
* Create a clone of this coordinate that can be mutated without
* changing the original coordinate
*
* @returns {Coordinate} clone
* @private
* var coord = new Coordinate(0, 0, 0);
* var c2 = coord.clone();
* // since coord is cloned, modifying a property of c2 does
* // not modify it.
* c2.zoom = 2;
*/
Coordinate.prototype.clone = function clone () {
return new Coordinate(this.column, this.row, this.zoom);
};
/**
* Zoom this coordinate to a given zoom level. This returns a new
* coordinate object, not mutating the old one.
*
* @param {number} zoom
* @returns {Coordinate} zoomed coordinate
* @private
* @example
* var coord = new Coordinate(0, 0, 0);
* var c2 = coord.zoomTo(1);
* c2 // equals new Coordinate(0, 0, 1);
*/
Coordinate.prototype.zoomTo = function zoomTo (zoom ) { return this.clone()._zoomTo(zoom); };
/**
* Subtract the column and row values of this coordinate from those
* of another coordinate. The other coordinat will be zoomed to the
* same level as `this` before the subtraction occurs
*
* @param {Coordinate} c other coordinate
* @returns {Coordinate} result
* @private
*/
Coordinate.prototype.sub = function sub (c ) { return this.clone()._sub(c); };
Coordinate.prototype._zoomTo = function _zoomTo (zoom ) {
var scale = Math.pow(2, zoom - this.zoom);
this.column *= scale;
this.row *= scale;
this.zoom = zoom;
return this;
};
Coordinate.prototype._sub = function _sub (c ) {
c = c.zoomTo(this.zoom);
this.column -= c.column;
this.row -= c.row;
return this;
};
'use strict';
var pointGeometry = Point;
/**
* A standalone point geometry with useful accessor, comparison, and
* modification methods.
*
* @class Point
* @param {Number} x the x-coordinate. this could be longitude or screen
* pixels, or any other sort of unit.
* @param {Number} y the y-coordinate. this could be latitude or screen
* pixels, or any other sort of unit.
* @example
* var point = new Point(-77, 38);
*/
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype = {
/**
* Clone this point, returning a new point that can be modified
* without affecting the old one.
* @return {Point} the clone
*/
clone: function() { return new Point(this.x, this.y); },
/**
* Add this point's x & y coordinates to another point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
add: function(p) { return this.clone()._add(p); },
/**
* Subtract this point's x & y coordinates to from point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
sub: function(p) { return this.clone()._sub(p); },
/**
* Multiply this point's x & y coordinates by point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
multByPoint: function(p) { return this.clone()._multByPoint(p); },
/**
* Divide this point's x & y coordinates by point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
divByPoint: function(p) { return this.clone()._divByPoint(p); },
/**
* Multiply this point's x & y coordinates by a factor,
* yielding a new point.
* @param {Point} k factor
* @return {Point} output point
*/
mult: function(k) { return this.clone()._mult(k); },
/**
* Divide this point's x & y coordinates by a factor,
* yielding a new point.
* @param {Point} k factor
* @return {Point} output point
*/
div: function(k) { return this.clone()._div(k); },
/**
* Rotate this point around the 0, 0 origin by an angle a,
* given in radians
* @param {Number} a angle to rotate around, in radians
* @return {Point} output point
*/
rotate: function(a) { return this.clone()._rotate(a); },
/**
* Rotate this point around p point by an angle a,
* given in radians
* @param {Number} a angle to rotate around, in radians
* @param {Point} p Point to rotate around
* @return {Point} output point
*/
rotateAround: function(a,p) { return this.clone()._rotateAround(a,p); },
/**
* Multiply this point by a 4x1 transformation matrix
* @param {Array<Number>} m transformation matrix
* @return {Point} output point
*/
matMult: function(m) { return this.clone()._matMult(m); },
/**
* Calculate this point but as a unit vector from 0, 0, meaning
* that the distance from the resulting point to the 0, 0
* coordinate will be equal to 1 and the angle from the resulting
* point to the 0, 0 coordinate will be the same as before.
* @return {Point} unit vector point
*/
unit: function() { return this.clone()._unit(); },
/**
* Compute a perpendicular point, where the new y coordinate
* is the old x coordinate and the new x coordinate is the old y
* coordinate multiplied by -1
* @return {Point} perpendicular point
*/
perp: function() { return this.clone()._perp(); },
/**
* Return a version of this point with the x & y coordinates
* rounded to integers.
* @return {Point} rounded point
*/
round: function() { return this.clone()._round(); },
/**
* Return the magitude of this point: this is the Euclidean
* distance from the 0, 0 coordinate to this point's x and y
* coordinates.
* @return {Number} magnitude
*/
mag: function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
},
/**
* Judge whether this point is equal to another point, returning
* true or false.
* @param {Point} other the other point
* @return {boolean} whether the points are equal
*/
equals: function(other) {
return this.x === other.x &&
this.y === other.y;
},
/**
* Calculate the distance from this point to another point
* @param {Point} p the other point
* @return {Number} distance
*/
dist: function(p) {
return Math.sqrt(this.distSqr(p));
},
/**
* Calculate the distance from this point to another point,
* without the square root step. Useful if you're comparing
* relative distances.
* @param {Point} p the other point
* @return {Number} distance
*/
distSqr: function(p) {
var dx = p.x - this.x,
dy = p.y - this.y;
return dx * dx + dy * dy;
},
/**
* Get the angle from the 0, 0 coordinate to this point, in radians
* coordinates.
* @return {Number} angle
*/
angle: function() {
return Math.atan2(this.y, this.x);
},
/**
* Get the angle from this point to another point, in radians
* @param {Point} b the other point
* @return {Number} angle
*/
angleTo: function(b) {
return Math.atan2(this.y - b.y, this.x - b.x);
},
/**
* Get the angle between this point and another point, in radians
* @param {Point} b the other point
* @return {Number} angle
*/
angleWith: function(b) {
return this.angleWithSep(b.x, b.y);
},
/*
* Find the angle of the two vectors, solving the formula for
* the cross product a x b = |a||b|sin(θ) for θ.
* @param {Number} x the x-coordinate
* @param {Number} y the y-coordinate
* @return {Number} the angle in radians
*/
angleWithSep: function(x, y) {
return Math.atan2(
this.x * y - this.y * x,
this.x * x + this.y * y);
},
_matMult: function(m) {
var x = m[0] * this.x + m[1] * this.y,
y = m[2] * this.x + m[3] * this.y;
this.x = x;
this.y = y;
return this;
},
_add: function(p) {
this.x += p.x;
this.y += p.y;
return this;
},
_sub: function(p) {
this.x -= p.x;
this.y -= p.y;
return this;
},
_mult: function(k) {
this.x *= k;
this.y *= k;
return this;
},
_div: function(k) {
this.x /= k;
this.y /= k;
return this;
},
_multByPoint: function(p) {
this.x *= p.x;
this.y *= p.y;
return this;
},
_divByPoint: function(p) {
this.x /= p.x;
this.y /= p.y;
return this;
},
_unit: function() {
this._div(this.mag());
return this;
},
_perp: function() {
var y = this.y;
this.y = this.x;
this.x = -y;
return this;
},
_rotate: function(angle) {
var cos = Math.cos(angle),
sin = Math.sin(angle),
x = cos * this.x - sin * this.y,
y = sin * this.x + cos * this.y;
this.x = x;
this.y = y;
return this;
},
_rotateAround: function(angle, p) {
var cos = Math.cos(angle),
sin = Math.sin(angle),
x = p.x + cos * (this.x - p.x) - sin * (this.y - p.y),
y = p.y + sin * (this.x - p.x) + cos * (this.y - p.y);
this.x = x;
this.y = y;
return this;
},
_round: function() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
return this;
}
};
/**
* Construct a point from an array if necessary, otherwise if the input
* is already a Point, or an unknown type, return it unchanged
* @param {Array<Number>|Point|*} a any kind of input value
* @return {Point} constructed point, or passed-through value.
* @example
* // this
* var point = Point.convert([0, 1]);
* // is equivalent to
* var point = new Point(0, 1);
*/
Point.convert = function (a) {
if (a instanceof Point) {
return a;
}
if (Array.isArray(a)) {
return new Point(a[0], a[1]);
}
return a;
};
//
//
/**
* Deeply compares two object literals.
*
* @private
*/
function deepEqual(a , b ) {
if (Array.isArray(a)) {
if (!Array.isArray(b) || a.length !== b.length) { return false; }
for (var i = 0; i < a.length; i++) {
if (!deepEqual(a[i], b[i])) { return false; }
}
return true;
}
if (typeof a === 'object' && a !== null && b !== null) {
if (!(typeof b === 'object')) { return false; }
var keys = Object.keys(a);
if (keys.length !== Object.keys(b).length) { return false; }
for (var key in a) {
if (!deepEqual(a[key], b[key])) { return false; }
}
return true;
}
return a === b;
}
//
/**
* @module util
* @private
*/
/**
* Given a value `t` that varies between 0 and 1, return
* an interpolation function that eases between 0 and 1 in a pleasing
* cubic in-out fashion.
*
* @private
*/
function easeCubicInOut(t ) {
if (t <= 0) { return 0; }
if (t >= 1) { return 1; }
var t2 = t * t,
t3 = t2 * t;
return 4 * (t < 0.5 ? t3 : 3 * (t - t2) + t3 - 0.75);
}
/**
* Given given (x, y), (x1, y1) control points for a bezier curve,
* return a function that interpolates along that curve.
*
* @param p1x control point 1 x coordinate
* @param p1y control point 1 y coordinate
* @param p2x control point 2 x coordinate
* @param p2y control point 2 y coordinate
* @private
*/
function bezier(p1x , p1y , p2x , p2y ) {
var bezier = new unitbezier(p1x, p1y, p2x, p2y);
return function(t ) {
return bezier.solve(t);
};
}
/**
* A default bezier-curve powered easing function with
* control points (0.25, 0.1) and (0.25, 1)
*
* @private
*/
var ease = bezier(0.25, 0.1, 0.25, 1);
/**
* constrain n to the given range via min + max
*
* @param n value
* @param min the minimum value to be returned
* @param max the maximum value to be returned
* @returns the clamped value
* @private
*/
function clamp(n , min , max ) {
return Math.min(max, Math.max(min, n));
}
/**
* constrain n to the given range, excluding the minimum, via modular arithmetic
*
* @param n value
* @param min the minimum value to be returned, exclusive
* @param max the maximum value to be returned, inclusive
* @returns constrained number
* @private
*/
function wrap(n , min , max ) {
var d = max - min;
var w = ((n - min) % d + d) % d + min;
return (w === min) ? max : w;
}
/*
* Call an asynchronous function on an array of arguments,
* calling `callback` with the completed results of all calls.
*
* @param array input to each call of the async function.
* @param fn an async function with signature (data, callback)
* @param callback a callback run after all async work is done.
* called with an array, containing the results of each async call.
* @private
*/
function asyncAll (
array ,
fn ,
callback
) {
if (!array.length) { return callback(null, []); }
var remaining = array.length;
var results = new Array(array.length);
var error = null;
array.forEach(function (item, i) {
fn(item, function (err, result) {
if (err) { error = err; }
results[i] = ((result ) ); // https://github.com/facebook/flow/issues/2123
if (--remaining === 0) { callback(error, results); }
});
});
}
/*
* Polyfill for Object.values. Not fully spec compliant, but we don't
* need it to be.
*
* @private
*/
function values (obj ) {
var result = [];
for (var k in obj) {
result.push(obj[k]);
}
return result;
}
/*
* Compute the difference between the keys in one object and the keys
* in another object.
*
* @returns keys difference
* @private
*/
function keysDifference (obj , other ) {
var difference = [];
for (var i in obj) {
if (!(i in other)) {
difference.push(i);
}
}
return difference;
}
/**
* Given a destination object and optionally many source objects,
* copy all properties from the source objects into the destination.
* The last source object given overrides properties from previous
* source objects.
*
* @param dest destination object
* @param sources sources from which properties are pulled
* @private
*/
function extend(dest ) {
var sources = [], len = arguments.length - 1;
while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
for (var i = 0, list = sources; i < list.length; i += 1) {
var src = list[i];
for (var k in src) {
dest[k] = src[k];
}
}
return dest;
}
/**
* Given an object and a number of properties as strings, return version
* of that object with only those properties.
*
* @param src the object
* @param properties an array of property names chosen
* to appear on the resulting object.
* @returns object with limited properties.
* @example
* var foo = { name: 'Charlie', age: 10 };
* var justName = pick(foo, ['name']);
* // justName = { name: 'Charlie' }
* @private
*/
function pick(src , properties ) {
var result = {};
for (var i = 0; i < properties.length; i++) {
var k = properties[i];
if (k in src) {
result[k] = src[k];
}
}
return result;
}
var id = 1;
/**
* Return a unique numeric id, starting at 1 and incrementing with
* each call.
*
* @returns unique numeric id.
* @private
*/
function uniqueId() {
return id++;
}
/**
* Return a random UUID (v4). Taken from: https://gist.github.com/jed/982883
*/
function uuid() {
function b(a) {
return a ? (a ^ Math.random() * 16 >> a / 4).toString(16) :
//$FlowFixMe: Flow doesn't like the implied array literal conversion here
([1e7] + -[1e3] + -4e3 + -8e3 + -1e11).replace(/[018]/g, b);
}
return b();
}
/**
* Validate a string to match UUID(v4) of the
* form: xxxxxxxx-xxxx-4xxx-[89ab]xxx-xxxxxxxxxxxx
* @param str string to validate.
*/
function validateUuid(str ) {
return str ? /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(str) : false;
}
/**
* Given an array of member function names as strings, replace all of them
* with bound versions that will always refer to `context` as `this`. This
* is useful for classes where otherwise event bindings would reassign
* `this` to the evented object or some other value: this lets you ensure
* the `this` value always.
*
* @param fns list of member function names
* @param context the context value
* @example
* function MyClass() {
* bindAll(['ontimer'], this);
* this.name = 'Tom';
* }
* MyClass.prototype.ontimer = function() {
* alert(this.name);
* };
* var myClass = new MyClass();
* setTimeout(myClass.ontimer, 100);
* @private
*/
function bindAll(fns , context ) {
fns.forEach(function (fn) {
if (!context[fn]) { return; }
context[fn] = context[fn].bind(context);
});
}
/**
* Given a list of coordinates, get their center as a coordinate.
*
* @returns centerpoint
* @private
*/
function getCoordinatesCenter(coords ) {
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
for (var i = 0; i < coords.length; i++) {
minX = Math.min(minX, coords[i].column);
minY = Math.min(minY, coords[i].row);
maxX = Math.max(maxX, coords[i].column);
maxY = Math.max(maxY, coords[i].row);
}
var dx = maxX - minX;
var dy = maxY - minY;
var dMax = Math.max(dx, dy);
var zoom = Math.max(0, Math.floor(-Math.log(dMax) / Math.LN2));
return new Coordinate((minX + maxX) / 2, (minY + maxY) / 2, 0)
.zoomTo(zoom);
}
/**
* Determine if a string ends with a particular substring
*
* @private
*/
function endsWith(string , suffix ) {
return string.indexOf(suffix, string.length - suffix.length) !== -1;
}
/**
* Create an object by mapping all the values of an existing object while
* preserving their keys.
*
* @private
*/
function mapObject(input , iterator , context ) {
var this$1 = this;
var output = {};
for (var key in input) {
output[key] = iterator.call(context || this$1, input[key], key, input);
}
return output;
}
/**
* Create an object by filtering out values of an existing object.
*
* @private
*/
function filterObject(input , iterator , context ) {
var this$1 = this;
var output = {};
for (var key in input) {
if (iterator.call(context || this$1, input[key], key, input)) {
output[key] = input[key];
}
}
return output;
}
/**
* Deeply clones two objects.
*
* @private
*/
function clone (input ) {
if (Array.isArray(input)) {
return input.map(clone);
} else if (typeof input === 'object' && input) {
return ((mapObject(input, clone) ) );
} else {
return input;
}
}
/**
* Check if two arrays have at least one common element.
*
* @private
*/
function arraysIntersect (a , b ) {
for (var l = 0; l < a.length; l++) {
if (b.indexOf(a[l]) >= 0) { return true; }
}
return false;
}
/**
* Print a warning message to the console and ensure duplicate warning messages
* are not printed.
*
* @private
*/
var warnOnceHistory = {};
function warnOnce(message ) {
if (!warnOnceHistory[message]) {
// console isn't defined in some WebWorkers, see #2558
if (typeof console !== "undefined") { console.warn(message); }
warnOnceHistory[message] = true;
}
}
/**
* Indicates if the provided Points are in a counter clockwise (true) or clockwise (false) order
*
* @private
* @returns true for a counter clockwise set of points
*/
// http://bryceboe.com/2006/10/23/line-segment-intersection-algorithm/
function isCounterClockwise(a , b , c ) {
return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x);
}
/**
* Returns the signed area for the polygon ring. Postive areas are exterior rings and
* have a clockwise winding. Negative areas are interior rings and have a counter clockwise
* ordering.
*
* @private
* @param ring Exterior or interior ring
*/
function calculateSignedArea(ring ) {
var sum = 0;
for (var i = 0, len = ring.length, j = len - 1, p1 = (void 0), p2 = (void 0); i < len; j = i++) {
p1 = ring[i];
p2 = ring[j];
sum += (p2.x - p1.x) * (p1.y + p2.y);
}
return sum;
}
/**
* Detects closed polygons, first + last point are equal
*
* @private
* @param points array of points
* @return true if the points are a closed polygon
*/
function isClosedPolygon(points ) {
// If it is 2 points that are the same then it is a point
// If it is 3 points with start and end the same then it is a line
if (points.length < 4)
{ return false; }
var p1 = points[0];
var p2 = points[points.length - 1];
if (Math.abs(p1.x - p2.x) > 0 ||
Math.abs(p1.y - p2.y) > 0) {
return false;
}
// polygon simplification can produce polygons with zero area and more than 3 points
return Math.abs(calculateSignedArea(points)) > 0.01;
}
/**
* Converts spherical coordinates to cartesian coordinates.
*
* @private
* @param spherical Spherical coordinates, in [radial, azimuthal, polar]
* @return cartesian coordinates in [x, y, z]
*/
function sphericalToCartesian(ref ) {
var r = ref[0];
var azimuthal = ref[1];
var polar = ref[2];
// We abstract "north"/"up" (compass-wise) to be 0° when really this is 90° (π/2):
// correct for that here
azimuthal += 90;
// Convert azimuthal and polar angles to radians
azimuthal *= Math.PI / 180;
polar *= Math.PI / 180;
return {
x: r * Math.cos(azimuthal) * Math.sin(polar),
y: r * Math.sin(azimuthal) * Math.sin(polar),
z: r * Math.cos(polar)
};
}
/**
* Parses data from 'Cache-Control' headers.
*
* @private
* @param cacheControl Value of 'Cache-Control' header
* @return object containing parsed header info.
*/
function parseCacheControl(cacheControl ) {
// Taken from [Wreck](https://github.com/hapijs/wreck)
var re = /(?:^|(?:\s*\,\s*))([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)(?:\=(?:([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)|(?:\"((?:[^"\\]|\\.)*)\")))?/g;
var header = {};
cacheControl.replace(re, function ($0, $1, $2, $3) {
var value = $2 || $3;
header[$1] = value ? value.toLowerCase() : true;
return '';
});
if (header['max-age']) {
var maxAge = parseInt(header['max-age'], 10);
if (isNaN(maxAge)) { delete header['max-age']; }
else { header['max-age'] = maxAge; }
}
return header;
}
function storageAvailable(type ) {
try {
var storage = self[type];
storage.setItem('_mapbox_test_', 1);
storage.removeItem('_mapbox_test_');
return true;
} catch (e) {
return false;
}
}
//
var now = self.performance && self.performance.now ?
self.performance.now.bind(self.performance) :
Date.now.bind(Date);
var raf = self.requestAnimationFrame ||
self.mozRequestAnimationFrame ||
self.webkitRequestAnimationFrame ||
self.msRequestAnimationFrame;
var cancel = self.cancelAnimationFrame ||
self.mozCancelAnimationFrame ||
self.webkitCancelAnimationFrame ||
self.msCancelAnimationFrame;
/**
* @private
*/
var exported = {
/**
* Provides a function that outputs milliseconds: either performance.now()
* or a fallback to Date.now()
*/
now: now,
frame: function frame(fn ) {
var frame = raf(fn);
return { cancel: function () { return cancel(frame); } };
},
getImageData: function getImageData(img ) {
var canvas = self.document.createElement('canvas');
var context = canvas.getContext('2d');
if (!context) {
throw new Error('failed to create canvas 2d context');
}
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0, img.width, img.height);
return context.getImageData(0, 0, img.width, img.height);
},
resolveURL: function resolveURL(path ) {
var a = self.document.createElement('a');
a.href = path;
return a.href;
},
hardwareConcurrency: self.navigator.hardwareConcurrency || 4,
get devicePixelRatio() { return self.devicePixelRatio; },
supportsWebp: false
};
if (self.document) {
var webpImgTest = self.document.createElement('img');
webpImgTest.onload = function() {
exported.supportsWebp = true;
};
webpImgTest.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA=';
}
//
/**
* The type of a resource.
* @private
* @readonly
* @enum {string}
*/
var ResourceType = {
Unknown: 'Unknown',
Style: 'Style',
Source: 'Source',
Tile: 'Tile',
Glyphs: 'Glyphs',
SpriteImage: 'SpriteImage',
SpriteJSON: 'SpriteJSON',
Image: 'Image'
};
if (typeof Object.freeze == 'function') {
Object.freeze(ResourceType);
}
/**
* A `RequestParameters` object to be returned from Map.options.transformRequest callbacks.
* @typedef {Object} RequestParameters
* @property {string} url The URL to be requested.
* @property {Object} headers The headers to be sent with the request.
* @property {string} credentials `'same-origin'|'include'` Use 'include' to send cookies with cross-origin requests.
*/
var AJAXError = (function (Error) {
function AJAXError(message , status , url ) {
Error.call(this, message);
this.status = status;
this.url = url;
// work around for https://github.com/Rich-Harris/buble/issues/40
this.name = this.constructor.name;
this.message = message;
}
if ( Error ) AJAXError.__proto__ = Error;
AJAXError.prototype = Object.create( Error && Error.prototype );
AJAXError.prototype.constructor = AJAXError;
AJAXError.prototype.toString = function toString () {
return ((this.name) + ": " + (this.message) + " (" + (this.status) + "): " + (this.url));
};
return AJAXError;
}(Error));
function makeRequest(requestParameters ) {
var xhr = new self.XMLHttpRequest();
xhr.open(requestParameters.method || 'GET', requestParameters.url, true);
for (var k in requestParameters.headers) {
xhr.setRequestHeader(k, requestParameters.headers[k]);
}
xhr.withCredentials = requestParameters.credentials === 'include';
return xhr;
}
var getJSON = function(requestParameters , callback ) {
var xhr = makeRequest(requestParameters);
xhr.setRequestHeader('Accept', 'application/json');
xhr.onerror = function() {
callback(new Error(xhr.statusText));
};
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300 && xhr.response) {
var data;
try {
data = JSON.parse(xhr.response);
} catch (err) {
return callback(err);
}
callback(null, data);
} else {
if (xhr.status === 401 && requestParameters.url.match(/mapbox.com/)) {
callback(new AJAXError(((xhr.statusText) + ": you may have provided an invalid Mapbox access token. See https://www.mapbox.com/api-documentation/#access-tokens"), xhr.status, requestParameters.url));
} else {
callback(new AJAXError(xhr.statusText, xhr.status, requestParameters.url));
}
}
};
xhr.send();
return { cancel: function () { return xhr.abort(); } };
};
var getArrayBuffer = function(requestParameters , callback ) {
var xhr = makeRequest(requestParameters);
xhr.responseType = 'arraybuffer';
xhr.onerror = function() {
callback(new Error(xhr.statusText));
};
xhr.onload = function() {
var response = xhr.response;
if (response.byteLength === 0 && xhr.status === 200) {
return callback(new Error('http status 200 returned without content.'));
}
if (xhr.status >= 200 && xhr.status < 300 && xhr.response) {
callback(null, {
data: response,
cacheControl: xhr.getResponseHeader('Cache-Control'),
expires: xhr.getResponseHeader('Expires')
});
} else {
callback(new AJAXError(xhr.statusText, xhr.status, requestParameters.url));
}
};
xhr.send();
return { cancel: function () { return xhr.abort(); } };
};
var postData = function(requestParameters , payload , callback ) {
var xhr = makeRequest(extend(requestParameters, {method: 'POST'}));
xhr.onerror = function() {
callback(new Error(xhr.statusText));
};
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
callback(null, xhr.response);
} else {
callback(new AJAXError(xhr.statusText, xhr.status, requestParameters.url));
}
};
xhr.send(payload);
return { cancel: function () { return xhr.abort(); } };
};
function sameOrigin(url) {
var a = self.document.createElement('a');
a.href = url;
return a.protocol === self.document.location.protocol && a.host === self.document.location.host;
}
var transparentPngUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII=';
var getImage = function(requestParameters , callback ) {
// request the image with XHR to work around caching issues
// see https://github.com/mapbox/mapbox-gl-js/issues/1470
return getArrayBuffer(requestParameters, function (err, imgData) {
if (err) {
callback(err);
} else if (imgData) {
var img = new self.Image();
var URL = self.URL || self.webkitURL;
img.onload = function () {
callback(null, img);
URL.revokeObjectURL(img.src);
};
var blob = new self.Blob([new Uint8Array(imgData.data)], { type: 'image/png' });
(img ).cacheControl = imgData.cacheControl;
(img ).expires = imgData.expires;
img.src = imgData.data.byteLength ? URL.createObjectURL(blob) : transparentPngUrl;
}
});
};
var getVideo = function(urls , callback ) {
var video = self.document.createElement('video');
video.muted = true;
video.onloadstart = function() {
callback(null, video);
};
for (var i = 0; i < urls.length; i++) {
var s = self.document.createElement('source');
if (!sameOrigin(urls[i])) {
video.crossOrigin = 'Anonymous';
}
s.src = urls[i];
video.appendChild(s);
}
return { cancel: function () {} };
};
//
function _addEventListener(type , listener , listenerList ) {
var listenerExists = listenerList[type] && listenerList[type].indexOf(listener) !== -1;
if (!listenerExists) {
listenerList[type] = listenerList[type] || [];
listenerList[type].push(listener);
}
}
function _removeEventListener(type , listener , listenerList ) {
if (listenerList && listenerList[type]) {
var index = listenerList[type].indexOf(listener);
if (index !== -1) {
listenerList[type].splice(index, 1);
}
}
}
var Event = function Event(type , data) {
if ( data === void 0 ) data = {};
extend(this, data);
this.type = type;
};
var ErrorEvent = (function (Event) {
function ErrorEvent(error , data) {
if ( data === void 0 ) data = {};
Event.call(this, 'error', extend({error: error}, data));
}
if ( Event ) ErrorEvent.__proto__ = Event;
ErrorEvent.prototype = Object.create( Event && Event.prototype );
ErrorEvent.prototype.constructor = ErrorEvent;
return ErrorEvent;
}(Event));
/**
* Methods mixed in to other classes for event capabilities.
*
* @mixin Evented
*/
var Evented = function Evented () {};
Evented.prototype.on = function on (type , listener ) {
this._listeners = this._listeners || {};
_addEventListener(type, listener, this._listeners);
return this;
};
/**
* Removes a previously registered event listener.
*
* @param {string} type The event type to remove listeners for.
* @param {Function} listener The listener function to remove.
* @returns {Object} `this`
*/
Evented.prototype.off = function off (type , listener ) {
_removeEventListener(type, listener, this._listeners);
_removeEventListener(type, listener, this._oneTimeListeners);
return this;
};
/**
* Adds a listener that will be called only once to a specified event type.
*
* The listener will be called first time the event fires after the listener is registered.
*
* @param {string} type The event type to listen for.
* @param {Function} listener The function to be called when the event is fired the first time.
* @returns {Object} `this`
*/
Evented.prototype.once = function once (type , listener ) {
this._oneTimeListeners = this._oneTimeListeners || {};
_addEventListener(type, listener, this._oneTimeListeners);
return this;
};
Evented.prototype.fire = function fire (event ) {
var this$1 = this;
// Compatibility with (type: string, properties: Object) signature from previous versions.
// See https://github.com/mapbox/mapbox-gl-js/issues/6522,
// https://github.com/mapbox/mapbox-gl-draw/issues/766
if (typeof event === 'string') {
event = new Event(event, arguments[1] || {});
}
var type = event.type;
if (this.listens(type)) {
(event ).target = this;
// make sure adding or removing listeners inside other listeners won't cause an infinite loop
var listeners = this._listeners && this._listeners[type] ? this._listeners[type].slice() : [];
for (var i = 0, list = listeners; i < list.length; i += 1) {
var listener = list[i];
listener.call(this$1, event);
}
var oneTimeListeners = this._oneTimeListeners && this._oneTimeListeners[type] ? this._oneTimeListeners[type].slice() : [];
for (var i$1 = 0, list$1 = oneTimeListeners; i$1 < list$1.length; i$1 += 1) {
var listener$1 = list$1[i$1];
_removeEventListener(type, listener$1, this$1._oneTimeListeners);
listener$1.call(this$1, event);
}
var parent = this._eventedParent;
if (parent) {
extend(
event,
typeof this._eventedParentData === 'function' ? this._eventedParentData() : this._eventedParentData
);
parent.fire(event);
}
// To ensure that no error events are dropped, print them to the
// console if they have no listeners.
} else if (event instanceof ErrorEvent) {
console.error(event.error);
}
return this;
};
/**
* Returns a true if this instance of Evented or any forwardeed instances of Evented have a listener for the specified type.
*
* @param {string} type The event type
* @returns {boolean} `true` if there is at least one registered listener for specified event type, `false` otherwise
* @private
*/
Evented.prototype.listens = function listens (type ) {
return (
(this._listeners && this._listeners[type] && this._listeners[type].length > 0) ||
(this._oneTimeListeners && this._oneTimeListeners[type] && this._oneTimeListeners[type].length > 0) ||
(this._eventedParent && this._eventedParent.listens(type))
);
};
/**
* Bubble all events fired by this instance of Evented to this parent instance of Evented.
*
* @private
* @returns {Object} `this`
* @private
*/
Evented.prototype.setEventedParent = function setEventedParent (parent , data ) {
this._eventedParent = parent;
this._eventedParentData = data;
return this;
};
var $version = 8;
var $root = {"version":{"required":true,"type":"enum","values":[8]},"name":{"type":"string"},"metadata":{"type":"*"},"center":{"type":"array","value":"number"},"zoom":{"type":"number"},"bearing":{"type":"number","default":0,"period":360,"units":"degrees"},"pitch":{"type":"number","default":0,"units":"degrees"},"light":{"type":"light"},"sources":{"required":true,"type":"sources"},"sprite":{"type":"string"},"glyphs":{"type":"string"},"transition":{"type":"transition"},"layers":{"required":true,"type":"array","value":"layer"}};
var sources = {"*":{"type":"source"}};
var source = ["source_vector","source_raster","source_raster_dem","source_geojson","source_video","source_image"];
var source_vector = {"type":{"required":true,"type":"enum","values":{"vector":{}}},"url":{"type":"string"},"tiles":{"type":"array","value":"string"},"bounds":{"type":"array","value":"number","length":4,"default":[-180,-85.051129,180,85.051129]},"scheme":{"type":"enum","values":{"xyz":{},"tms":{}},"default":"xyz"},"minzoom":{"type":"number","default":0},"maxzoom":{"type":"number","default":22},"attribution":{"type":"string"},"*":{"type":"*"}};
var source_raster = {"type":{"required":true,"type":"enum","values":{"raster":{}}},"url":{"type":"string"},"tiles":{"type":"array","value":"string"},"bounds":{"type":"array","value":"number","length":4,"default":[-180,-85.051129,180,85.051129]},"minzoom":{"type":"number","default":0},"maxzoom":{"type":"number","default":22},"tileSize":{"type":"number","default":512,"units":"pixels"},"scheme":{"type":"enum","values":{"xyz":{},"tms":{}},"default":"xyz"},"attribution":{"type":"string"},"*":{"type":"*"}};
var source_raster_dem = {"type":{"required":true,"type":"enum","values":{"raster-dem":{}}},"url":{"type":"string"},"tiles":{"type":"array","value":"string"},"bounds":{"type":"array","value":"number","length":4,"default":[-180,-85.051129,180,85.051129]},"minzoom":{"type":"number","default":0},"maxzoom":{"type":"number","default":22},"tileSize":{"type":"number","default":512,"units":"pixels"},"attribution":{"type":"string"},"encoding":{"type":"enum","values":{"terrarium":{},"mapbox":{}},"default":"mapbox"},"*":{"type":"*"}};
var source_geojson = {"type":{"required":true,"type":"enum","values":{"geojson":{}}},"data":{"type":"*"},"maxzoom":{"type":"number","default":18},"attribution":{"type":"string"},"buffer":{"type":"number","default":128,"maximum":512,"minimum":0},"tolerance":{"type":"number","default":0.375},"cluster":{"type":"boolean","default":false},"clusterRadius":{"type":"number","default":50,"minimum":0},"clusterMaxZoom":{"type":"number"},"lineMetrics":{"type":"boolean","default":false},"generateId":{"type":"boolean","default":false}};
var source_video = {"type":{"required":true,"type":"enum","values":{"video":{}}},"urls":{"required":true,"type":"array","value":"string"},"coordinates":{"required":true,"type":"array","length":4,"value":{"type":"array","length":2,"value":"number"}}};
var source_image = {"type":{"required":true,"type":"enum","values":{"image":{}}},"url":{"required":true,"type":"string"},"coordinates":{"required":true,"type":"array","length":4,"value":{"type":"array","length":2,"value":"number"}}};
var layer = {"id":{"type":"string","required":true},"type":{"type":"enum","values":{"fill":{},"line":{},"symbol":{},"circle":{},"heatmap":{},"fill-extrusion":{},"raster":{},"hillshade":{},"background":{}},"required":true},"metadata":{"type":"*"},"source":{"type":"string"},"source-layer":{"type":"string"},"minzoom":{"type":"number","minimum":0,"maximum":24},"maxzoom":{"type":"number","minimum":0,"maximum":24},"filter":{"type":"filter"},"layout":{"type":"layout"},"paint":{"type":"paint"}};
var layout = ["layout_fill","layout_line","layout_circle","layout_heatmap","layout_fill-extrusion","layout_symbol","layout_raster","layout_hillshade","layout_background"];
var layout_background = {"visibility":{"type":"enum","values":{"visible":{},"none":{}},"default":"visible","property-type":"constant"}};
var layout_fill = {"visibility":{"type":"enum","values":{"visible":{},"none":{}},"default":"visible","property-type":"constant"}};
var layout_circle = {"visibility":{"type":"enum","values":{"visible":{},"none":{}},"default":"visible","property-type":"constant"}};
var layout_heatmap = {"visibility":{"type":"enum","values":{"visible":{},"none":{}},"default":"visible","property-type":"constant"}};
var layout_line = {"line-cap":{"type":"enum","values":{"butt":{},"round":{},"square":{}},"default":"butt","expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"line-join":{"type":"enum","values":{"bevel":{},"round":{},"miter":{}},"default":"miter","expression":{"interpolated":false,"parameters":["zoom","feature"]},"property-type":"data-driven"},"line-miter-limit":{"type":"number","default":2,"requires":[{"line-join":"miter"}],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"line-round-limit":{"type":"number","default":1.05,"requires":[{"line-join":"round"}],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"visibility":{"type":"enum","values":{"visible":{},"none":{}},"default":"visible","property-type":"constant"}};
var layout_symbol = {"symbol-placement":{"type":"enum","values":{"point":{},"line":{},"line-center":{}},"default":"point","expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"symbol-spacing":{"type":"number","default":250,"minimum":1,"units":"pixels","requires":[{"symbol-placement":"line"}],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"symbol-avoid-edges":{"type":"boolean","default":false,"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"icon-allow-overlap":{"type":"boolean","default":false,"requires":["icon-image"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"icon-ignore-placement":{"type":"boolean","default":false,"requires":["icon-image"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"icon-optional":{"type":"boolean","default":false,"requires":["icon-image","text-field"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"icon-rotation-alignment":{"type":"enum","values":{"map":{},"viewport":{},"auto":{}},"default":"auto","requires":["icon-image"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"icon-size":{"type":"number","default":1,"minimum":0,"units":"factor of the original icon size","requires":["icon-image"],"expression":{"interpolated":true,"parameters":["zoom","feature"]},"property-type":"data-driven"},"icon-text-fit":{"type":"enum","values":{"none":{},"width":{},"height":{},"both":{}},"default":"none","requires":["icon-image","text-field"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"icon-text-fit-padding":{"type":"array","value":"number","length":4,"default":[0,0,0,0],"units":"pixels","requires":["icon-image","text-field",{"icon-text-fit":["both","width","height"]}],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"icon-image":{"type":"string","tokens":true,"expression":{"interpolated":false,"parameters":["zoom","feature"]},"property-type":"data-driven"},"icon-rotate":{"type":"number","default":0,"period":360,"units":"degrees","requires":["icon-image"],"expression":{"interpolated":true,"parameters":["zoom","feature"]},"property-type":"data-driven"},"icon-padding":{"type":"number","default":2,"minimum":0,"units":"pixels","requires":["icon-image"],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"icon-keep-upright":{"type":"boolean","default":false,"requires":["icon-image",{"icon-rotation-alignment":"map"},{"symbol-placement":["line","line-center"]}],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"icon-offset":{"type":"array","value":"number","length":2,"default":[0,0],"requires":["icon-image"],"expression":{"interpolated":true,"parameters":["zoom","feature"]},"property-type":"data-driven"},"icon-anchor":{"type":"enum","values":{"center":{},"left":{},"right":{},"top":{},"bottom":{},"top-left":{},"top-right":{},"bottom-left":{},"bottom-right":{}},"default":"center","requires":["icon-image"],"expression":{"interpolated":false,"parameters":["zoom","feature"]},"property-type":"data-driven"},"icon-pitch-alignment":{"type":"enum","values":{"map":{},"viewport":{},"auto":{}},"default":"auto","requires":["icon-image"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"text-pitch-alignment":{"type":"enum","values":{"map":{},"viewport":{},"auto":{}},"default":"auto","requires":["text-field"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"text-rotation-alignment":{"type":"enum","values":{"map":{},"viewport":{},"auto":{}},"default":"auto","requires":["text-field"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"text-field":{"type":"formatted","default":"","tokens":true,"expression":{"interpolated":false,"parameters":["zoom","feature"]},"property-type":"data-driven"},"text-font":{"type":"array","value":"string","default":["Open Sans Regular","Arial Unicode MS Regular"],"requires":["text-field"],"expression":{"interpolated":false,"parameters":["zoom","feature"]},"property-type":"data-driven"},"text-size":{"type":"number","default":16,"minimum":0,"units":"pixels","requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom","feature"]},"property-type":"data-driven"},"text-max-width":{"type":"number","default":10,"minimum":0,"units":"ems","requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom","feature"]},"property-type":"data-driven"},"text-line-height":{"type":"number","default":1.2,"units":"ems","requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"text-letter-spacing":{"type":"number","default":0,"units":"ems","requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom","feature"]},"property-type":"data-driven"},"text-justify":{"type":"enum","values":{"left":{},"center":{},"right":{}},"default":"center","requires":["text-field"],"expression":{"interpolated":false,"parameters":["zoom","feature"]},"property-type":"data-driven"},"text-anchor":{"type":"enum","values":{"center":{},"left":{},"right":{},"top":{},"bottom":{},"top-left":{},"top-right":{},"bottom-left":{},"bottom-right":{}},"default":"center","requires":["text-field"],"expression":{"interpolated":false,"parameters":["zoom","feature"]},"property-type":"data-driven"},"text-max-angle":{"type":"number","default":45,"units":"degrees","requires":["text-field",{"symbol-placement":["line","line-center"]}],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"text-rotate":{"type":"number","default":0,"period":360,"units":"degrees","requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom","feature"]},"property-type":"data-driven"},"text-padding":{"type":"number","default":2,"minimum":0,"units":"pixels","requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"text-keep-upright":{"type":"boolean","default":true,"requires":["text-field",{"text-rotation-alignment":"map"},{"symbol-placement":["line","line-center"]}],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"text-transform":{"type":"enum","values":{"none":{},"uppercase":{},"lowercase":{}},"default":"none","requires":["text-field"],"expression":{"interpolated":false,"parameters":["zoom","feature"]},"property-type":"data-driven"},"text-offset":{"type":"array","value":"number","units":"ems","length":2,"default":[0,0],"requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom","feature"]},"property-type":"data-driven"},"text-allow-overlap":{"type":"boolean","default":false,"requires":["text-field"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"text-ignore-placement":{"type":"boolean","default":false,"requires":["text-field"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"text-optional":{"type":"boolean","default":false,"requires":["text-field","icon-image"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"visibility":{"type":"enum","values":{"visible":{},"none":{}},"default":"visible","property-type":"constant"}};
var layout_raster = {"visibility":{"type":"enum","values":{"visible":{},"none":{}},"default":"visible","property-type":"constant"}};
var layout_hillshade = {"visibility":{"type":"enum","values":{"visible":{},"none":{}},"default":"visible","property-type":"constant"}};
var filter = {"type":"array","value":"*"};
var filter_operator = {"type":"enum","values":{"==":{},"!=":{},">":{},">=":{},"<":{},"<=":{},"in":{},"!in":{},"all":{},"any":{},"none":{},"has":{},"!has":{}}};
var geometry_type = {"type":"enum","values":{"Point":{},"LineString":{},"Polygon":{}}};
var function_stop = {"type":"array","minimum":0,"maximum":22,"value":["number","color"],"length":2};
var expression = {"type":"array","value":"*","minimum":1};
var expression_name = {"type":"enum","values":{"let":{"group":"Variable binding"},"var":{"group":"Variable binding"},"literal":{"group":"Types"},"array":{"group":"Types"},"at":{"group":"Lookup"},"case":{"group":"Decision"},"match":{"group":"Decision"},"coalesce":{"group":"Decision"},"step":{"group":"Ramps, scales, curves"},"interpolate":{"group":"Ramps, scales, curves"},"interpolate-hcl":{"group":"Ramps, scales, curves"},"interpolate-lab":{"group":"Ramps, scales, curves"},"ln2":{"group":"Math"},"pi":{"group":"Math"},"e":{"group":"Math"},"typeof":{"group":"Types"},"string":{"group":"Types"},"number":{"group":"Types"},"boolean":{"group":"Types"},"object":{"group":"Types"},"collator":{"group":"Types"},"format":{"group":"Types"},"to-string":{"group":"Types"},"to-number":{"group":"Types"},"to-boolean":{"group":"Types"},"to-rgba":{"group":"Color"},"to-color":{"group":"Types"},"rgb":{"group":"Color"},"rgba":{"group":"Color"},"get":{"group":"Lookup"},"has":{"group":"Lookup"},"length":{"group":"Lookup"},"properties":{"group":"Feature data"},"feature-state":{"group":"Feature data"},"geometry-type":{"group":"Feature data"},"id":{"group":"Feature data"},"zoom":{"group":"Zoom"},"heatmap-density":{"group":"Heatmap"},"line-progress":{"group":"Heatmap"},"+":{"group":"Math"},"*":{"group":"Math"},"-":{"group":"Math"},"/":{"group":"Math"},"%":{"group":"Math"},"^":{"group":"Math"},"sqrt":{"group":"Math"},"log10":{"group":"Math"},"ln":{"group":"Math"},"log2":{"group":"Math"},"sin":{"group":"Math"},"cos":{"group":"Math"},"tan":{"group":"Math"},"asin":{"group":"Math"},"acos":{"group":"Math"},"atan":{"group":"Math"},"min":{"group":"Math"},"max":{"group":"Math"},"round":{"group":"Math"},"abs":{"group":"Math"},"ceil":{"group":"Math"},"floor":{"group":"Math"},"==":{"group":"Decision"},"!=":{"group":"Decision"},">":{"group":"Decision"},"<":{"group":"Decision"},">=":{"group":"Decision"},"<=":{"group":"Decision"},"all":{"group":"Decision"},"any":{"group":"Decision"},"!":{"group":"Decision"},"is-supported-script":{"group":"String"},"upcase":{"group":"String"},"downcase":{"group":"String"},"concat":{"group":"String"},"resolved-locale":{"group":"String"}}};
var light = {"anchor":{"type":"enum","default":"viewport","values":{"map":{},"viewport":{}},"property-type":"data-constant","transition":false,"expression":{"interpolated":false,"parameters":["zoom"]}},"position":{"type":"array","default":[1.15,210,30],"length":3,"value":"number","property-type":"data-constant","transition":true,"expression":{"interpolated":true,"parameters":["zoom"]}},"color":{"type":"color","property-type":"data-constant","default":"#ffffff","expression":{"interpolated":true,"parameters":["zoom"]},"transition":true},"intensity":{"type":"number","property-type":"data-constant","default":0.5,"minimum":0,"maximum":1,"expression":{"interpolated":true,"parameters":["zoom"]},"transition":true}};
var paint = ["paint_fill","paint_line","paint_circle","paint_heatmap","paint_fill-extrusion","paint_symbol","paint_raster","paint_hillshade","paint_background"];
var paint_fill = {"fill-antialias":{"type":"boolean","default":true,"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"fill-opacity":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-color":{"type":"color","default":"#000000","transition":true,"requires":[{"!":"fill-pattern"}],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-outline-color":{"type":"color","transition":true,"requires":[{"!":"fill-pattern"},{"fill-antialias":true}],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-translate":{"type":"array","value":"number","length":2,"default":[0,0],"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"fill-translate-anchor":{"type":"enum","values":{"map":{},"viewport":{}},"default":"map","requires":["fill-translate"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"fill-pattern":{"type":"string","transition":true,"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"cross-faded"}};
var paint_line = {"line-opacity":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-color":{"type":"color","default":"#000000","transition":true,"requires":[{"!":"line-pattern"}],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-translate":{"type":"array","value":"number","length":2,"default":[0,0],"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"line-translate-anchor":{"type":"enum","values":{"map":{},"viewport":{}},"default":"map","requires":["line-translate"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"line-width":{"type":"number","default":1,"minimum":0,"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-gap-width":{"type":"number","default":0,"minimum":0,"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-offset":{"type":"number","default":0,"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-blur":{"type":"number","default":0,"minimum":0,"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-dasharray":{"type":"array","value":"number","minimum":0,"transition":true,"units":"line widths","requires":[{"!":"line-pattern"}],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"cross-faded"},"line-pattern":{"type":"string","transition":true,"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"cross-faded"},"line-gradient":{"type":"color","transition":false,"requires":[{"!":"line-dasharray"},{"!":"line-pattern"},{"source":"geojson","has":{"lineMetrics":true}}],"expression":{"interpolated":true,"parameters":["line-progress"]},"property-type":"color-ramp"}};
var paint_circle = {"circle-radius":{"type":"number","default":5,"minimum":0,"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-color":{"type":"color","default":"#000000","transition":true,"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-blur":{"type":"number","default":0,"transition":true,"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-opacity":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-translate":{"type":"array","value":"number","length":2,"default":[0,0],"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"circle-translate-anchor":{"type":"enum","values":{"map":{},"viewport":{}},"default":"map","requires":["circle-translate"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"circle-pitch-scale":{"type":"enum","values":{"map":{},"viewport":{}},"default":"map","expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"circle-pitch-alignment":{"type":"enum","values":{"map":{},"viewport":{}},"default":"viewport","expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"circle-stroke-width":{"type":"number","default":0,"minimum":0,"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-stroke-color":{"type":"color","default":"#000000","transition":true,"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-stroke-opacity":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"}};
var paint_heatmap = {"heatmap-radius":{"type":"number","default":30,"minimum":1,"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"heatmap-weight":{"type":"number","default":1,"minimum":0,"transition":false,"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"heatmap-intensity":{"type":"number","default":1,"minimum":0,"transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"heatmap-color":{"type":"color","default":["interpolate",["linear"],["heatmap-density"],0,"rgba(0, 0, 255, 0)",0.1,"royalblue",0.3,"cyan",0.5,"lime",0.7,"yellow",1,"red"],"transition":false,"expression":{"interpolated":true,"parameters":["heatmap-density"]},"property-type":"color-ramp"},"heatmap-opacity":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"}};
var paint_symbol = {"icon-opacity":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"requires":["icon-image"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"icon-color":{"type":"color","default":"#000000","transition":true,"requires":["icon-image"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"icon-halo-color":{"type":"color","default":"rgba(0, 0, 0, 0)","transition":true,"requires":["icon-image"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"icon-halo-width":{"type":"number","default":0,"minimum":0,"transition":true,"units":"pixels","requires":["icon-image"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"icon-halo-blur":{"type":"number","default":0,"minimum":0,"transition":true,"units":"pixels","requires":["icon-image"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"icon-translate":{"type":"array","value":"number","length":2,"default":[0,0],"transition":true,"units":"pixels","requires":["icon-image"],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"icon-translate-anchor":{"type":"enum","values":{"map":{},"viewport":{}},"default":"map","requires":["icon-image","icon-translate"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"text-opacity":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"text-color":{"type":"color","default":"#000000","transition":true,"requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"text-halo-color":{"type":"color","default":"rgba(0, 0, 0, 0)","transition":true,"requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"text-halo-width":{"type":"number","default":0,"minimum":0,"transition":true,"units":"pixels","requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"text-halo-blur":{"type":"number","default":0,"minimum":0,"transition":true,"units":"pixels","requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"text-translate":{"type":"array","value":"number","length":2,"default":[0,0],"transition":true,"units":"pixels","requires":["text-field"],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"text-translate-anchor":{"type":"enum","values":{"map":{},"viewport":{}},"default":"map","requires":["text-field","text-translate"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"}};
var paint_raster = {"raster-opacity":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"raster-hue-rotate":{"type":"number","default":0,"period":360,"transition":true,"units":"degrees","expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"raster-brightness-min":{"type":"number","default":0,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"raster-brightness-max":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"raster-saturation":{"type":"number","default":0,"minimum":-1,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"raster-contrast":{"type":"number","default":0,"minimum":-1,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"raster-resampling":{"type":"enum","values":{"linear":{},"nearest":{}},"default":"linear","expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"raster-fade-duration":{"type":"number","default":300,"minimum":0,"transition":false,"units":"milliseconds","expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"}};
var paint_hillshade = {"hillshade-illumination-direction":{"type":"number","default":335,"minimum":0,"maximum":359,"transition":false,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"hillshade-illumination-anchor":{"type":"enum","values":{"map":{},"viewport":{}},"default":"viewport","expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"hillshade-exaggeration":{"type":"number","default":0.5,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"hillshade-shadow-color":{"type":"color","default":"#000000","transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"hillshade-highlight-color":{"type":"color","default":"#FFFFFF","transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"hillshade-accent-color":{"type":"color","default":"#000000","transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"}};
var paint_background = {"background-color":{"type":"color","default":"#000000","transition":true,"requires":[{"!":"background-pattern"}],"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"background-pattern":{"type":"string","transition":true,"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"cross-faded"},"background-opacity":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"}};
var transition = {"duration":{"type":"number","default":300,"minimum":0,"units":"milliseconds"},"delay":{"type":"number","default":0,"minimum":0,"units":"milliseconds"}};
var styleSpec = {
$version: $version,
$root: $root,
sources: sources,
source: source,
source_vector: source_vector,
source_raster: source_raster,
source_raster_dem: source_raster_dem,
source_geojson: source_geojson,
source_video: source_video,
source_image: source_image,
layer: layer,
layout: layout,
layout_background: layout_background,
layout_fill: layout_fill,
layout_circle: layout_circle,
layout_heatmap: layout_heatmap,
layout_line: layout_line,
layout_symbol: layout_symbol,
layout_raster: layout_raster,
layout_hillshade: layout_hillshade,
filter: filter,
filter_operator: filter_operator,
geometry_type: geometry_type,
function_stop: function_stop,
expression: expression,
expression_name: expression_name,
light: light,
paint: paint,
paint_fill: paint_fill,
paint_line: paint_line,
paint_circle: paint_circle,
paint_heatmap: paint_heatmap,
paint_symbol: paint_symbol,
paint_raster: paint_raster,
paint_hillshade: paint_hillshade,
paint_background: paint_background,
transition: transition,
"layout_fill-extrusion": {"visibility":{"type":"enum","values":{"visible":{},"none":{}},"default":"visible","property-type":"constant"}},
"function": {"expression":{"type":"expression"},"stops":{"type":"array","value":"function_stop"},"base":{"type":"number","default":1,"minimum":0},"property":{"type":"string","default":"$zoom"},"type":{"type":"enum","values":{"identity":{},"exponential":{},"interval":{},"categorical":{}},"default":"exponential"},"colorSpace":{"type":"enum","values":{"rgb":{},"lab":{},"hcl":{}},"default":"rgb"},"default":{"type":"*","required":false}},
"paint_fill-extrusion": {"fill-extrusion-opacity":{"type":"number","default":1,"minimum":0,"maximum":1,"transition":true,"expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"fill-extrusion-color":{"type":"color","default":"#000000","transition":true,"requires":[{"!":"fill-extrusion-pattern"}],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-extrusion-translate":{"type":"array","value":"number","length":2,"default":[0,0],"transition":true,"units":"pixels","expression":{"interpolated":true,"parameters":["zoom"]},"property-type":"data-constant"},"fill-extrusion-translate-anchor":{"type":"enum","values":{"map":{},"viewport":{}},"default":"map","requires":["fill-extrusion-translate"],"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"data-constant"},"fill-extrusion-pattern":{"type":"string","transition":true,"expression":{"interpolated":false,"parameters":["zoom"]},"property-type":"cross-faded"},"fill-extrusion-height":{"type":"number","default":0,"minimum":0,"units":"meters","transition":true,"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-extrusion-base":{"type":"number","default":0,"minimum":0,"units":"meters","transition":true,"requires":["fill-extrusion-height"],"expression":{"interpolated":true,"parameters":["zoom","feature","feature-state"]},"property-type":"data-driven"}},
"property-type": {"data-driven":{"type":"property-type"},"cross-faded":{"type":"property-type"},"cross-faded-data-driven":{"type":"property-type"},"color-ramp":{"type":"property-type"},"data-constant":{"type":"property-type"},"constant":{"type":"property-type"}}
};
var ValidationError = function ValidationError(key, value, message, identifier) {
this.message = (key ? (key + ": ") : '') + message;
if (identifier) { this.identifier = identifier; }
if (value !== null && value !== undefined && value.__line__) {
this.line = value.__line__;
}
};
function validateConstants(options) {
var key = options.key;
var constants = options.value;
if (constants) {
return [new ValidationError(key, constants, 'constants have been deprecated as of v8')];
} else {
return [];
}
}
function extend$1 (output) {
var inputs = [], len = arguments.length - 1;
while ( len-- > 0 ) inputs[ len ] = arguments[ len + 1 ];
for (var i = 0, list = inputs; i < list.length; i += 1) {
var input = list[i];
for (var k in input) {
output[k] = input[k];
}
}
return output;
}
// Turn jsonlint-lines-primitives objects into primitive objects
function unbundle(value) {
if (value instanceof Number || value instanceof String || value instanceof Boolean) {
return value.valueOf();
} else {
return value;
}
}
function deepUnbundle(value) {
if (Array.isArray(value)) {
return value.map(deepUnbundle);
}
return unbundle(value);
}
//
var ParsingError = (function (Error) {
function ParsingError(key , message ) {
Error.call(this, message);
this.message = message;
this.key = key;
}
if ( Error ) ParsingError.__proto__ = Error;
ParsingError.prototype = Object.create( Error && Error.prototype );
ParsingError.prototype.constructor = ParsingError;
return ParsingError;
}(Error));
//
/**
* Tracks `let` bindings during expression parsing.
* @private
*/
var Scope = function Scope(parent , bindings) {
var this$1 = this;
if ( bindings === void 0 ) bindings = [];
this.parent = parent;
this.bindings = {};
for (var i = 0, list = bindings; i < list.length; i += 1) {
var ref = list[i];
var name = ref[0];
var expression = ref[1];
this$1.bindings[name] = expression;
}
};
Scope.prototype.concat = function concat (bindings ) {
return new Scope(this, bindings);
};
Scope.prototype.get = function get (name ) {
if (this.bindings[name]) { return this.bindings[name]; }
if (this.parent) { return this.parent.get(name); }
throw new Error((name + " not found in scope."));
};
Scope.prototype.has = function has (name ) {
if (this.bindings[name]) { return true; }
return this.parent ? this.parent.has(name) : false;
};
//
var NullType = { kind: 'null' };
var NumberType = { kind: 'number' };
var StringType = { kind: 'string' };
var BooleanType = { kind: 'boolean' };
var ColorType = { kind: 'color' };
var ObjectType = { kind: 'object' };
var ValueType = { kind: 'value' };
var ErrorType = { kind: 'error' };
var CollatorType = { kind: 'collator' };
var FormattedType = { kind: 'formatted' };
function array(itemType , N ) {
return {
kind: 'array',
itemType: itemType,
N: N
};
}
function toString(type ) {
if (type.kind === 'array') {
var itemType = toString(type.itemType);
return typeof type.N === 'number' ?
("array<" + itemType + ", " + (type.N) + ">") :
type.itemType.kind === 'value' ? 'array' : ("array<" + itemType + ">");
} else {
return type.kind;
}
}
var valueMemberTypes = [
NullType,
NumberType,
StringType,
BooleanType,
ColorType,
FormattedType,
ObjectType,
array(ValueType)
];
/**
* Returns null if `t` is a subtype of `expected`; otherwise returns an
* error message.
* @private
*/
function checkSubtype(expected , t ) {
if (t.kind === 'error') {
// Error is a subtype of every type
return null;
} else if (expected.kind === 'array') {
if (t.kind === 'array' &&
!checkSubtype(expected.itemType, t.itemType) &&
(typeof expected.N !== 'number' || expected.N === t.N)) {
return null;
}
} else if (expected.kind === t.kind) {
return null;
} else if (expected.kind === 'value') {
for (var i = 0, list = valueMemberTypes; i < list.length; i += 1) {
var memberType = list[i];
if (!checkSubtype(memberType, t)) {
return null;
}
}
}
return ("Expected " + (toString(expected)) + " but found " + (toString(t)) + " instead.");
}
var csscolorparser = createCommonjsModule(function (module, exports) {
// (c) Dean McNamee <dean@gmail.com>, 2012.
//
// https://github.com/deanm/css-color-parser-js
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// http://www.w3.org/TR/css3-color/
var kCSSColorTable = {
"transparent": [0,0,0,0], "aliceblue": [240,248,255,1],
"antiquewhite": [250,235,215,1], "aqua": [0,255,255,1],
"aquamarine": [127,255,212,1], "azure": [240,255,255,1],
"beige": [245,245,220,1], "bisque": [255,228,196,1],
"black": [0,0,0,1], "blanchedalmond": [255,235,205,1],
"blue": [0,0,255,1], "blueviolet": [138,43,226,1],
"brown": [165,42,42,1], "burlywood": [222,184,135,1],
"cadetblue": [95,158,160,1], "chartreuse": [127,255,0,1],
"chocolate": [210,105,30,1], "coral": [255,127,80,1],
"cornflowerblue": [100,149,237,1], "cornsilk": [255,248,220,1],
"crimson": [220,20,60,1], "cyan": [0,255,255,1],
"darkblue": [0,0,139,1], "darkcyan": [0,139,139,1],
"darkgoldenrod": [184,134,11,1], "darkgray": [169,169,169,1],
"darkgreen": [0,100,0,1], "darkgrey": [169,169,169,1],
"darkkhaki": [189,183,107,1], "darkmagenta": [139,0,139,1],
"darkolivegreen": [85,107,47,1], "darkorange": [255,140,0,1],
"darkorchid": [153,50,204,1], "darkred": [139,0,0,1],
"darksalmon": [233,150,122,1], "darkseagreen": [143,188,143,1],
"darkslateblue": [72,61,139,1], "darkslategray": [47,79,79,1],
"darkslategrey": [47,79,79,1], "darkturquoise": [0,206,209,1],
"darkviolet": [148,0,211,1], "deeppink": [255,20,147,1],
"deepskyblue": [0,191,255,1], "dimgray": [105,105,105,1],
"dimgrey": [105,105,105,1], "dodgerblue": [30,144,255,1],
"firebrick": [178,34,34,1], "floralwhite": [255,250,240,1],
"forestgreen": [34,139,34,1], "fuchsia": [255,0,255,1],
"gainsboro": [220,220,220,1], "ghostwhite": [248,248,255,1],
"gold": [255,215,0,1], "goldenrod": [218,165,32,1],
"gray": [128,128,128,1], "green": [0,128,0,1],
"greenyellow": [173,255,47,1], "grey": [128,128,128,1],
"honeydew": [240,255,240,1], "hotpink": [255,105,180,1],
"indianred": [205,92,92,1], "indigo": [75,0,130,1],
"ivory": [255,255,240,1], "khaki": [240,230,140,1],
"lavender": [230,230,250,1], "lavenderblush": [255,240,245,1],
"lawngreen": [124,252,0,1], "lemonchiffon": [255,250,205,1],
"lightblue": [173,216,230,1], "lightcoral": [240,128,128,1],
"lightcyan": [224,255,255,1], "lightgoldenrodyellow": [250,250,210,1],
"lightgray": [211,211,211,1], "lightgreen": [144,238,144,1],
"lightgrey": [211,211,211,1], "lightpink": [255,182,193,1],
"lightsalmon": [255,160,122,1], "lightseagreen": [32,178,170,1],
"lightskyblue": [135,206,250,1], "lightslategray": [119,136,153,1],
"lightslategrey": [119,136,153,1], "lightsteelblue": [176,196,222,1],
"lightyellow": [255,255,224,1], "lime": [0,255,0,1],
"limegreen": [50,205,50,1], "linen": [250,240,230,1],
"magenta": [255,0,255,1], "maroon": [128,0,0,1],
"mediumaquamarine": [102,205,170,1], "mediumblue": [0,0,205,1],
"mediumorchid": [186,85,211,1], "mediumpurple": [147,112,219,1],
"mediumseagreen": [60,179,113,1], "mediumslateblue": [123,104,238,1],
"mediumspringgreen": [0,250,154,1], "mediumturquoise": [72,209,204,1],
"mediumvioletred": [199,21,133,1], "midnightblue": [25,25,112,1],
"mintcream": [245,255,250,1], "mistyrose": [255,228,225,1],
"moccasin": [255,228,181,1], "navajowhite": [255,222,173,1],
"navy": [0,0,128,1], "oldlace": [253,245,230,1],
"olive": [128,128,0,1], "olivedrab": [107,142,35,1],
"orange": [255,165,0,1], "orangered": [255,69,0,1],
"orchid": [218,112,214,1], "palegoldenrod": [238,232,170,1],
"palegreen": [152,251,152,1], "paleturquoise": [175,238,238,1],
"palevioletred": [219,112,147,1], "papayawhip": [255,239,213,1],
"peachpuff": [255,218,185,1], "peru": [205,133,63,1],
"pink": [255,192,203,1], "plum": [221,160,221,1],
"powderblue": [176,224,230,1], "purple": [128,0,128,1],
"rebeccapurple": [102,51,153,1],
"red": [255,0,0,1], "rosybrown": [188,143,143,1],
"royalblue": [65,105,225,1], "saddlebrown": [139,69,19,1],
"salmon": [250,128,114,1], "sandybrown": [244,164,96,1],
"seagreen": [46,139,87,1], "seashell": [255,245,238,1],
"sienna": [160,82,45,1], "silver": [192,192,192,1],
"skyblue": [135,206,235,1], "slateblue": [106,90,205,1],
"slategray": [112,128,144,1], "slategrey": [112,128,144,1],
"snow": [255,250,250,1], "springgreen": [0,255,127,1],
"steelblue": [70,130,180,1], "tan": [210,180,140,1],
"teal": [0,128,128,1], "thistle": [216,191,216,1],
"tomato": [255,99,71,1], "turquoise": [64,224,208,1],
"violet": [238,130,238,1], "wheat": [245,222,179,1],
"white": [255,255,255,1], "whitesmoke": [245,245,245,1],
"yellow": [255,255,0,1], "yellowgreen": [154,205,50,1]};
function clamp_css_byte(i) { // Clamp to integer 0 .. 255.
i = Math.round(i); // Seems to be what Chrome does (vs truncation).
return i < 0 ? 0 : i > 255 ? 255 : i;
}
function clamp_css_float(f) { // Clamp to float 0.0 .. 1.0.
return f < 0 ? 0 : f > 1 ? 1 : f;
}
function parse_css_int(str) { // int or percentage.
if (str[str.length - 1] === '%')
{ return clamp_css_byte(parseFloat(str) / 100 * 255); }
return clamp_css_byte(parseInt(str));
}
function parse_css_float(str) { // float or percentage.
if (str[str.length - 1] === '%')
{ return clamp_css_float(parseFloat(str) / 100); }
return clamp_css_float(parseFloat(str));
}
function css_hue_to_rgb(m1, m2, h) {
if (h < 0) { h += 1; }
else if (h > 1) { h -= 1; }
if (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; }
if (h * 2 < 1) { return m2; }
if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; }
return m1;
}
function parseCSSColor(css_str) {
// Remove all whitespace, not compliant, but should just be more accepting.
var str = css_str.replace(/ /g, '').toLowerCase();
// Color keywords (and transparent) lookup.
if (str in kCSSColorTable) { return kCSSColorTable[str].slice(); } // dup.
// #abc and #abc123 syntax.
if (str[0] === '#') {
if (str.length === 4) {
var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
if (!(iv >= 0 && iv <= 0xfff)) { return null; } // Covers NaN.
return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),
(iv & 0xf0) | ((iv & 0xf0) >> 4),
(iv & 0xf) | ((iv & 0xf) << 4),
1];
} else if (str.length === 7) {
var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
if (!(iv >= 0 && iv <= 0xffffff)) { return null; } // Covers NaN.
return [(iv & 0xff0000) >> 16,
(iv & 0xff00) >> 8,
iv & 0xff,
1];
}
return null;
}
var op = str.indexOf('('), ep = str.indexOf(')');
if (op !== -1 && ep + 1 === str.length) {
var fname = str.substr(0, op);
var params = str.substr(op+1, ep-(op+1)).split(',');
var alpha = 1; // To allow case fallthrough.
switch (fname) {
case 'rgba':
if (params.length !== 4) { return null; }
alpha = parse_css_float(params.pop());
// Fall through.
case 'rgb':
if (params.length !== 3) { return null; }
return [parse_css_int(params[0]),
parse_css_int(params[1]),
parse_css_int(params[2]),
alpha];
case 'hsla':
if (params.length !== 4) { return null; }
alpha = parse_css_float(params.pop());
// Fall through.
case 'hsl':
if (params.length !== 3) { return null; }
var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360; // 0 .. 1
// NOTE(deanm): According to the CSS spec s/l should only be
// percentages, but we don't bother and let float or percentage.
var s = parse_css_float(params[1]);
var l = parse_css_float(params[2]);
var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
var m1 = l * 2 - m2;
return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255),
clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255),
clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255),
alpha];
default:
return null;
}
}
return null;
}
try { exports.parseCSSColor = parseCSSColor; } catch(e) { }
});
var csscolorparser_1 = csscolorparser.parseCSSColor;
//
/**
* An RGBA color value. Create instances from color strings using the static
* method `Color.parse`. The constructor accepts RGB channel values in the range
* `[0, 1]`, premultiplied by A.
*
* @param {number} r The red channel.
* @param {number} g The green channel.
* @param {number} b The blue channel.
* @param {number} a The alpha channel.
* @private
*/
var Color = function Color(r , g , b , a) {
if ( a === void 0 ) a = 1;
this.r = r;
this.g = g;
this.b = b;
this.a = a;
};
/**
* Parses valid CSS color strings and returns a `Color` instance.
* @returns A `Color` instance, or `undefined` if the input is not a valid color string.
*/
Color.parse = function parse (input ) {
if (!input) {
return undefined;
}
if (input instanceof Color) {
return input;
}
if (typeof input !== 'string') {
return undefined;
}
var rgba = csscolorparser_1(input);
if (!rgba) {
return undefined;
}
return new Color(
rgba[0] / 255 * rgba[3],
rgba[1] / 255 * rgba[3],
rgba[2] / 255 * rgba[3],
rgba[3]
);
};
/**
* Returns an RGBA string representing the color value.
*
* @returns An RGBA string.
* @example
* var purple = new Color.parse('purple');
* purple.toString; // = "rgba(128,0,128,1)"
* var translucentGreen = new Color.parse('rgba(26, 207, 26, .73)');
* translucentGreen.toString(); // = "rgba(26,207,26,0.73)"
*/
Color.prototype.toString = function toString () {
var ref = this.toArray();
var r = ref[0];
var g = ref[1];
var b = ref[2];
var a = ref[3];
return ("rgba(" + (Math.round(r)) + "," + (Math.round(g)) + "," + (Math.round(b)) + "," + a + ")");
};
Color.prototype.toArray = function toArray () {
var ref = this;
var r = ref.r;
var g = ref.g;
var b = ref.b;
var a = ref.a;
return a === 0 ? [0, 0, 0, 0] : [
r * 255 / a,
g * 255 / a,
b * 255 / a,
a
];
};
Color.black = new Color(0, 0, 0, 1);
Color.white = new Color(1, 1, 1, 1);
Color.transparent = new Color(0, 0, 0, 0);
Color.red = new Color(1, 0, 0, 1);
//
// Flow type declarations for Intl cribbed from
// https://github.com/facebook/flow/issues/1270
var Collator = function Collator(caseSensitive , diacriticSensitive , locale ) {
if (caseSensitive)
{ this.sensitivity = diacriticSensitive ? 'variant' : 'case'; }
else
{ this.sensitivity = diacriticSensitive ? 'accent' : 'base'; }
this.locale = locale;
this.collator = new Intl.Collator(this.locale ? this.locale : [],
{ sensitivity: this.sensitivity, usage: 'search' });
};
Collator.prototype.compare = function compare (lhs , rhs ) {
return this.collator.compare(lhs, rhs);
};
Collator.prototype.resolvedLocale = function resolvedLocale () {
// We create a Collator without "usage: search" because we don't want
// the search options encoded in our result (e.g. "en-u-co-search")
return new Intl.Collator(this.locale ? this.locale : [])
.resolvedOptions().locale;
};
var CollatorExpression = function CollatorExpression(caseSensitive , diacriticSensitive , locale ) {
this.type = CollatorType;
this.locale = locale;
this.caseSensitive = caseSensitive;
this.diacriticSensitive = diacriticSensitive;
};
CollatorExpression.parse = function parse (args , context ) {
if (args.length !== 2)
{ return context.error("Expected one argument."); }
var options = (args[1] );
if (typeof options !== "object" || Array.isArray(options))
{ return context.error("Collator options argument must be an object."); }
var caseSensitive = context.parse(
options['case-sensitive'] === undefined ? false : options['case-sensitive'], 1, BooleanType);
if (!caseSensitive) { return null; }
var diacriticSensitive = context.parse(
options['diacritic-sensitive'] === undefined ? false : options['diacritic-sensitive'], 1, BooleanType);
if (!diacriticSensitive) { return null; }
var locale = null;
if (options['locale']) {
locale = context.parse(options['locale'], 1, StringType);
if (!locale) { return null; }
}
return new CollatorExpression(caseSensitive, diacriticSensitive, locale);
};
CollatorExpression.prototype.evaluate = function evaluate (ctx ) {
return new Collator(this.caseSensitive.evaluate(ctx), this.diacriticSensitive.evaluate(ctx), this.locale ? this.locale.evaluate(ctx) : null);
};
CollatorExpression.prototype.eachChild = function eachChild (fn ) {
fn(this.caseSensitive);
fn(this.diacriticSensitive);
if (this.locale) {
fn(this.locale);
}
};
CollatorExpression.prototype.possibleOutputs = function possibleOutputs () {
// Technically the set of possible outputs is the combinatoric set of Collators produced
// by all possibleOutputs of locale/caseSensitive/diacriticSensitive
// But for the primary use of Collators in comparison operators, we ignore the Collator's
// possibleOutputs anyway, so we can get away with leaving this undefined for now.
return [undefined];
};
CollatorExpression.prototype.serialize = function serialize () {
var options = {};
options['case-sensitive'] = this.caseSensitive.serialize();
options['diacritic-sensitive'] = this.diacriticSensitive.serialize();
if (this.locale) {
options['locale'] = this.locale.serialize();
}
return ["collator", options];
};
//
function validateRGBA(r , g , b , a ) {
if (!(
typeof r === 'number' && r >= 0 && r <= 255 &&
typeof g === 'number' && g >= 0 && g <= 255 &&
typeof b === 'number' && b >= 0 && b <= 255
)) {
var value = typeof a === 'number' ? [r, g, b, a] : [r, g, b];
return ("Invalid rgba value [" + (value.join(', ')) + "]: 'r', 'g', and 'b' must be between 0 and 255.");
}
if (!(
typeof a === 'undefined' || (typeof a === 'number' && a >= 0 && a <= 1)
)) {
return ("Invalid rgba value [" + ([r, g, b, a].join(', ')) + "]: 'a' must be between 0 and 1.");
}
return null;
}
function isValue(mixed ) {
if (mixed === null) {
return true;
} else if (typeof mixed === 'string') {
return true;
} else if (typeof mixed === 'boolean') {
return true;
} else if (typeof mixed === 'number') {
return true;
} else if (mixed instanceof Color) {
return true;
} else if (mixed instanceof Collator) {
return true;
} else if (Array.isArray(mixed)) {
for (var i = 0, list = mixed; i < list.length; i += 1) {
var item = list[i];
if (!isValue(item)) {
return false;
}
}
return true;
} else if (typeof mixed === 'object') {
for (var key in mixed) {
if (!isValue(mixed[key])) {
return false;
}
}
return true;
} else {
return false;
}
}
function typeOf(value ) {
if (value === null) {
return NullType;
} else if (typeof value === 'string') {
return StringType;
} else if (typeof value === 'boolean') {
return BooleanType;
} else if (typeof value === 'number') {
return NumberType;
} else if (value instanceof Color) {
return ColorType;
} else if (value instanceof Collator) {
return CollatorType;
} else if (Array.isArray(value)) {
var length = value.length;
var itemType ;
for (var i = 0, list = value; i < list.length; i += 1) {
var item = list[i];
var t = typeOf(item);
if (!itemType) {
itemType = t;
} else if (itemType === t) {
continue;
} else {
itemType = ValueType;
break;
}
}
return array(itemType || ValueType, length);
} else {
assert_1(typeof value === 'object');
return ObjectType;
}
}
//
var FormattedSection = function FormattedSection(text , scale , fontStack ) {
this.text = text;
this.scale = scale;
this.fontStack = fontStack;
};
var Formatted = function Formatted(sections ) {
this.sections = sections;
};
Formatted.prototype.toString = function toString$$1 () {
return this.sections.map(function (section) { return section.text; }).join('');
};
Formatted.prototype.serialize = function serialize () {
var this$1 = this;
var serialized = ["format"];
for (var i = 0, list = this$1.sections; i < list.length; i += 1) {
var section = list[i];
serialized.push(section.text);
var fontStack = section.fontStack ?
["literal", section.fontStack.split(',')] :
null;
serialized.push({ "text-font": fontStack, "font-scale": section.scale });
}
return serialized;
};
var FormatExpression = function FormatExpression(sections ) {
this.type = FormattedType;
this.sections = sections;
};
FormatExpression.parse = function parse (args , context ) {
if (args.length < 3) {
return context.error("Expected at least two arguments.");
}
if ((args.length - 1) % 2 !== 0) {
return context.error("Expected an even number of arguments.");
}
var sections = [];
for (var i = 1; i < args.length - 1; i += 2) {
var text = context.parse(args[i], 1, ValueType);
if (!text) { return null; }
var kind = text.type.kind;
if (kind !== 'string' && kind !== 'value' && kind !== 'null')
{ return context.error("Formatted text type must be 'string', 'value', or 'null'."); }
var options = (args[i + 1] );
if (typeof options !== "object" || Array.isArray(options))
{ return context.error("Format options argument must be an object."); }
var scale = null;
if (options['font-scale']) {
scale = context.parse(options['font-scale'], 1, NumberType);
if (!scale) { return null; }
}
var font = null;
if (options['text-font']) {
font = context.parse(options['text-font'], 1, array(StringType));
if (!font) { return null; }
}
sections.push({text: text, scale: scale, font: font});
}
return new FormatExpression(sections);
};
FormatExpression.prototype.evaluate = function evaluate (ctx ) {
return new Formatted(
this.sections.map(function (section) { return new FormattedSection(
section.text.evaluate(ctx) || "",
section.scale ? section.scale.evaluate(ctx) : null,
section.font ? section.font.evaluate(ctx).join(',') : null
); }
)
);
};
FormatExpression.prototype.eachChild = function eachChild (fn ) {
var this$1 = this;
for (var i = 0, list = this$1.sections; i < list.length; i += 1) {
var section = list[i];
fn(section.text);
if (section.scale) {
fn(section.scale);
}
if (section.font) {
fn(section.font);
}
}
};
FormatExpression.prototype.possibleOutputs = function possibleOutputs () {
// Technically the combinatoric set of all children
// Usually, this.text will be undefined anyway
return [undefined];
};
FormatExpression.prototype.serialize = function serialize () {
var this$1 = this;
var serialized = ["format"];
for (var i = 0, list = this$1.sections; i < list.length; i += 1) {
var section = list[i];
serialized.push(section.text.serialize());
var options = {};
if (section.scale) {
options['font-scale'] = section.scale.serialize();
}
if (section.font) {
options['text-font'] = section.font.serialize();
}
serialized.push(options);
}
return serialized;
};
//
var Literal = function Literal(type , value ) {
this.type = type;
this.value = value;
};
Literal.parse = function parse (args , context ) {
if (args.length !== 2)
{ return context.error(("'literal' expression requires exactly one argument, but found " + (args.length - 1) + " instead.")); }
if (!isValue(args[1]))
{ return context.error("invalid value"); }
var value = (args[1] );
var type = typeOf(value);
// special case: infer the item type if possible for zero-length arrays
var expected = context.expectedType;
if (
type.kind === 'array' &&
type.N === 0 &&
expected &&
expected.kind === 'array' &&
(typeof expected.N !== 'number' || expected.N === 0)
) {
type = expected;
}
return new Literal(type, value);
};
Literal.prototype.evaluate = function evaluate () {
return this.value;
};
Literal.prototype.eachChild = function eachChild () {};
Literal.prototype.possibleOutputs = function possibleOutputs () {
return [this.value];
};
Literal.prototype.serialize = function serialize () {
if (this.type.kind === 'array' || this.type.kind === 'object') {
return ["literal", this.value];
} else if (this.value instanceof Color) {
// Constant-folding can generate Literal expressions that you
// couldn't actually generate with a "literal" expression,
// so we have to implement an equivalent serialization here
return ["rgba"].concat(this.value.toArray());
} else if (this.value instanceof Formatted) {
// Same as Color
return this.value.serialize();
} else {
assert_1(this.value === null ||
typeof this.value === 'string' ||
typeof this.value === 'number' ||
typeof this.value === 'boolean');
return (this.value );
}
};
//
var RuntimeError = function RuntimeError(message ) {
this.name = 'ExpressionEvaluationError';
this.message = message;
};
RuntimeError.prototype.toJSON = function toJSON () {
return this.message;
};
//
var types = {
string: StringType,
number: NumberType,
boolean: BooleanType,
object: ObjectType
};
var Assertion = function Assertion(type , args ) {
this.type = type;
this.args = args;
};
Assertion.parse = function parse (args , context ) {
if (args.length < 2)
{ return context.error("Expected at least one argument."); }
var name = (args[0] );
assert_1(types[name], name);
var type = types[name];
var parsed = [];
for (var i = 1; i < args.length; i++) {
var input = context.parse(args[i], i, ValueType);
if (!input) { return null; }
parsed.push(input);
}
return new Assertion(type, parsed);
};
Assertion.prototype.evaluate = function evaluate (ctx ) {
var this$1 = this;
for (var i = 0; i < this.args.length; i++) {
var value = this$1.args[i].evaluate(ctx);
var error = checkSubtype(this$1.type, typeOf(value));
if (!error) {
return value;
} else if (i === this$1.args.length - 1) {
throw new RuntimeError(("Expected value to be of type " + (toString(this$1.type)) + ", but found " + (toString(typeOf(value))) + " instead."));
}
}
assert_1(false);
return null;
};
Assertion.prototype.eachChild = function eachChild (fn ) {
this.args.forEach(fn);
};
Assertion.prototype.possibleOutputs = function possibleOutputs () {
return (ref = []).concat.apply(ref, this.args.map(function (arg) { return arg.possibleOutputs(); }));
var ref;
};
Assertion.prototype.serialize = function serialize () {
return [this.type.kind].concat(this.args.map(function (arg) { return arg.serialize(); }));
};
//
var types$1 = {
string: StringType,
number: NumberType,
boolean: BooleanType
};
var ArrayAssertion = function ArrayAssertion(type , input ) {
this.type = type;
this.input = input;
};
ArrayAssertion.parse = function parse (args , context ) {
if (args.length < 2 || args.length > 4)
{ return context.error(("Expected 1, 2, or 3 arguments, but found " + (args.length - 1) + " instead.")); }
var itemType;
var N;
if (args.length > 2) {
var type$1 = args[1];
if (typeof type$1 !== 'string' || !(type$1 in types$1))
{ return context.error('The item type argument of "array" must be one of string, number, boolean', 1); }
itemType = types$1[type$1];
} else {
itemType = ValueType;
}
if (args.length > 3) {
if (
typeof args[2] !== 'number' ||
args[2] < 0 ||
args[2] !== Math.floor(args[2])
) {
return context.error('The length argument to "array" must be a positive integer literal', 2);
}
N = args[2];
}
var type = array(itemType, N);
var input = context.parse(args[args.length - 1], args.length - 1, ValueType);
if (!input) { return null; }
return new ArrayAssertion(type, input);
};
ArrayAssertion.prototype.evaluate = function evaluate (ctx ) {
var value = this.input.evaluate(ctx);
var error = checkSubtype(this.type, typeOf(value));
if (error) {
throw new RuntimeError(("Expected value to be of type " + (toString(this.type)) + ", but found " + (toString(typeOf(value))) + " instead."));
}
return value;
};
ArrayAssertion.prototype.eachChild = function eachChild (fn ) {
fn(this.input);
};
ArrayAssertion.prototype.possibleOutputs = function possibleOutputs () {
return this.input.possibleOutputs();
};
ArrayAssertion.prototype.serialize = function serialize () {
var serialized = ["array"];
var itemType = this.type.itemType;
if (itemType.kind === 'string' ||
itemType.kind === 'number' ||
itemType.kind === 'boolean') {
serialized.push(itemType.kind);
var N = this.type.N;
if (typeof N === 'number') {
serialized.push(N);
}
}
serialized.push(this.input.serialize());
return serialized;
};
//
var types$2 = {
'to-number': NumberType,
'to-color': ColorType
};
/**
* Special form for error-coalescing coercion expressions "to-number",
* "to-color". Since these coercions can fail at runtime, they accept multiple
* arguments, only evaluating one at a time until one succeeds.
*
* @private
*/
var Coercion = function Coercion(type , args ) {
this.type = type;
this.args = args;
};
Coercion.parse = function parse (args , context ) {
if (args.length < 2)
{ return context.error("Expected at least one argument."); }
var name = (args[0] );
assert_1(types$2[name], name);
var type = types$2[name];
var parsed = [];
for (var i = 1; i < args.length; i++) {
var input = context.parse(args[i], i, ValueType);
if (!input) { return null; }
parsed.push(input);
}
return new Coercion(type, parsed);
};
Coercion.prototype.evaluate = function evaluate (ctx ) {
var this$1 = this;
if (this.type.kind === 'color') {
var input;
var error;
for (var i = 0, list = this$1.args; i < list.length; i += 1) {
var arg = list[i];
input = arg.evaluate(ctx);
error = null;
if (typeof input === 'string') {
var c = ctx.parseColor(input);
if (c) { return c; }
} else if (Array.isArray(input)) {
if (input.length < 3 || input.length > 4) {
error = "Invalid rbga value " + (JSON.stringify(input)) + ": expected an array containing either three or four numeric values.";
} else {
error = validateRGBA(input[0], input[1], input[2], input[3]);
}
if (!error) {
return new Color((input[0] ) / 255, (input[1] ) / 255, (input[2] ) / 255, (input[3] ));
}
}
}
throw new RuntimeError(error || ("Could not parse color from value '" + (typeof input === 'string' ? input : JSON.stringify(input)) + "'"));
} else if (this.type.kind === 'formatted') {
var input$1;
for (var i$1 = 0, list$1 = this$1.args; i$1 < list$1.length; i$1 += 1) {
var arg$1 = list$1[i$1];
input$1 = arg$1.evaluate(ctx);
if (typeof input$1 === 'string') {
return new Formatted([new FormattedSection(input$1, null, null)]);
}
}
throw new RuntimeError(("Could not parse formatted text from value '" + (typeof input$1 === 'string' ? input$1 : JSON.stringify(input$1)) + "'"));
} else {
var value = null;
for (var i$2 = 0, list$2 = this$1.args; i$2 < list$2.length; i$2 += 1) {
var arg$2 = list$2[i$2];
value = arg$2.evaluate(ctx);
if (value === null) { continue; }
var num = Number(value);
if (isNaN(num)) { continue; }
return num;
}
throw new RuntimeError(("Could not convert " + (JSON.stringify(value)) + " to number."));
}
};
Coercion.prototype.eachChild = function eachChild (fn ) {
this.args.forEach(fn);
};
Coercion.prototype.possibleOutputs = function possibleOutputs () {
return (ref = []).concat.apply(ref, this.args.map(function (arg) { return arg.possibleOutputs(); }));
var ref;
};
Coercion.prototype.serialize = function serialize () {
var serialized = [("to-" + (this.type.kind))];
this.eachChild(function (child) { serialized.push(child.serialize()); });
return serialized;
};
//
var geometryTypes = ['Unknown', 'Point', 'LineString', 'Polygon'];
var EvaluationContext = function EvaluationContext() {
this._parseColorCache = {};
};
EvaluationContext.prototype.id = function id () {
return this.feature && 'id' in this.feature ? this.feature.id : null;
};
EvaluationContext.prototype.geometryType = function geometryType () {
return this.feature ? typeof this.feature.type === 'number' ? geometryTypes[this.feature.type] : this.feature.type : null;
};
EvaluationContext.prototype.properties = function properties () {
return this.feature && this.feature.properties || {};
};
EvaluationContext.prototype.parseColor = function parseColor (input ) {
var cached = this._parseColorCache[input];
if (!cached) {
cached = this._parseColorCache[input] = Color.parse(input);
}
return cached;
};
//
var CompoundExpression = function CompoundExpression(name , type , evaluate , args ) {
this.name = name;
this.type = type;
this._evaluate = evaluate;
this.args = args;
};
CompoundExpression.prototype.evaluate = function evaluate (ctx ) {
return this._evaluate(ctx, this.args);
};
CompoundExpression.prototype.eachChild = function eachChild (fn ) {
this.args.forEach(fn);
};
CompoundExpression.prototype.possibleOutputs = function possibleOutputs () {
return [undefined];
};
CompoundExpression.prototype.serialize = function serialize () {
return [this.name].concat(this.args.map(function (arg) { return arg.serialize(); }));
};
CompoundExpression.parse = function parse (args , context ) {
var op = (args[0] );
var definition = CompoundExpression.definitions[op];
if (!definition) {
return context.error(("Unknown expression \"" + op + "\". If you wanted a literal array, use [\"literal\", [...]]."), 0);
}
// Now check argument types against each signature
var type = Array.isArray(definition) ?
definition[0] : definition.type;
var availableOverloads = Array.isArray(definition) ?
[[definition[1], definition[2]]] :
definition.overloads;
var overloads = availableOverloads.filter(function (ref) {
var signature = ref[0];
return (
!Array.isArray(signature) || // varags
signature.length === args.length - 1 // correct param count
);
});
var signatureContext = (null );
for (var i$3 = 0, list = overloads; i$3 < list.length; i$3 += 1) {
// Use a fresh context for each attempted signature so that, if
// we eventually succeed, we haven't polluted `context.errors`.
var ref = list[i$3];
var params = ref[0];
var evaluate = ref[1];
signatureContext = new ParsingContext(context.registry, context.path, null, context.scope);
// First parse all the args, potentially coercing to the
// types expected by this overload.
var parsedArgs = [];
var argParseFailed = false;
for (var i = 1; i < args.length; i++) {
var arg = args[i];
var expectedType = Array.isArray(params) ?
params[i - 1] :
params.type;
var parsed = signatureContext.parse(arg, 1 + parsedArgs.length, expectedType);
if (!parsed) {
argParseFailed = true;
break;
}
parsedArgs.push(parsed);
}
if (argParseFailed) {
// Couldn't coerce args of this overload to expected type, move
// on to next one.
continue;
}
if (Array.isArray(params)) {
if (params.length !== parsedArgs.length) {
signatureContext.error(("Expected " + (params.length) + " arguments, but found " + (parsedArgs.length) + " instead."));
continue;
}
}
for (var i$1 = 0; i$1 < parsedArgs.length; i$1++) {
var expected = Array.isArray(params) ? params[i$1] : params.type;
var arg$1 = parsedArgs[i$1];
signatureContext.concat(i$1 + 1).checkSubtype(expected, arg$1.type);
}
if (signatureContext.errors.length === 0) {
return new CompoundExpression(op, type, evaluate, parsedArgs);
}
}
assert_1(!signatureContext || signatureContext.errors.length > 0);
if (overloads.length === 1) {
context.errors.push.apply(context.errors, signatureContext.errors);
} else {
var expected$1 = overloads.length ? overloads : availableOverloads;
var signatures = expected$1
.map(function (ref) {
var params = ref[0];
return stringifySignature(params);
})
.join(' | ');
var actualTypes = [];
// For error message, re-parse arguments without trying to
// apply any coercions
for (var i$2 = 1; i$2 < args.length; i$2++) {
var parsed$1 = context.parse(args[i$2], 1 + actualTypes.length);
if (!parsed$1) { return null; }
actualTypes.push(toString(parsed$1.type));
}
context.error(("Expected arguments of type " + signatures + ", but found (" + (actualTypes.join(', ')) + ") instead."));
}
return null;
};
CompoundExpression.register = function register (
registry ,
definitions
) {
assert_1(!CompoundExpression.definitions);
CompoundExpression.definitions = definitions;
for (var name in definitions) {
registry[name] = CompoundExpression;
}
};
function stringifySignature(signature ) {
if (Array.isArray(signature)) {
return ("(" + (signature.map(toString).join(', ')) + ")");
} else {
return ("(" + (toString(signature.type)) + "...)");
}
}
//
function isFeatureConstant(e ) {
if (e instanceof CompoundExpression) {
if (e.name === 'get' && e.args.length === 1) {
return false;
} else if (e.name === 'feature-state') {
return false;
} else if (e.name === 'has' && e.args.length === 1) {
return false;
} else if (
e.name === 'properties' ||
e.name === 'geometry-type' ||
e.name === 'id'
) {
return false;
} else if (/^filter-/.test(e.name)) {
return false;
}
}
var result = true;
e.eachChild(function (arg) {
if (result && !isFeatureConstant(arg)) { result = false; }
});
return result;
}
function isStateConstant(e ) {
if (e instanceof CompoundExpression) {
if (e.name === 'feature-state') {
return false;
}
}
var result = true;
e.eachChild(function (arg) {
if (result && !isStateConstant(arg)) { result = false; }
});
return result;
}
function isGlobalPropertyConstant(e , properties ) {
if (e instanceof CompoundExpression && properties.indexOf(e.name) >= 0) { return false; }
var result = true;
e.eachChild(function (arg) {
if (result && !isGlobalPropertyConstant(arg, properties)) { result = false; }
});
return result;
}
//
var Var = function Var(name , boundExpression ) {
this.type = boundExpression.type;
this.name = name;
this.boundExpression = boundExpression;
};
Var.parse = function parse (args , context ) {
if (args.length !== 2 || typeof args[1] !== 'string')
{ return context.error("'var' expression requires exactly one string literal argument."); }
var name = args[1];
if (!context.scope.has(name)) {
return context.error(("Unknown variable \"" + name + "\". Make sure \"" + name + "\" has been bound in an enclosing \"let\" expression before using it."), 1);
}
return new Var(name, context.scope.get(name));
};
Var.prototype.evaluate = function evaluate (ctx ) {
return this.boundExpression.evaluate(ctx);
};
Var.prototype.eachChild = function eachChild () {};
Var.prototype.possibleOutputs = function possibleOutputs () {
return [undefined];
};
Var.prototype.serialize = function serialize () {
return ["var", this.name];
};
//
/**
* State associated parsing at a given point in an expression tree.
* @private
*/
var ParsingContext = function ParsingContext(
registry ,
path,
expectedType ,
scope,
errors
) {
if ( path === void 0 ) path = [];
if ( scope === void 0 ) scope = new Scope();
if ( errors === void 0 ) errors = [];
this.registry = registry;
this.path = path;
this.key = path.map(function (part) { return ("[" + part + "]"); }).join('');
this.scope = scope;
this.errors = errors;
this.expectedType = expectedType;
};
/**
* @param expr the JSON expression to parse
* @param index the optional argument index if this expression is an argument of a parent expression that's being parsed
* @param options
* @param options.omitTypeAnnotations set true to omit inferred type annotations. Caller beware: with this option set, the parsed expression's type will NOT satisfy `expectedType` if it would normally be wrapped in an inferred annotation.
* @private
*/
ParsingContext.prototype.parse = function parse (
expr ,
index ,
expectedType ,
bindings ,
options
) {
if ( options === void 0 ) options = {};
if (index) {
return this.concat(index, expectedType, bindings)._parse(expr, options);
}
return this._parse(expr, options);
};
ParsingContext.prototype._parse = function _parse (expr , options ) {
if (expr === null || typeof expr === 'string' || typeof expr === 'boolean' || typeof expr === 'number') {
expr = ['literal', expr];
}
if (Array.isArray(expr)) {
if (expr.length === 0) {
return this.error("Expected an array with at least one element. If you wanted a literal array, use [\"literal\", []].");
}
var op = expr[0];
if (typeof op !== 'string') {
this.error(("Expression name must be a string, but found " + (typeof op) + " instead. If you wanted a literal array, use [\"literal\", [...]]."), 0);
return null;
}
var Expr = this.registry[op];
if (Expr) {
var parsed = Expr.parse(expr, this);
if (!parsed) { return null; }
if (this.expectedType) {
var expected = this.expectedType;
var actual = parsed.type;
// When we expect a number, string, boolean, or array but
// have a Value, we can wrap it in a refining assertion.
// When we expect a Color but have a String or Value, we
// can wrap it in "to-color" coercion.
// Otherwise, we do static type-checking.
if ((expected.kind === 'string' || expected.kind === 'number' || expected.kind === 'boolean' || expected.kind === 'object') && actual.kind === 'value') {
if (!options.omitTypeAnnotations) {
parsed = new Assertion(expected, [parsed]);
}
} else if (expected.kind === 'array' && actual.kind === 'value') {
if (!options.omitTypeAnnotations) {
parsed = new ArrayAssertion(expected, parsed);
}
} else if (expected.kind === 'color' && (actual.kind === 'value' || actual.kind === 'string')) {
if (!options.omitTypeAnnotations) {
parsed = new Coercion(expected, [parsed]);
}
} else if (expected.kind === 'formatted' && (actual.kind === 'value' || actual.kind === 'string')) {
if (!options.omitTypeAnnotations) {
parsed = new Coercion(expected, [parsed]);
}
} else if (this.checkSubtype(this.expectedType, parsed.type)) {
return null;
}
}
// If an expression's arguments are all literals, we can evaluate
// it immediately and replace it with a literal value in the
// parsed/compiled result.
if (!(parsed instanceof Literal) && isConstant(parsed)) {
var ec = new EvaluationContext();
try {
parsed = new Literal(parsed.type, parsed.evaluate(ec));
} catch (e) {
this.error(e.message);
return null;
}
}
return parsed;
}
return this.error(("Unknown expression \"" + op + "\". If you wanted a literal array, use [\"literal\", [...]]."), 0);
} else if (typeof expr === 'undefined') {
return this.error("'undefined' value invalid. Use null instead.");
} else if (typeof expr === 'object') {
return this.error("Bare objects invalid. Use [\"literal\", {...}] instead.");
} else {
return this.error(("Expected an array, but found " + (typeof expr) + " instead."));
}
};
/**
* Returns a copy of this context suitable for parsing the subexpression at
* index `index`, optionally appending to 'let' binding map.
*
* Note that `errors` property, intended for collecting errors while
* parsing, is copied by reference rather than cloned.
* @private
*/
ParsingContext.prototype.concat = function concat (index , expectedType , bindings ) {
var path = typeof index === 'number' ? this.path.concat(index) : this.path;
var scope = bindings ? this.scope.concat(bindings) : this.scope;
return new ParsingContext(
this.registry,
path,
expectedType || null,
scope,
this.errors
);
};
/**
* Push a parsing (or type checking) error into the `this.errors`
* @param error The message
* @param keys Optionally specify the source of the error at a child
* of the current expression at `this.key`.
* @private
*/
ParsingContext.prototype.error = function error (error$1 ) {
var keys = [], len = arguments.length - 1;
while ( len-- > 0 ) keys[ len ] = arguments[ len + 1 ];
var key = "" + (this.key) + (keys.map(function (k) { return ("[" + k + "]"); }).join(''));
this.errors.push(new ParsingError(key, error$1));
};
/**
* Returns null if `t` is a subtype of `expected`; otherwise returns an
* error message and also pushes it to `this.errors`.
*/
ParsingContext.prototype.checkSubtype = function checkSubtype$1 (expected , t ) {
var error = checkSubtype(expected, t);
if (error) { this.error(error); }
return error;
};
function isConstant(expression ) {
if (expression instanceof Var) {
return isConstant(expression.boundExpression);
} else if (expression instanceof CompoundExpression && expression.name === 'error') {
return false;
} else if (expression instanceof CollatorExpression) {
// Although the results of a Collator expression with fixed arguments
// generally shouldn't change between executions, we can't serialize them
// as constant expressions because results change based on environment.
return false;
}
var isTypeAnnotation = expression instanceof Coercion ||
expression instanceof Assertion ||
expression instanceof ArrayAssertion;
var childrenConstant = true;
expression.eachChild(function (child) {
// We can _almost_ assume that if `expressions` children are constant,
// they would already have been evaluated to Literal values when they
// were parsed. Type annotations are the exception, because they might
// have been inferred and added after a child was parsed.
// So we recurse into isConstant() for the children of type annotations,
// but otherwise simply check whether they are Literals.
if (isTypeAnnotation) {
childrenConstant = childrenConstant && isConstant(child);
} else {
childrenConstant = childrenConstant && child instanceof Literal;
}
});
if (!childrenConstant) {
return false;
}
return isFeatureConstant(expression) &&
isGlobalPropertyConstant(expression, ['zoom', 'heatmap-density', 'line-progress', 'is-supported-script']);
}
//
/**
* Returns the index of the last stop <= input, or 0 if it doesn't exist.
* @private
*/
function findStopLessThanOrEqualTo(stops , input ) {
var n = stops.length;
var lowerIndex = 0;
var upperIndex = n - 1;
var currentIndex = 0;
var currentValue, upperValue;
while (lowerIndex <= upperIndex) {
currentIndex = Math.floor((lowerIndex + upperIndex) / 2);
currentValue = stops[currentIndex];
upperValue = stops[currentIndex + 1];
if (input === currentValue || input > currentValue && input < upperValue) { // Search complete
return currentIndex;
} else if (currentValue < input) {
lowerIndex = currentIndex + 1;
} else if (currentValue > input) {
upperIndex = currentIndex - 1;
} else {
throw new RuntimeError('Input is not a number.');
}
}
return Math.max(currentIndex - 1, 0);
}
//
var Step = function Step(type , input , stops ) {
var this$1 = this;
this.type = type;
this.input = input;
this.labels = [];
this.outputs = [];
for (var i = 0, list = stops; i < list.length; i += 1) {
var ref = list[i];
var label = ref[0];
var expression = ref[1];
this$1.labels.push(label);
this$1.outputs.push(expression);
}
};
Step.parse = function parse (args , context ) {
var input = args[1];
var rest = args.slice(2);
if (args.length - 1 < 4) {
return context.error(("Expected at least 4 arguments, but found only " + (args.length - 1) + "."));
}
if ((args.length - 1) % 2 !== 0) {
return context.error("Expected an even number of arguments.");
}
input = context.parse(input, 1, NumberType);
if (!input) { return null; }
var stops = [];
var outputType = (null );
if (context.expectedType && context.expectedType.kind !== 'value') {
outputType = context.expectedType;
}
rest.unshift(-Infinity);
for (var i = 0; i < rest.length; i += 2) {
var label = rest[i];
var value = rest[i + 1];
var labelKey = i + 1;
var valueKey = i + 2;
if (typeof label !== 'number') {
return context.error('Input/output pairs for "step" expressions must be defined using literal numeric values (not computed expressions) for the input values.', labelKey);
}
if (stops.length && stops[stops.length - 1][0] >= label) {
return context.error('Input/output pairs for "step" expressions must be arranged with input values in strictly ascending order.', labelKey);
}
var parsed = context.parse(value, valueKey, outputType);
if (!parsed) { return null; }
outputType = outputType || parsed.type;
stops.push([label, parsed]);
}
return new Step(outputType, input, stops);
};
Step.prototype.evaluate = function evaluate (ctx ) {
var labels = this.labels;
var outputs = this.outputs;
if (labels.length === 1) {
return outputs[0].evaluate(ctx);
}
var value = ((this.input.evaluate(ctx) ) );
if (value <= labels[0]) {
return outputs[0].evaluate(ctx);
}
var stopCount = labels.length;
if (value >= labels[stopCount - 1]) {
return outputs[stopCount - 1].evaluate(ctx);
}
var index = findStopLessThanOrEqualTo(labels, value);
return outputs[index].evaluate(ctx);
};
Step.prototype.eachChild = function eachChild (fn ) {
var this$1 = this;
fn(this.input);
for (var i = 0, list = this$1.outputs; i < list.length; i += 1) {
var expression = list[i];
fn(expression);
}
};
Step.prototype.possibleOutputs = function possibleOutputs () {
return (ref = []).concat.apply(ref, this.outputs.map(function (output) { return output.possibleOutputs(); }));
var ref;
};
Step.prototype.serialize = function serialize () {
var this$1 = this;
var serialized = ["step", this.input.serialize()];
for (var i = 0; i < this.labels.length; i++) {
if (i > 0) {
serialized.push(this$1.labels[i]);
}
serialized.push(this$1.outputs[i].serialize());
}
return serialized;
};
/*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Ported from Webkit
* http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/UnitBezier.h
*/
var unitbezier$1 = UnitBezier$1;
function UnitBezier$1(p1x, p1y, p2x, p2y) {
// Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
this.cx = 3.0 * p1x;
this.bx = 3.0 * (p2x - p1x) - this.cx;
this.ax = 1.0 - this.cx - this.bx;
this.cy = 3.0 * p1y;
this.by = 3.0 * (p2y - p1y) - this.cy;
this.ay = 1.0 - this.cy - this.by;
this.p1x = p1x;
this.p1y = p2y;
this.p2x = p2x;
this.p2y = p2y;
}
UnitBezier$1.prototype.sampleCurveX = function(t) {
// `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
return ((this.ax * t + this.bx) * t + this.cx) * t;
};
UnitBezier$1.prototype.sampleCurveY = function(t) {
return ((this.ay * t + this.by) * t + this.cy) * t;
};
UnitBezier$1.prototype.sampleCurveDerivativeX = function(t) {
return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx;
};
UnitBezier$1.prototype.solveCurveX = function(x, epsilon) {
var this$1 = this;
if (typeof epsilon === 'undefined') { epsilon = 1e-6; }
var t0, t1, t2, x2, i;
// First try a few iterations of Newton's method -- normally very fast.
for (t2 = x, i = 0; i < 8; i++) {
x2 = this$1.sampleCurveX(t2) - x;
if (Math.abs(x2) < epsilon) { return t2; }
var d2 = this$1.sampleCurveDerivativeX(t2);
if (Math.abs(d2) < 1e-6) { break; }
t2 = t2 - x2 / d2;
}
// Fall back to the bisection method for reliability.
t0 = 0.0;
t1 = 1.0;
t2 = x;
if (t2 < t0) { return t0; }
if (t2 > t1) { return t1; }
while (t0 < t1) {
x2 = this$1.sampleCurveX(t2);
if (Math.abs(x2 - x) < epsilon) { return t2; }
if (x > x2) {
t0 = t2;
} else {
t1 = t2;
}
t2 = (t1 - t0) * 0.5 + t0;
}
// Failure.
return t2;
};
UnitBezier$1.prototype.solve = function(x, epsilon) {
return this.sampleCurveY(this.solveCurveX(x, epsilon));
};
//
function number(a , b , t ) {
return (a * (1 - t)) + (b * t);
}
function color(from , to , t ) {
return new Color(
number(from.r, to.r, t),
number(from.g, to.g, t),
number(from.b, to.b, t),
number(from.a, to.a, t)
);
}
function array$1(from , to , t ) {
return from.map(function (d, i) {
return number(d, to[i], t);
});
}
var interpolate = /*#__PURE__*/Object.freeze({
number: number,
color: color,
array: array$1
});
//
// Constants
var Xn = 0.950470, // D65 standard referent
Yn = 1,
Zn = 1.088830,
t0 = 4 / 29,
t1 = 6 / 29,
t2 = 3 * t1 * t1,
t3 = t1 * t1 * t1,
deg2rad = Math.PI / 180,
rad2deg = 180 / Math.PI;
// Utilities
function xyz2lab(t) {
return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
}
function lab2xyz(t) {
return t > t1 ? t * t * t : t2 * (t - t0);
}
function xyz2rgb(x) {
return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
}
function rgb2xyz(x) {
x /= 255;
return x <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
}
// LAB
function rgbToLab(rgbColor ) {
var b = rgb2xyz(rgbColor.r),
a = rgb2xyz(rgbColor.g),
l = rgb2xyz(rgbColor.b),
x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn),
y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn),
z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn);
return {
l: 116 * y - 16,
a: 500 * (x - y),
b: 200 * (y - z),
alpha: rgbColor.a
};
}
function labToRgb(labColor ) {
var y = (labColor.l + 16) / 116,
x = isNaN(labColor.a) ? y : y + labColor.a / 500,
z = isNaN(labColor.b) ? y : y - labColor.b / 200;
y = Yn * lab2xyz(y);
x = Xn * lab2xyz(x);
z = Zn * lab2xyz(z);
return new Color(
xyz2rgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
xyz2rgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z),
labColor.alpha
);
}
function interpolateLab(from , to , t ) {
return {
l: number(from.l, to.l, t),
a: number(from.a, to.a, t),
b: number(from.b, to.b, t),
alpha: number(from.alpha, to.alpha, t)
};
}
// HCL
function rgbToHcl(rgbColor ) {
var ref = rgbToLab(rgbColor);
var l = ref.l;
var a = ref.a;
var b = ref.b;
var h = Math.atan2(b, a) * rad2deg;
return {
h: h < 0 ? h + 360 : h,
c: Math.sqrt(a * a + b * b),
l: l,
alpha: rgbColor.a
};
}
function hclToRgb(hclColor ) {
var h = hclColor.h * deg2rad,
c = hclColor.c,
l = hclColor.l;
return labToRgb({
l: l,
a: Math.cos(h) * c,
b: Math.sin(h) * c,
alpha: hclColor.alpha
});
}
function interpolateHue(a , b , t ) {
var d = b - a;
return a + t * (d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d);
}
function interpolateHcl(from , to , t ) {
return {
h: interpolateHue(from.h, to.h, t),
c: number(from.c, to.c, t),
l: number(from.l, to.l, t),
alpha: number(from.alpha, to.alpha, t)
};
}
var lab = {
forward: rgbToLab,
reverse: labToRgb,
interpolate: interpolateLab
};
var hcl = {
forward: rgbToHcl,
reverse: hclToRgb,
interpolate: interpolateHcl
};
var colorSpaces = /*#__PURE__*/Object.freeze({
lab: lab,
hcl: hcl
});
//
var Interpolate = function Interpolate(type , operator , interpolation , input , stops ) {
var this$1 = this;
this.type = type;
this.operator = operator;
this.interpolation = interpolation;
this.input = input;
this.labels = [];
this.outputs = [];
for (var i = 0, list = stops; i < list.length; i += 1) {
var ref = list[i];
var label = ref[0];
var expression = ref[1];
this$1.labels.push(label);
this$1.outputs.push(expression);
}
};
Interpolate.interpolationFactor = function interpolationFactor (interpolation , input , lower , upper ) {
var t = 0;
if (interpolation.name === 'exponential') {
t = exponentialInterpolation(input, interpolation.base, lower, upper);
} else if (interpolation.name === 'linear') {
t = exponentialInterpolation(input, 1, lower, upper);
} else if (interpolation.name === 'cubic-bezier') {
var c = interpolation.controlPoints;
var ub = new unitbezier$1(c[0], c[1], c[2], c[3]);
t = ub.solve(exponentialInterpolation(input, 1, lower, upper));
}
return t;
};
Interpolate.parse = function parse (args , context ) {
var operator = args[0];
var interpolation = args[1];
var input = args[2];
var rest = args.slice(3);
if (!Array.isArray(interpolation) || interpolation.length === 0) {
return context.error("Expected an interpolation type expression.", 1);
}
if (interpolation[0] === 'linear') {
interpolation = { name: 'linear' };
} else if (interpolation[0] === 'exponential') {
var base = interpolation[1];
if (typeof base !== 'number')
{ return context.error("Exponential interpolation requires a numeric base.", 1, 1); }
interpolation = {
name: 'exponential',
base: base
};
} else if (interpolation[0] === 'cubic-bezier') {
var controlPoints = interpolation.slice(1);
if (
controlPoints.length !== 4 ||
controlPoints.some(function (t) { return typeof t !== 'number' || t < 0 || t > 1; })
) {
return context.error('Cubic bezier interpolation requires four numeric arguments with values between 0 and 1.', 1);
}
interpolation = {
name: 'cubic-bezier',
controlPoints: (controlPoints )
};
} else {
return context.error(("Unknown interpolation type " + (String(interpolation[0]))), 1, 0);
}
if (args.length - 1 < 4) {
return context.error(("Expected at least 4 arguments, but found only " + (args.length - 1) + "."));
}
if ((args.length - 1) % 2 !== 0) {
return context.error("Expected an even number of arguments.");
}
input = context.parse(input, 2, NumberType);
if (!input) { return null; }
var stops = [];
var outputType = (null );
if (operator === 'interpolate-hcl' || operator === 'interpolate-lab') {
outputType = ColorType;
} else if (context.expectedType && context.expectedType.kind !== 'value') {
outputType = context.expectedType;
}
for (var i = 0; i < rest.length; i += 2) {
var label = rest[i];
var value = rest[i + 1];
var labelKey = i + 3;
var valueKey = i + 4;
if (typeof label !== 'number') {
return context.error('Input/output pairs for "interpolate" expressions must be defined using literal numeric values (not computed expressions) for the input values.', labelKey);
}
if (stops.length && stops[stops.length - 1][0] >= label) {
return context.error('Input/output pairs for "interpolate" expressions must be arranged with input values in strictly ascending order.', labelKey);
}
var parsed = context.parse(value, valueKey, outputType);
if (!parsed) { return null; }
outputType = outputType || parsed.type;
stops.push([label, parsed]);
}
if (outputType.kind !== 'number' &&
outputType.kind !== 'color' &&
!(
outputType.kind === 'array' &&
outputType.itemType.kind === 'number' &&
typeof outputType.N === 'number'
)
) {
return context.error(("Type " + (toString(outputType)) + " is not interpolatable."));
}
return new Interpolate(outputType, (operator ), interpolation, input, stops);
};
Interpolate.prototype.evaluate = function evaluate (ctx ) {
var labels = this.labels;
var outputs = this.outputs;
if (labels.length === 1) {
return outputs[0].evaluate(ctx);
}
var value = ((this.input.evaluate(ctx) ) );
if (value <= labels[0]) {
return outputs[0].evaluate(ctx);
}
var stopCount = labels.length;
if (value >= labels[stopCount - 1]) {
return outputs[stopCount - 1].evaluate(ctx);
}
var index = findStopLessThanOrEqualTo(labels, value);
var lower = labels[index];
var upper = labels[index + 1];
var t = Interpolate.interpolationFactor(this.interpolation, value, lower, upper);
var outputLower = outputs[index].evaluate(ctx);
var outputUpper = outputs[index + 1].evaluate(ctx);
if (this.operator === 'interpolate') {
return (interpolate[this.type.kind.toLowerCase()] )(outputLower, outputUpper, t); // eslint-disable-line import/namespace
} else if (this.operator === 'interpolate-hcl') {
return hcl.reverse(hcl.interpolate(hcl.forward(outputLower), hcl.forward(outputUpper), t));
} else {
return lab.reverse(lab.interpolate(lab.forward(outputLower), lab.forward(outputUpper), t));
}
};
Interpolate.prototype.eachChild = function eachChild (fn ) {
var this$1 = this;
fn(this.input);
for (var i = 0, list = this$1.outputs; i < list.length; i += 1) {
var expression = list[i];
fn(expression);
}
};
Interpolate.prototype.possibleOutputs = function possibleOutputs () {
return (ref = []).concat.apply(ref, this.outputs.map(function (output) { return output.possibleOutputs(); }));
var ref;
};
Interpolate.prototype.serialize = function serialize () {
var this$1 = this;
var interpolation;
if (this.interpolation.name === 'linear') {
interpolation = ["linear"];
} else if (this.interpolation.name === 'exponential') {
if (this.interpolation.base === 1) {
interpolation = ["linear"];
} else {
interpolation = ["exponential", this.interpolation.base];
}
} else {
interpolation = ["cubic-bezier" ].concat(this.interpolation.controlPoints);
}
var serialized = [this.operator, interpolation, this.input.serialize()];
for (var i = 0; i < this.labels.length; i++) {
serialized.push(
this$1.labels[i],
this$1.outputs[i].serialize()
);
}
return serialized;
};
/**
* Returns a ratio that can be used to interpolate between exponential function
* stops.
* How it works: Two consecutive stop values define a (scaled and shifted) exponential function `f(x) = a * base^x + b`, where `base` is the user-specified base,
* and `a` and `b` are constants affording sufficient degrees of freedom to fit
* the function to the given stops.
*
* Here's a bit of algebra that lets us compute `f(x)` directly from the stop
* values without explicitly solving for `a` and `b`:
*
* First stop value: `f(x0) = y0 = a * base^x0 + b`
* Second stop value: `f(x1) = y1 = a * base^x1 + b`
* => `y1 - y0 = a(base^x1 - base^x0)`
* => `a = (y1 - y0)/(base^x1 - base^x0)`
*
* Desired value: `f(x) = y = a * base^x + b`
* => `f(x) = y0 + a * (base^x - base^x0)`
*
* From the above, we can replace the `a` in `a * (base^x - base^x0)` and do a
* little algebra:
* ```
* a * (base^x - base^x0) = (y1 - y0)/(base^x1 - base^x0) * (base^x - base^x0)
* = (y1 - y0) * (base^x - base^x0) / (base^x1 - base^x0)
* ```
*
* If we let `(base^x - base^x0) / (base^x1 base^x0)`, then we have
* `f(x) = y0 + (y1 - y0) * ratio`. In other words, `ratio` may be treated as
* an interpolation factor between the two stops' output values.
*
* (Note: a slightly different form for `ratio`,
* `(base^(x-x0) - 1) / (base^(x1-x0) - 1) `, is equivalent, but requires fewer
* expensive `Math.pow()` operations.)
*
* @private
*/
function exponentialInterpolation(input, base, lowerValue, upperValue) {
var difference = upperValue - lowerValue;
var progress = input - lowerValue;
if (difference === 0) {
return 0;
} else if (base === 1) {
return progress / difference;
} else {
return (Math.pow(base, progress) - 1) / (Math.pow(base, difference) - 1);
}
}
//
var Coalesce = function Coalesce(type , args ) {
this.type = type;
this.args = args;
};
Coalesce.parse = function parse (args , context ) {
if (args.length < 2) {
return context.error("Expectected at least one argument.");
}
var outputType = (null );
var expectedType = context.expectedType;
if (expectedType && expectedType.kind !== 'value') {
outputType = expectedType;
}
var parsedArgs = [];
for (var i = 0, list = args.slice(1); i < list.length; i += 1) {
var arg = list[i];
var parsed = context.parse(arg, 1 + parsedArgs.length, outputType, undefined, {omitTypeAnnotations: true});
if (!parsed) { return null; }
outputType = outputType || parsed.type;
parsedArgs.push(parsed);
}
assert_1(outputType);
// Above, we parse arguments without inferred type annotation so that
// they don't produce a runtime error for `null` input, which would
// preempt the desired null-coalescing behavior.
// Thus, if any of our arguments would have needed an annotation, we
// need to wrap the enclosing coalesce expression with it instead.
var needsAnnotation = expectedType &&
parsedArgs.some(function (arg) { return checkSubtype(expectedType, arg.type); });
return needsAnnotation ?
new Coalesce(ValueType, parsedArgs) :
new Coalesce((outputType ), parsedArgs);
};
Coalesce.prototype.evaluate = function evaluate (ctx ) {
var this$1 = this;
var result = null;
for (var i = 0, list = this$1.args; i < list.length; i += 1) {
var arg = list[i];
result = arg.evaluate(ctx);
if (result !== null) { break; }
}
return result;
};
Coalesce.prototype.eachChild = function eachChild (fn ) {
this.args.forEach(fn);
};
Coalesce.prototype.possibleOutputs = function possibleOutputs () {
return (ref = []).concat.apply(ref, this.args.map(function (arg) { return arg.possibleOutputs(); }));
var ref;
};
Coalesce.prototype.serialize = function serialize () {
var serialized = ["coalesce"];
this.eachChild(function (child) { serialized.push(child.serialize()); });
return serialized;
};
//
var Let = function Let(bindings , result ) {
this.type = result.type;
this.bindings = [].concat(bindings);
this.result = result;
};
Let.prototype.evaluate = function evaluate (ctx ) {
return this.result.evaluate(ctx);
};
Let.prototype.eachChild = function eachChild (fn ) {
var this$1 = this;
for (var i = 0, list = this$1.bindings; i < list.length; i += 1) {
var binding = list[i];
fn(binding[1]);
}
fn(this.result);
};
Let.parse = function parse (args , context ) {
if (args.length < 4)
{ return context.error(("Expected at least 3 arguments, but found " + (args.length - 1) + " instead.")); }
var bindings = [];
for (var i = 1; i < args.length - 1; i += 2) {
var name = args[i];
if (typeof name !== 'string') {
return context.error(("Expected string, but found " + (typeof name) + " instead."), i);
}
if (/[^a-zA-Z0-9_]/.test(name)) {
return context.error("Variable names must contain only alphanumeric characters or '_'.", i);
}
var value = context.parse(args[i + 1], i + 1);
if (!value) { return null; }
bindings.push([name, value]);
}
var result = context.parse(args[args.length - 1], args.length - 1, undefined, bindings);
if (!result) { return null; }
return new Let(bindings, result);
};
Let.prototype.possibleOutputs = function possibleOutputs () {
return this.result.possibleOutputs();
};
Let.prototype.serialize = function serialize () {
var this$1 = this;
var serialized = ["let"];
for (var i = 0, list = this$1.bindings; i < list.length; i += 1) {
var ref = list[i];
var name = ref[0];
var expr = ref[1];
serialized.push(name, expr.serialize());
}
serialized.push(this.result.serialize());
return serialized;
};
//
var At = function At(type , index , input ) {
this.type = type;
this.index = index;
this.input = input;
};
At.parse = function parse (args , context ) {
if (args.length !== 3)
{ return context.error(("Expected 2 arguments, but found " + (args.length - 1) + " instead.")); }
var index = context.parse(args[1], 1, NumberType);
var input = context.parse(args[2], 2, array(context.expectedType || ValueType));
if (!index || !input) { return null; }
var t = (input.type );
return new At(t.itemType, index, input);
};
At.prototype.evaluate = function evaluate (ctx ) {
var index = ((this.index.evaluate(ctx) ) );
var array$$1 = ((this.input.evaluate(ctx) ) );
if (index < 0) {
throw new RuntimeError(("Array index out of bounds: " + index + " < 0."));
}
if (index >= array$$1.length) {
throw new RuntimeError(("Array index out of bounds: " + index + " > " + (array$$1.length - 1) + "."));
}
if (index !== Math.floor(index)) {
throw new RuntimeError(("Array index must be an integer, but found " + index + " instead."));
}
return array$$1[index];
};
At.prototype.eachChild = function eachChild (fn ) {
fn(this.index);
fn(this.input);
};
At.prototype.possibleOutputs = function possibleOutputs () {
return [undefined];
};
At.prototype.serialize = function serialize () {
return ["at", this.index.serialize(), this.input.serialize()];
};
//
// Map input label values to output expression index
var Match = function Match(inputType , outputType , input , cases , outputs , otherwise ) {
this.inputType = inputType;
this.type = outputType;
this.input = input;
this.cases = cases;
this.outputs = outputs;
this.otherwise = otherwise;
};
Match.parse = function parse (args , context ) {
if (args.length < 5)
{ return context.error(("Expected at least 4 arguments, but found only " + (args.length - 1) + ".")); }
if (args.length % 2 !== 1)
{ return context.error("Expected an even number of arguments."); }
var inputType;
var outputType;
if (context.expectedType && context.expectedType.kind !== 'value') {
outputType = context.expectedType;
}
var cases = {};
var outputs = [];
for (var i = 2; i < args.length - 1; i += 2) {
var labels = args[i];
var value = args[i + 1];
if (!Array.isArray(labels)) {
labels = [labels];
}
var labelContext = context.concat(i);
if (labels.length === 0) {
return labelContext.error('Expected at least one branch label.');
}
for (var i$1 = 0, list = labels; i$1 < list.length; i$1 += 1) {
var label = list[i$1];
if (typeof label !== 'number' && typeof label !== 'string') {
return labelContext.error("Branch labels must be numbers or strings.");
} else if (typeof label === 'number' && Math.abs(label) > Number.MAX_SAFE_INTEGER) {
return labelContext.error(("Branch labels must be integers no larger than " + (Number.MAX_SAFE_INTEGER) + "."));
} else if (typeof label === 'number' && Math.floor(label) !== label) {
return labelContext.error("Numeric branch labels must be integer values.");
} else if (!inputType) {
inputType = typeOf(label);
} else if (labelContext.checkSubtype(inputType, typeOf(label))) {
return null;
}
if (typeof cases[String(label)] !== 'undefined') {
return labelContext.error('Branch labels must be unique.');
}
cases[String(label)] = outputs.length;
}
var result = context.parse(value, i, outputType);
if (!result) { return null; }
outputType = outputType || result.type;
outputs.push(result);
}
var input = context.parse(args[1], 1, ValueType);
if (!input) { return null; }
var otherwise = context.parse(args[args.length - 1], args.length - 1, outputType);
if (!otherwise) { return null; }
assert_1(inputType && outputType);
if (input.type.kind !== 'value' && context.concat(1).checkSubtype((inputType ), input.type)) {
return null;
}
return new Match((inputType ), (outputType ), input, cases, outputs, otherwise);
};
Match.prototype.evaluate = function evaluate (ctx ) {
var input = (this.input.evaluate(ctx) );
var output = (typeOf(input) === this.inputType && this.outputs[this.cases[input]]) || this.otherwise;
return output.evaluate(ctx);
};
Match.prototype.eachChild = function eachChild (fn ) {
fn(this.input);
this.outputs.forEach(fn);
fn(this.otherwise);
};
Match.prototype.possibleOutputs = function possibleOutputs () {
return (ref = [])
.concat.apply(ref, this.outputs.map(function (out) { return out.possibleOutputs(); }))
.concat(this.otherwise.possibleOutputs());
var ref;
};
Match.prototype.serialize = function serialize () {
var this$1 = this;
var serialized = ["match", this.input.serialize()];
// Sort so serialization has an arbitrary defined order, even though
// branch order doesn't affect evaluation
var sortedLabels = Object.keys(this.cases).sort();
// Group branches by unique match expression to support condensed
// serializations of the form [case1, case2, ...] -> matchExpression
var groupedByOutput = [];
var outputLookup = {}; // lookup index into groupedByOutput for a given output expression
for (var i = 0, list = sortedLabels; i < list.length; i += 1) {
var label = list[i];
var outputIndex = outputLookup[this$1.cases[label]];
if (outputIndex === undefined) {
// First time seeing this output, add it to the end of the grouped list
outputLookup[this$1.cases[label]] = groupedByOutput.length;
groupedByOutput.push([this$1.cases[label], [label]]);
} else {
// We've seen this expression before, add the label to that output's group
groupedByOutput[outputIndex][1].push(label);
}
}
var coerceLabel = function (label) { return this$1.inputType.kind === 'number' ? Number(label) : label; };
for (var i$1 = 0, list$1 = groupedByOutput; i$1 < list$1.length; i$1 += 1) {
var ref = list$1[i$1];
var outputIndex$1 = ref[0];
var labels = ref[1];
if (labels.length === 1) {
// Only a single label matches this output expression
serialized.push(coerceLabel(labels[0]));
} else {
// Array of literal labels pointing to this output expression
serialized.push(labels.map(coerceLabel));
}
serialized.push(this$1.outputs[outputIndex$1].serialize());
}
serialized.push(this.otherwise.serialize());
return serialized;
};
//
var Case = function Case(type , branches , otherwise ) {
this.type = type;
this.branches = branches;
this.otherwise = otherwise;
};
Case.parse = function parse (args , context ) {
if (args.length < 4)
{ return context.error(("Expected at least 3 arguments, but found only " + (args.length - 1) + ".")); }
if (args.length % 2 !== 0)
{ return context.error("Expected an odd number of arguments."); }
var outputType ;
if (context.expectedType && context.expectedType.kind !== 'value') {
outputType = context.expectedType;
}
var branches = [];
for (var i = 1; i < args.length - 1; i += 2) {
var test = context.parse(args[i], i, BooleanType);
if (!test) { return null; }
var result = context.parse(args[i + 1], i + 1, outputType);
if (!result) { return null; }
branches.push([test, result]);
outputType = outputType || result.type;
}
var otherwise = context.parse(args[args.length - 1], args.length - 1, outputType);
if (!otherwise) { return null; }
assert_1(outputType);
return new Case((outputType ), branches, otherwise);
};
Case.prototype.evaluate = function evaluate (ctx ) {
var this$1 = this;
for (var i = 0, list = this$1.branches; i < list.length; i += 1) {
var ref = list[i];
var test = ref[0];
var expression = ref[1];
if (test.evaluate(ctx)) {
return expression.evaluate(ctx);
}
}
return this.otherwise.evaluate(ctx);
};
Case.prototype.eachChild = function eachChild (fn ) {
var this$1 = this;
for (var i = 0, list = this$1.branches; i < list.length; i += 1) {
var ref = list[i];
var test = ref[0];
var expression = ref[1];
fn(test);
fn(expression);
}
fn(this.otherwise);
};
Case.prototype.possibleOutputs = function possibleOutputs () {
return (ref = [])
.concat.apply(ref, this.branches.map(function (ref) {
var _ = ref[0];
var out = ref[1];
return out.possibleOutputs();
}))
.concat(this.otherwise.possibleOutputs());
var ref;
};
Case.prototype.serialize = function serialize () {
var serialized = ["case"];
this.eachChild(function (child) { serialized.push(child.serialize()); });
return serialized;
};
//
function isComparableType(op , type ) {
if (op === '==' || op === '!=') {
// equality operator
return type.kind === 'boolean' ||
type.kind === 'string' ||
type.kind === 'number' ||
type.kind === 'null' ||
type.kind === 'value';
} else {
// ordering operator
return type.kind === 'string' ||
type.kind === 'number' ||
type.kind === 'value';
}
}
function eq(ctx, a, b) { return a === b; }
function neq(ctx, a, b) { return a !== b; }
function lt(ctx, a, b) { return a < b; }
function gt(ctx, a, b) { return a > b; }
function lteq(ctx, a, b) { return a <= b; }
function gteq(ctx, a, b) { return a >= b; }
function eqCollate(ctx, a, b, c) { return c.compare(a, b) === 0; }
function neqCollate(ctx, a, b, c) { return !eqCollate(ctx, a, b, c); }
function ltCollate(ctx, a, b, c) { return c.compare(a, b) < 0; }
function gtCollate(ctx, a, b, c) { return c.compare(a, b) > 0; }
function lteqCollate(ctx, a, b, c) { return c.compare(a, b) <= 0; }
function gteqCollate(ctx, a, b, c) { return c.compare(a, b) >= 0; }
/**
* Special form for comparison operators, implementing the signatures:
* - (T, T, ?Collator) => boolean
* - (T, value, ?Collator) => boolean
* - (value, T, ?Collator) => boolean
*
* For inequalities, T must be either value, string, or number. For ==/!=, it
* can also be boolean or null.
*
* Equality semantics are equivalent to Javascript's strict equality (===/!==)
* -- i.e., when the arguments' types don't match, == evaluates to false, != to
* true.
*
* When types don't match in an ordering comparison, a runtime error is thrown.
*
* @private
*/
function makeComparison(op , compareBasic, compareWithCollator) {
var isOrderComparison = op !== '==' && op !== '!=';
return (function () {
function Comparison(lhs , rhs , collator ) {
this.type = BooleanType;
this.lhs = lhs;
this.rhs = rhs;
this.collator = collator;
this.hasUntypedArgument = lhs.type.kind === 'value' || rhs.type.kind === 'value';
}
Comparison.parse = function parse (args , context ) {
if (args.length !== 3 && args.length !== 4)
{ return context.error("Expected two or three arguments."); }
var op = (args[0] );
var lhs = context.parse(args[1], 1, ValueType);
if (!lhs) { return null; }
if (!isComparableType(op, lhs.type)) {
return context.concat(1).error(("\"" + op + "\" comparisons are not supported for type '" + (toString(lhs.type)) + "'."));
}
var rhs = context.parse(args[2], 2, ValueType);
if (!rhs) { return null; }
if (!isComparableType(op, rhs.type)) {
return context.concat(2).error(("\"" + op + "\" comparisons are not supported for type '" + (toString(rhs.type)) + "'."));
}
if (
lhs.type.kind !== rhs.type.kind &&
lhs.type.kind !== 'value' &&
rhs.type.kind !== 'value'
) {
return context.error(("Cannot compare types '" + (toString(lhs.type)) + "' and '" + (toString(rhs.type)) + "'."));
}
if (isOrderComparison) {
// typing rules specific to less/greater than operators
if (lhs.type.kind === 'value' && rhs.type.kind !== 'value') {
// (value, T)
lhs = new Assertion(rhs.type, [lhs]);
} else if (lhs.type.kind !== 'value' && rhs.type.kind === 'value') {
// (T, value)
rhs = new Assertion(lhs.type, [rhs]);
}
}
var collator = null;
if (args.length === 4) {
if (
lhs.type.kind !== 'string' &&
rhs.type.kind !== 'string' &&
lhs.type.kind !== 'value' &&
rhs.type.kind !== 'value'
) {
return context.error("Cannot use collator to compare non-string types.");
}
collator = context.parse(args[3], 3, CollatorType);
if (!collator) { return null; }
}
return new Comparison(lhs, rhs, collator);
};
Comparison.prototype.evaluate = function evaluate (ctx ) {
var lhs = this.lhs.evaluate(ctx);
var rhs = this.rhs.evaluate(ctx);
if (isOrderComparison && this.hasUntypedArgument) {
var lt = typeOf(lhs);
var rt = typeOf(rhs);
// check that type is string or number, and equal
if (lt.kind !== rt.kind || !(lt.kind === 'string' || lt.kind === 'number')) {
throw new RuntimeError(("Expected arguments for \"" + op + "\" to be (string, string) or (number, number), but found (" + (lt.kind) + ", " + (rt.kind) + ") instead."));
}
}
if (this.collator && !isOrderComparison && this.hasUntypedArgument) {
var lt$1 = typeOf(lhs);
var rt$1 = typeOf(rhs);
if (lt$1.kind !== 'string' || rt$1.kind !== 'string') {
return compareBasic(ctx, lhs, rhs);
}
}
return this.collator ?
compareWithCollator(ctx, lhs, rhs, this.collator.evaluate(ctx)) :
compareBasic(ctx, lhs, rhs);
};
Comparison.prototype.eachChild = function eachChild (fn ) {
fn(this.lhs);
fn(this.rhs);
if (this.collator) {
fn(this.collator);
}
};
Comparison.prototype.possibleOutputs = function possibleOutputs () {
return [true, false];
};
Comparison.prototype.serialize = function serialize () {
var serialized = [op];
this.eachChild(function (child) { serialized.push(child.serialize()); });
return serialized;
};
return Comparison;
}());
}
var Equals = makeComparison('==', eq, eqCollate);
var NotEquals = makeComparison('!=', neq, neqCollate);
var LessThan = makeComparison('<', lt, ltCollate);
var GreaterThan = makeComparison('>', gt, gtCollate);
var LessThanOrEqual = makeComparison('<=', lteq, lteqCollate);
var GreaterThanOrEqual = makeComparison('>=', gteq, gteqCollate);
//
var Length = function Length(input ) {
this.type = NumberType;
this.input = input;
};
Length.parse = function parse (args , context ) {
if (args.length !== 2)
{ return context.error(("Expected 1 argument, but found " + (args.length - 1) + " instead.")); }
var input = context.parse(args[1], 1);
if (!input) { return null; }
if (input.type.kind !== 'array' && input.type.kind !== 'string' && input.type.kind !== 'value')
{ return context.error(("Expected argument of type string or array, but found " + (toString(input.type)) + " instead.")); }
return new Length(input);
};
Length.prototype.evaluate = function evaluate (ctx ) {
var input = this.input.evaluate(ctx);
if (typeof input === 'string') {
return input.length;
} else if (Array.isArray(input)) {
return input.length;
} else {
throw new RuntimeError(("Expected value to be of type string or array, but found " + (toString(typeOf(input))) + " instead."));
}
};
Length.prototype.eachChild = function eachChild (fn ) {
fn(this.input);
};
Length.prototype.possibleOutputs = function possibleOutputs () {
return [undefined];
};
Length.prototype.serialize = function serialize () {
var serialized = ["length"];
this.eachChild(function (child) { serialized.push(child.serialize()); });
return serialized;
};
//
var expressions = {
// special forms
'==': Equals,
'!=': NotEquals,
'>': GreaterThan,
'<': LessThan,
'>=': GreaterThanOrEqual,
'<=': LessThanOrEqual,
'array': ArrayAssertion,
'at': At,
'boolean': Assertion,
'case': Case,
'coalesce': Coalesce,
'collator': CollatorExpression,
'format': FormatExpression,
'interpolate': Interpolate,
'interpolate-hcl': Interpolate,
'interpolate-lab': Interpolate,
'length': Length,
'let': Let,
'literal': Literal,
'match': Match,
'number': Assertion,
'object': Assertion,
'step': Step,
'string': Assertion,
'to-color': Coercion,
'to-number': Coercion,
'var': Var
};
function rgba(ctx, ref) {
var r = ref[0];
var g = ref[1];
var b = ref[2];
var a = ref[3];
r = r.evaluate(ctx);
g = g.evaluate(ctx);
b = b.evaluate(ctx);
var alpha = a ? a.evaluate(ctx) : 1;
var error = validateRGBA(r, g, b, alpha);
if (error) { throw new RuntimeError(error); }
return new Color(r / 255 * alpha, g / 255 * alpha, b / 255 * alpha, alpha);
}
function has(key, obj) {
return key in obj;
}
function get(key, obj) {
var v = obj[key];
return typeof v === 'undefined' ? null : v;
}
function binarySearch(v, a, i, j) {
while (i <= j) {
var m = (i + j) >> 1;
if (a[m] === v)
{ return true; }
if (a[m] > v)
{ j = m - 1; }
else
{ i = m + 1; }
}
return false;
}
function varargs(type ) {
return { type: type };
}
CompoundExpression.register(expressions, {
'error': [
ErrorType,
[StringType],
function (ctx, ref) {
var v = ref[0];
throw new RuntimeError(v.evaluate(ctx)); }
],
'typeof': [
StringType,
[ValueType],
function (ctx, ref) {
var v = ref[0];
return toString(typeOf(v.evaluate(ctx)));
}
],
'to-string': [
StringType,
[ValueType],
function (ctx, ref) {
var v = ref[0];
v = v.evaluate(ctx);
var type = typeof v;
if (v === null) {
return '';
} else if (type === 'string' || type === 'number' || type === 'boolean') {
return String(v);
} else if (v instanceof Color || v instanceof Formatted) {
return v.toString();
} else {
return JSON.stringify(v);
}
}
],
'to-boolean': [
BooleanType,
[ValueType],
function (ctx, ref) {
var v = ref[0];
return Boolean(v.evaluate(ctx));
}
],
'to-rgba': [
array(NumberType, 4),
[ColorType],
function (ctx, ref) {
var v = ref[0];
return v.evaluate(ctx).toArray();
}
],
'rgb': [
ColorType,
[NumberType, NumberType, NumberType],
rgba
],
'rgba': [
ColorType,
[NumberType, NumberType, NumberType, NumberType],
rgba
],
'has': {
type: BooleanType,
overloads: [
[
[StringType],
function (ctx, ref) {
var key = ref[0];
return has(key.evaluate(ctx), ctx.properties());
}
], [
[StringType, ObjectType],
function (ctx, ref) {
var key = ref[0];
var obj = ref[1];
return has(key.evaluate(ctx), obj.evaluate(ctx));
}
]
]
},
'get': {
type: ValueType,
overloads: [
[
[StringType],
function (ctx, ref) {
var key = ref[0];
return get(key.evaluate(ctx), ctx.properties());
}
], [
[StringType, ObjectType],
function (ctx, ref) {
var key = ref[0];
var obj = ref[1];
return get(key.evaluate(ctx), obj.evaluate(ctx));
}
]
]
},
'feature-state': [
ValueType,
[StringType],
function (ctx, ref) {
var key = ref[0];
return get(key.evaluate(ctx), ctx.featureState || {});
}
],
'properties': [
ObjectType,
[],
function (ctx) { return ctx.properties(); }
],
'geometry-type': [
StringType,
[],
function (ctx) { return ctx.geometryType(); }
],
'id': [
ValueType,
[],
function (ctx) { return ctx.id(); }
],
'zoom': [
NumberType,
[],
function (ctx) { return ctx.globals.zoom; }
],
'heatmap-density': [
NumberType,
[],
function (ctx) { return ctx.globals.heatmapDensity || 0; }
],
'line-progress': [
NumberType,
[],
function (ctx) { return ctx.globals.lineProgress || 0; }
],
'+': [
NumberType,
varargs(NumberType),
function (ctx, args) {
var result = 0;
for (var i = 0, list = args; i < list.length; i += 1) {
var arg = list[i];
result += arg.evaluate(ctx);
}
return result;
}
],
'*': [
NumberType,
varargs(NumberType),
function (ctx, args) {
var result = 1;
for (var i = 0, list = args; i < list.length; i += 1) {
var arg = list[i];
result *= arg.evaluate(ctx);
}
return result;
}
],
'-': {
type: NumberType,
overloads: [
[
[NumberType, NumberType],
function (ctx, ref) {
var a = ref[0];
var b = ref[1];
return a.evaluate(ctx) - b.evaluate(ctx);
}
], [
[NumberType],
function (ctx, ref) {
var a = ref[0];
return -a.evaluate(ctx);
}
]
]
},
'/': [
NumberType,
[NumberType, NumberType],
function (ctx, ref) {
var a = ref[0];
var b = ref[1];
return a.evaluate(ctx) / b.evaluate(ctx);
}
],
'%': [
NumberType,
[NumberType, NumberType],
function (ctx, ref) {
var a = ref[0];
var b = ref[1];
return a.evaluate(ctx) % b.evaluate(ctx);
}
],
'ln2': [
NumberType,
[],
function () { return Math.LN2; }
],
'pi': [
NumberType,
[],
function () { return Math.PI; }
],
'e': [
NumberType,
[],
function () { return Math.E; }
],
'^': [
NumberType,
[NumberType, NumberType],
function (ctx, ref) {
var b = ref[0];
var e = ref[1];
return Math.pow(b.evaluate(ctx), e.evaluate(ctx));
}
],
'sqrt': [
NumberType,
[NumberType],
function (ctx, ref) {
var x = ref[0];
return Math.sqrt(x.evaluate(ctx));
}
],
'log10': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.log10(n.evaluate(ctx));
}
],
'ln': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.log(n.evaluate(ctx));
}
],
'log2': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.log2(n.evaluate(ctx));
}
],
'sin': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.sin(n.evaluate(ctx));
}
],
'cos': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.cos(n.evaluate(ctx));
}
],
'tan': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.tan(n.evaluate(ctx));
}
],
'asin': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.asin(n.evaluate(ctx));
}
],
'acos': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.acos(n.evaluate(ctx));
}
],
'atan': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.atan(n.evaluate(ctx));
}
],
'min': [
NumberType,
varargs(NumberType),
function (ctx, args) { return Math.min.apply(Math, args.map(function (arg) { return arg.evaluate(ctx); })); }
],
'max': [
NumberType,
varargs(NumberType),
function (ctx, args) { return Math.max.apply(Math, args.map(function (arg) { return arg.evaluate(ctx); })); }
],
'abs': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.abs(n.evaluate(ctx));
}
],
'round': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
var v = n.evaluate(ctx);
// Javascript's Math.round() rounds towards +Infinity for halfway
// values, even when they're negative. It's more common to round
// away from 0 (e.g., this is what python and C++ do)
return v < 0 ? -Math.round(-v) : Math.round(v);
}
],
'floor': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.floor(n.evaluate(ctx));
}
],
'ceil': [
NumberType,
[NumberType],
function (ctx, ref) {
var n = ref[0];
return Math.ceil(n.evaluate(ctx));
}
],
'filter-==': [
BooleanType,
[StringType, ValueType],
function (ctx, ref) {
var k = ref[0];
var v = ref[1];
return ctx.properties()[(k ).value] === (v ).value;
}
],
'filter-id-==': [
BooleanType,
[ValueType],
function (ctx, ref) {
var v = ref[0];
return ctx.id() === (v ).value;
}
],
'filter-type-==': [
BooleanType,
[StringType],
function (ctx, ref) {
var v = ref[0];
return ctx.geometryType() === (v ).value;
}
],
'filter-<': [
BooleanType,
[StringType, ValueType],
function (ctx, ref) {
var k = ref[0];
var v = ref[1];
var a = ctx.properties()[(k ).value];
var b = (v ).value;
return typeof a === typeof b && a < b;
}
],
'filter-id-<': [
BooleanType,
[ValueType],
function (ctx, ref) {
var v = ref[0];
var a = ctx.id();
var b = (v ).value;
return typeof a === typeof b && a < b;
}
],
'filter->': [
BooleanType,
[StringType, ValueType],
function (ctx, ref) {
var k = ref[0];
var v = ref[1];
var a = ctx.properties()[(k ).value];
var b = (v ).value;
return typeof a === typeof b && a > b;
}
],
'filter-id->': [
BooleanType,
[ValueType],
function (ctx, ref) {
var v = ref[0];
var a = ctx.id();
var b = (v ).value;
return typeof a === typeof b && a > b;
}
],
'filter-<=': [
BooleanType,
[StringType, ValueType],
function (ctx, ref) {
var k = ref[0];
var v = ref[1];
var a = ctx.properties()[(k ).value];
var b = (v ).value;
return typeof a === typeof b && a <= b;
}
],
'filter-id-<=': [
BooleanType,
[ValueType],
function (ctx, ref) {
var v = ref[0];
var a = ctx.id();
var b = (v ).value;
return typeof a === typeof b && a <= b;
}
],
'filter->=': [
BooleanType,
[StringType, ValueType],
function (ctx, ref) {
var k = ref[0];
var v = ref[1];
var a = ctx.properties()[(k ).value];
var b = (v ).value;
return typeof a === typeof b && a >= b;
}
],
'filter-id->=': [
BooleanType,
[ValueType],
function (ctx, ref) {
var v = ref[0];
var a = ctx.id();
var b = (v ).value;
return typeof a === typeof b && a >= b;
}
],
'filter-has': [
BooleanType,
[ValueType],
function (ctx, ref) {
var k = ref[0];
return (k ).value in ctx.properties();
}
],
'filter-has-id': [
BooleanType,
[],
function (ctx) { return ctx.id() !== null; }
],
'filter-type-in': [
BooleanType,
[array(StringType)],
function (ctx, ref) {
var v = ref[0];
return (v ).value.indexOf(ctx.geometryType()) >= 0;
}
],
'filter-id-in': [
BooleanType,
[array(ValueType)],
function (ctx, ref) {
var v = ref[0];
return (v ).value.indexOf(ctx.id()) >= 0;
}
],
'filter-in-small': [
BooleanType,
[StringType, array(ValueType)],
// assumes v is an array literal
function (ctx, ref) {
var k = ref[0];
var v = ref[1];
return (v ).value.indexOf(ctx.properties()[(k ).value]) >= 0;
}
],
'filter-in-large': [
BooleanType,
[StringType, array(ValueType)],
// assumes v is a array literal with values sorted in ascending order and of a single type
function (ctx, ref) {
var k = ref[0];
var v = ref[1];
return binarySearch(ctx.properties()[(k ).value], (v ).value, 0, (v ).value.length - 1);
}
],
'all': {
type: BooleanType,
overloads: [
[
[BooleanType, BooleanType],
function (ctx, ref) {
var a = ref[0];
var b = ref[1];
return a.evaluate(ctx) && b.evaluate(ctx);
}
],
[
varargs(BooleanType),
function (ctx, args) {
for (var i = 0, list = args; i < list.length; i += 1) {
var arg = list[i];
if (!arg.evaluate(ctx))
{ return false; }
}
return true;
}
]
]
},
'any': {
type: BooleanType,
overloads: [
[
[BooleanType, BooleanType],
function (ctx, ref) {
var a = ref[0];
var b = ref[1];
return a.evaluate(ctx) || b.evaluate(ctx);
}
],
[
varargs(BooleanType),
function (ctx, args) {
for (var i = 0, list = args; i < list.length; i += 1) {
var arg = list[i];
if (arg.evaluate(ctx))
{ return true; }
}
return false;
}
]
]
},
'!': [
BooleanType,
[BooleanType],
function (ctx, ref) {
var b = ref[0];
return !b.evaluate(ctx);
}
],
'is-supported-script': [
BooleanType,
[StringType],
// At parse time this will always return true, so we need to exclude this expression with isGlobalPropertyConstant
function (ctx, ref) {
var s = ref[0];
var isSupportedScript = ctx.globals && ctx.globals.isSupportedScript;
if (isSupportedScript) {
return isSupportedScript(s.evaluate(ctx));
}
return true;
}
],
'upcase': [
StringType,
[StringType],
function (ctx, ref) {
var s = ref[0];
return s.evaluate(ctx).toUpperCase();
}
],
'downcase': [
StringType,
[StringType],
function (ctx, ref) {
var s = ref[0];
return s.evaluate(ctx).toLowerCase();
}
],
'concat': [
StringType,
varargs(StringType),
function (ctx, args) { return args.map(function (arg) { return arg.evaluate(ctx); }).join(''); }
],
'resolved-locale': [
StringType,
[CollatorType],
function (ctx, ref) {
var collator = ref[0];
return collator.evaluate(ctx).resolvedLocale();
}
]
});
//
/**
* A type used for returning and propagating errors. The first element of the union
* represents success and contains a value, and the second represents an error and
* contains an error value.
* @private
*/
function success (value ) {
return { result: 'success', value: value };
}
function error (value ) {
return { result: 'error', value: value };
}
//
function supportsPropertyExpression(spec ) {
return spec['property-type'] === 'data-driven' || spec['property-type'] === 'cross-faded-data-driven';
}
function supportsZoomExpression(spec ) {
return !!spec.expression && spec.expression.parameters.indexOf('zoom') > -1;
}
function supportsInterpolation(spec ) {
return !!spec.expression && spec.expression.interpolated;
}
function getType(val) {
if (val instanceof Number) {
return 'number';
} else if (val instanceof String) {
return 'string';
} else if (val instanceof Boolean) {
return 'boolean';
} else if (Array.isArray(val)) {
return 'array';
} else if (val === null) {
return 'null';
} else {
return typeof val;
}
}
function isFunction(value) {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function identityFunction(x) {
return x;
}
function createFunction(parameters, propertySpec) {
var isColor = propertySpec.type === 'color';
var zoomAndFeatureDependent = parameters.stops && typeof parameters.stops[0][0] === 'object';
var featureDependent = zoomAndFeatureDependent || parameters.property !== undefined;
var zoomDependent = zoomAndFeatureDependent || !featureDependent;
var type = parameters.type || (supportsInterpolation(propertySpec) ? 'exponential' : 'interval');
if (isColor) {
parameters = extend$1({}, parameters);
if (parameters.stops) {
parameters.stops = parameters.stops.map(function (stop) {
return [stop[0], Color.parse(stop[1])];
});
}
if (parameters.default) {
parameters.default = Color.parse(parameters.default);
} else {
parameters.default = Color.parse(propertySpec.default);
}
}
if (parameters.colorSpace && parameters.colorSpace !== 'rgb' && !colorSpaces[parameters.colorSpace]) { // eslint-disable-line import/namespace
throw new Error(("Unknown color space: " + (parameters.colorSpace)));
}
var innerFun;
var hashedStops;
var categoricalKeyType;
if (type === 'exponential') {
innerFun = evaluateExponentialFunction;
} else if (type === 'interval') {
innerFun = evaluateIntervalFunction;
} else if (type === 'categorical') {
innerFun = evaluateCategoricalFunction;
// For categorical functions, generate an Object as a hashmap of the stops for fast searching
hashedStops = Object.create(null);
for (var i = 0, list = parameters.stops; i < list.length; i += 1) {
var stop = list[i];
hashedStops[stop[0]] = stop[1];
}
// Infer key type based on first stop key-- used to encforce strict type checking later
categoricalKeyType = typeof parameters.stops[0][0];
} else if (type === 'identity') {
innerFun = evaluateIdentityFunction;
} else {
throw new Error(("Unknown function type \"" + type + "\""));
}
if (zoomAndFeatureDependent) {
var featureFunctions = {};
var zoomStops = [];
for (var s = 0; s < parameters.stops.length; s++) {
var stop$1 = parameters.stops[s];
var zoom = stop$1[0].zoom;
if (featureFunctions[zoom] === undefined) {
featureFunctions[zoom] = {
zoom: zoom,
type: parameters.type,
property: parameters.property,
default: parameters.default,
stops: []
};
zoomStops.push(zoom);
}
featureFunctions[zoom].stops.push([stop$1[0].value, stop$1[1]]);
}
var featureFunctionStops = [];
for (var i$1 = 0, list$1 = zoomStops; i$1 < list$1.length; i$1 += 1) {
var z = list$1[i$1];
featureFunctionStops.push([featureFunctions[z].zoom, createFunction(featureFunctions[z], propertySpec)]);
}
return {
kind: 'composite',
interpolationFactor: Interpolate.interpolationFactor.bind(undefined, {name: 'linear'}),
zoomStops: featureFunctionStops.map(function (s) { return s[0]; }),
evaluate: function evaluate(ref, properties) {
var zoom = ref.zoom;
return evaluateExponentialFunction({
stops: featureFunctionStops,
base: parameters.base
}, propertySpec, zoom).evaluate(zoom, properties);
}
};
} else if (zoomDependent) {
return {
kind: 'camera',
interpolationFactor: type === 'exponential' ?
Interpolate.interpolationFactor.bind(undefined, {name: 'exponential', base: parameters.base !== undefined ? parameters.base : 1}) :
function () { return 0; },
zoomStops: parameters.stops.map(function (s) { return s[0]; }),
evaluate: function (ref) {
var zoom = ref.zoom;
return innerFun(parameters, propertySpec, zoom, hashedStops, categoricalKeyType);
}
};
} else {
return {
kind: 'source',
evaluate: function evaluate(_, feature) {
var value = feature && feature.properties ? feature.properties[parameters.property] : undefined;
if (value === undefined) {
return coalesce(parameters.default, propertySpec.default);
}
return innerFun(parameters, propertySpec, value, hashedStops, categoricalKeyType);
}
};
}
}
function coalesce(a, b, c) {
if (a !== undefined) { return a; }
if (b !== undefined) { return b; }
if (c !== undefined) { return c; }
}
function evaluateCategoricalFunction(parameters, propertySpec, input, hashedStops, keyType) {
var evaluated = typeof input === keyType ? hashedStops[input] : undefined; // Enforce strict typing on input
return coalesce(evaluated, parameters.default, propertySpec.default);
}
function evaluateIntervalFunction(parameters, propertySpec, input) {
// Edge cases
if (getType(input) !== 'number') { return coalesce(parameters.default, propertySpec.default); }
var n = parameters.stops.length;
if (n === 1) { return parameters.stops[0][1]; }
if (input <= parameters.stops[0][0]) { return parameters.stops[0][1]; }
if (input >= parameters.stops[n - 1][0]) { return parameters.stops[n - 1][1]; }
var index = findStopLessThanOrEqualTo$1(parameters.stops, input);
return parameters.stops[index][1];
}
function evaluateExponentialFunction(parameters, propertySpec, input) {
var base = parameters.base !== undefined ? parameters.base : 1;
// Edge cases
if (getType(input) !== 'number') { return coalesce(parameters.default, propertySpec.default); }
var n = parameters.stops.length;
if (n === 1) { return parameters.stops[0][1]; }
if (input <= parameters.stops[0][0]) { return parameters.stops[0][1]; }
if (input >= parameters.stops[n - 1][0]) { return parameters.stops[n - 1][1]; }
var index = findStopLessThanOrEqualTo$1(parameters.stops, input);
var t = interpolationFactor(
input, base,
parameters.stops[index][0],
parameters.stops[index + 1][0]);
var outputLower = parameters.stops[index][1];
var outputUpper = parameters.stops[index + 1][1];
var interp = interpolate[propertySpec.type] || identityFunction; // eslint-disable-line import/namespace
if (parameters.colorSpace && parameters.colorSpace !== 'rgb') {
var colorspace = colorSpaces[parameters.colorSpace]; // eslint-disable-line import/namespace
interp = function (a, b) { return colorspace.reverse(colorspace.interpolate(colorspace.forward(a), colorspace.forward(b), t)); };
}
if (typeof outputLower.evaluate === 'function') {
return {
evaluate: function evaluate() {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
var evaluatedLower = outputLower.evaluate.apply(undefined, args);
var evaluatedUpper = outputUpper.evaluate.apply(undefined, args);
// Special case for fill-outline-color, which has no spec default.
if (evaluatedLower === undefined || evaluatedUpper === undefined) {
return undefined;
}
return interp(evaluatedLower, evaluatedUpper, t);
}
};
}
return interp(outputLower, outputUpper, t);
}
function evaluateIdentityFunction(parameters, propertySpec, input) {
if (propertySpec.type === 'color') {
input = Color.parse(input);
} else if (getType(input) !== propertySpec.type && (propertySpec.type !== 'enum' || !propertySpec.values[input])) {
input = undefined;
}
return coalesce(input, parameters.default, propertySpec.default);
}
/**
* Returns the index of the last stop <= input, or 0 if it doesn't exist.
*
* @private
*/
function findStopLessThanOrEqualTo$1(stops, input) {
var n = stops.length;
var lowerIndex = 0;
var upperIndex = n - 1;
var currentIndex = 0;
var currentValue, upperValue;
while (lowerIndex <= upperIndex) {
currentIndex = Math.floor((lowerIndex + upperIndex) / 2);
currentValue = stops[currentIndex][0];
upperValue = stops[currentIndex + 1][0];
if (input === currentValue || input > currentValue && input < upperValue) { // Search complete
return currentIndex;
} else if (currentValue < input) {
lowerIndex = currentIndex + 1;
} else if (currentValue > input) {
upperIndex = currentIndex - 1;
}
}
return Math.max(currentIndex - 1, 0);
}
/**
* Returns a ratio that can be used to interpolate between exponential function
* stops.
*
* How it works:
* Two consecutive stop values define a (scaled and shifted) exponential
* function `f(x) = a * base^x + b`, where `base` is the user-specified base,
* and `a` and `b` are constants affording sufficient degrees of freedom to fit
* the function to the given stops.
*
* Here's a bit of algebra that lets us compute `f(x)` directly from the stop
* values without explicitly solving for `a` and `b`:
*
* First stop value: `f(x0) = y0 = a * base^x0 + b`
* Second stop value: `f(x1) = y1 = a * base^x1 + b`
* => `y1 - y0 = a(base^x1 - base^x0)`
* => `a = (y1 - y0)/(base^x1 - base^x0)`
*
* Desired value: `f(x) = y = a * base^x + b`
* => `f(x) = y0 + a * (base^x - base^x0)`
*
* From the above, we can replace the `a` in `a * (base^x - base^x0)` and do a
* little algebra:
* ```
* a * (base^x - base^x0) = (y1 - y0)/(base^x1 - base^x0) * (base^x - base^x0)
* = (y1 - y0) * (base^x - base^x0) / (base^x1 - base^x0)
* ```
*
* If we let `(base^x - base^x0) / (base^x1 base^x0)`, then we have
* `f(x) = y0 + (y1 - y0) * ratio`. In other words, `ratio` may be treated as
* an interpolation factor between the two stops' output values.
*
* (Note: a slightly different form for `ratio`,
* `(base^(x-x0) - 1) / (base^(x1-x0) - 1) `, is equivalent, but requires fewer
* expensive `Math.pow()` operations.)
*
* @private
*/
function interpolationFactor(input, base, lowerValue, upperValue) {
var difference = upperValue - lowerValue;
var progress = input - lowerValue;
if (difference === 0) {
return 0;
} else if (base === 1) {
return progress / difference;
} else {
return (Math.pow(base, progress) - 1) / (Math.pow(base, difference) - 1);
}
}
//
var StyleExpression = function StyleExpression(expression , propertySpec ) {
this.expression = expression;
this._warningHistory = {};
this._defaultValue = getDefaultValue(propertySpec);
if (propertySpec.type === 'enum') {
this._enumValues = propertySpec.values;
}
};
StyleExpression.prototype.evaluateWithoutErrorHandling = function evaluateWithoutErrorHandling (globals , feature , featureState ) {
if (!this._evaluator) {
this._evaluator = new EvaluationContext();
}
this._evaluator.globals = globals;
this._evaluator.feature = feature;
this._evaluator.featureState = featureState;
return this.expression.evaluate(this._evaluator);
};
StyleExpression.prototype.evaluate = function evaluate (globals , feature , featureState ) {
if (!this._evaluator) {
this._evaluator = new EvaluationContext();
}
this._evaluator.globals = globals;
this._evaluator.feature = feature;
this._evaluator.featureState = featureState;
try {
var val = this.expression.evaluate(this._evaluator);
if (val === null || val === undefined) {
return this._defaultValue;
}
if (this._enumValues && !(val in this._enumValues)) {
throw new RuntimeError(("Expected value to be one of " + (Object.keys(this._enumValues).map(function (v) { return JSON.stringify(v); }).join(', ')) + ", but found " + (JSON.stringify(val)) + " instead."));
}
return val;
} catch (e) {
if (!this._warningHistory[e.message]) {
this._warningHistory[e.message] = true;
if (typeof console !== 'undefined') {
console.warn(e.message);
}
}
return this._defaultValue;
}
};
function isExpression(expression ) {
return Array.isArray(expression) && expression.length > 0 &&
typeof expression[0] === 'string' && expression[0] in expressions;
}
/**
* Parse and typecheck the given style spec JSON expression. If
* options.defaultValue is provided, then the resulting StyleExpression's
* `evaluate()` method will handle errors by logging a warning (once per
* message) and returning the default value. Otherwise, it will throw
* evaluation errors.
*
* @private
*/
function createExpression(expression , propertySpec ) {
var parser = new ParsingContext(expressions, [], getExpectedType(propertySpec));
var parsed = parser.parse(expression);
if (!parsed) {
assert_1(parser.errors.length > 0);
return error(parser.errors);
}
return success(new StyleExpression(parsed, propertySpec));
}
var ZoomConstantExpression = function ZoomConstantExpression(kind , expression ) {
this.kind = kind;
this._styleExpression = expression;
this.isStateDependent = kind !== 'constant' && !isStateConstant(expression.expression);
};
ZoomConstantExpression.prototype.evaluateWithoutErrorHandling = function evaluateWithoutErrorHandling (globals , feature , featureState ) {
return this._styleExpression.evaluateWithoutErrorHandling(globals, feature, featureState);
};
ZoomConstantExpression.prototype.evaluate = function evaluate (globals , feature , featureState ) {
return this._styleExpression.evaluate(globals, feature, featureState);
};
var ZoomDependentExpression = function ZoomDependentExpression(kind , expression , zoomCurve ) {
this.kind = kind;
this.zoomStops = zoomCurve.labels;
this._styleExpression = expression;
this.isStateDependent = kind !== 'camera' && !isStateConstant(expression.expression);
if (zoomCurve instanceof Interpolate) {
this._interpolationType = zoomCurve.interpolation;
}
};
ZoomDependentExpression.prototype.evaluateWithoutErrorHandling = function evaluateWithoutErrorHandling (globals , feature , featureState ) {
return this._styleExpression.evaluateWithoutErrorHandling(globals, feature, featureState);
};
ZoomDependentExpression.prototype.evaluate = function evaluate (globals , feature , featureState ) {
return this._styleExpression.evaluate(globals, feature, featureState);
};
ZoomDependentExpression.prototype.interpolationFactor = function interpolationFactor (input , lower , upper ) {
if (this._interpolationType) {
return Interpolate.interpolationFactor(this._interpolationType, input, lower, upper);
} else {
return 0;
}
};
function createPropertyExpression(expression , propertySpec ) {
expression = createExpression(expression, propertySpec);
if (expression.result === 'error') {
return expression;
}
var parsed = expression.value.expression;
var isFeatureConstant$$1 = isFeatureConstant(parsed);
if (!isFeatureConstant$$1 && !supportsPropertyExpression(propertySpec)) {
return error([new ParsingError('', 'data expressions not supported')]);
}
var isZoomConstant = isGlobalPropertyConstant(parsed, ['zoom']);
if (!isZoomConstant && !supportsZoomExpression(propertySpec)) {
return error([new ParsingError('', 'zoom expressions not supported')]);
}
var zoomCurve = findZoomCurve(parsed);
if (!zoomCurve && !isZoomConstant) {
return error([new ParsingError('', '"zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.')]);
} else if (zoomCurve instanceof ParsingError) {
return error([zoomCurve]);
} else if (zoomCurve instanceof Interpolate && !supportsInterpolation(propertySpec)) {
return error([new ParsingError('', '"interpolate" expressions cannot be used with this property')]);
}
if (!zoomCurve) {
return success(isFeatureConstant$$1 ?
(new ZoomConstantExpression('constant', expression.value) ) :
(new ZoomConstantExpression('source', expression.value) ));
}
return success(isFeatureConstant$$1 ?
(new ZoomDependentExpression('camera', expression.value, zoomCurve) ) :
(new ZoomDependentExpression('composite', expression.value, zoomCurve) ));
}
// serialization wrapper for old-style stop functions normalized to the
// expression interface
var StylePropertyFunction = function StylePropertyFunction(parameters , specification ) {
this._parameters = parameters;
this._specification = specification;
extend$1(this, createFunction(this._parameters, this._specification));
};
StylePropertyFunction.deserialize = function deserialize (serialized ) {
return ((new StylePropertyFunction(serialized._parameters, serialized._specification)) );
};
StylePropertyFunction.serialize = function serialize (input ) {
return {
_parameters: input._parameters,
_specification: input._specification
};
};
function normalizePropertyExpression (value , specification ) {
if (isFunction(value)) {
return (new StylePropertyFunction(value, specification) );
} else if (isExpression(value)) {
var expression = createPropertyExpression(value, specification);
if (expression.result === 'error') {
// this should have been caught in validation
throw new Error(expression.value.map(function (err) { return ((err.key) + ": " + (err.message)); }).join(', '));
}
return expression.value;
} else {
var constant = value;
if (typeof value === 'string' && specification.type === 'color') {
constant = Color.parse(value);
}
return {
kind: 'constant',
evaluate: function () { return constant; }
};
}
}
// Zoom-dependent expressions may only use ["zoom"] as the input to a top-level "step" or "interpolate"
// expression (collectively referred to as a "curve"). The curve may be wrapped in one or more "let" or
// "coalesce" expressions.
function findZoomCurve(expression ) {
var result = null;
if (expression instanceof Let) {
result = findZoomCurve(expression.result);
} else if (expression instanceof Coalesce) {
for (var i = 0, list = expression.args; i < list.length; i += 1) {
var arg = list[i];
result = findZoomCurve(arg);
if (result) {
break;
}
}
} else if ((expression instanceof Step || expression instanceof Interpolate) &&
expression.input instanceof CompoundExpression &&
expression.input.name === 'zoom') {
result = expression;
}
if (result instanceof ParsingError) {
return result;
}
expression.eachChild(function (child) {
var childResult = findZoomCurve(child);
if (childResult instanceof ParsingError) {
result = childResult;
} else if (!result && childResult) {
result = new ParsingError('', '"zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.');
} else if (result && childResult && result !== childResult) {
result = new ParsingError('', 'Only one zoom-based "step" or "interpolate" subexpression may be used in an expression.');
}
});
return result;
}
function getExpectedType(spec ) {
var types = {
color: ColorType,
string: StringType,
number: NumberType,
enum: StringType,
boolean: BooleanType
};
if (spec.type === 'array') {
return array(types[spec.value] || ValueType, spec.length);
}
return types[spec.type] || null;
}
function getDefaultValue(spec ) {
if (spec.type === 'color' && isFunction(spec.default)) {
// Special case for heatmap-color: it uses the 'default:' to define a
// default color ramp, but createExpression expects a simple value to fall
// back to in case of runtime errors
return new Color(0, 0, 0, 0);
} else if (spec.type === 'color') {
return Color.parse(spec.default) || null;
} else if (spec.default === undefined) {
return null;
} else {
return spec.default;
}
}
function validateObject(options) {
var key = options.key;
var object = options.value;
var elementSpecs = options.valueSpec || {};
var elementValidators = options.objectElementValidators || {};
var style = options.style;
var styleSpec = options.styleSpec;
var errors = [];
var type = getType(object);
if (type !== 'object') {
return [new ValidationError(key, object, ("object expected, " + type + " found"))];
}
for (var objectKey in object) {
var elementSpecKey = objectKey.split('.')[0]; // treat 'paint.*' as 'paint'
var elementSpec = elementSpecs[elementSpecKey] || elementSpecs['*'];
var validateElement = (void 0);
if (elementValidators[elementSpecKey]) {
validateElement = elementValidators[elementSpecKey];
} else if (elementSpecs[elementSpecKey]) {
validateElement = validate;
} else if (elementValidators['*']) {
validateElement = elementValidators['*'];
} else if (elementSpecs['*']) {
validateElement = validate;
} else {
errors.push(new ValidationError(key, object[objectKey], ("unknown property \"" + objectKey + "\"")));
continue;
}
errors = errors.concat(validateElement({
key: (key ? (key + ".") : key) + objectKey,
value: object[objectKey],
valueSpec: elementSpec,
style: style,
styleSpec: styleSpec,
object: object,
objectKey: objectKey
}, object));
}
for (var elementSpecKey$1 in elementSpecs) {
// Don't check `required` when there's a custom validator for that property.
if (elementValidators[elementSpecKey$1]) {
continue;
}
if (elementSpecs[elementSpecKey$1].required && elementSpecs[elementSpecKey$1]['default'] === undefined && object[elementSpecKey$1] === undefined) {
errors.push(new ValidationError(key, object, ("missing required property \"" + elementSpecKey$1 + "\"")));
}
}
return errors;
}
function validateArray(options) {
var array = options.value;
var arraySpec = options.valueSpec;
var style = options.style;
var styleSpec = options.styleSpec;
var key = options.key;
var validateArrayElement = options.arrayElementValidator || validate;
if (getType(array) !== 'array') {
return [new ValidationError(key, array, ("array expected, " + (getType(array)) + " found"))];
}
if (arraySpec.length && array.length !== arraySpec.length) {
return [new ValidationError(key, array, ("array length " + (arraySpec.length) + " expected, length " + (array.length) + " found"))];
}
if (arraySpec['min-length'] && array.length < arraySpec['min-length']) {
return [new ValidationError(key, array, ("array length at least " + (arraySpec['min-length']) + " expected, length " + (array.length) + " found"))];
}
var arrayElementSpec = {
"type": arraySpec.value
};
if (styleSpec.$version < 7) {
arrayElementSpec.function = arraySpec.function;
}
if (getType(arraySpec.value) === 'object') {
arrayElementSpec = arraySpec.value;
}
var errors = [];
for (var i = 0; i < array.length; i++) {
errors = errors.concat(validateArrayElement({
array: array,
arrayIndex: i,
value: array[i],
valueSpec: arrayElementSpec,
style: style,
styleSpec: styleSpec,
key: (key + "[" + i + "]")
}));
}
return errors;
}
function validateNumber(options) {
var key = options.key;
var value = options.value;
var valueSpec = options.valueSpec;
var type = getType(value);
if (type !== 'number') {
return [new ValidationError(key, value, ("number expected, " + type + " found"))];
}
if ('minimum' in valueSpec && value < valueSpec.minimum) {
return [new ValidationError(key, value, (value + " is less than the minimum value " + (valueSpec.minimum)))];
}
if ('maximum' in valueSpec && value > valueSpec.maximum) {
return [new ValidationError(key, value, (value + " is greater than the maximum value " + (valueSpec.maximum)))];
}
return [];
}
function validateFunction(options) {
var functionValueSpec = options.valueSpec;
var functionType = unbundle(options.value.type);
var stopKeyType;
var stopDomainValues = {};
var previousStopDomainValue;
var previousStopDomainZoom;
var isZoomFunction = functionType !== 'categorical' && options.value.property === undefined;
var isPropertyFunction = !isZoomFunction;
var isZoomAndPropertyFunction =
getType(options.value.stops) === 'array' &&
getType(options.value.stops[0]) === 'array' &&
getType(options.value.stops[0][0]) === 'object';
var errors = validateObject({
key: options.key,
value: options.value,
valueSpec: options.styleSpec.function,
style: options.style,
styleSpec: options.styleSpec,
objectElementValidators: {
stops: validateFunctionStops,
default: validateFunctionDefault
}
});
if (functionType === 'identity' && isZoomFunction) {
errors.push(new ValidationError(options.key, options.value, 'missing required property "property"'));
}
if (functionType !== 'identity' && !options.value.stops) {
errors.push(new ValidationError(options.key, options.value, 'missing required property "stops"'));
}
if (functionType === 'exponential' && options.valueSpec.expression && !supportsInterpolation(options.valueSpec)) {
errors.push(new ValidationError(options.key, options.value, 'exponential functions not supported'));
}
if (options.styleSpec.$version >= 8) {
if (isPropertyFunction && !supportsPropertyExpression(options.valueSpec)) {
errors.push(new ValidationError(options.key, options.value, 'property functions not supported'));
} else if (isZoomFunction && !supportsZoomExpression(options.valueSpec)) {
errors.push(new ValidationError(options.key, options.value, 'zoom functions not supported'));
}
}
if ((functionType === 'categorical' || isZoomAndPropertyFunction) && options.value.property === undefined) {
errors.push(new ValidationError(options.key, options.value, '"property" property is required'));
}
return errors;
function validateFunctionStops(options) {
if (functionType === 'identity') {
return [new ValidationError(options.key, options.value, 'identity function may not have a "stops" property')];
}
var errors = [];
var value = options.value;
errors = errors.concat(validateArray({
key: options.key,
value: value,
valueSpec: options.valueSpec,
style: options.style,
styleSpec: options.styleSpec,
arrayElementValidator: validateFunctionStop
}));
if (getType(value) === 'array' && value.length === 0) {
errors.push(new ValidationError(options.key, value, 'array must have at least one stop'));
}
return errors;
}
function validateFunctionStop(options) {
var errors = [];
var value = options.value;
var key = options.key;
if (getType(value) !== 'array') {
return [new ValidationError(key, value, ("array expected, " + (getType(value)) + " found"))];
}
if (value.length !== 2) {
return [new ValidationError(key, value, ("array length 2 expected, length " + (value.length) + " found"))];
}
if (isZoomAndPropertyFunction) {
if (getType(value[0]) !== 'object') {
return [new ValidationError(key, value, ("object expected, " + (getType(value[0])) + " found"))];
}
if (value[0].zoom === undefined) {
return [new ValidationError(key, value, 'object stop key must have zoom')];
}
if (value[0].value === undefined) {
return [new ValidationError(key, value, 'object stop key must have value')];
}
if (previousStopDomainZoom && previousStopDomainZoom > unbundle(value[0].zoom)) {
return [new ValidationError(key, value[0].zoom, 'stop zoom values must appear in ascending order')];
}
if (unbundle(value[0].zoom) !== previousStopDomainZoom) {
previousStopDomainZoom = unbundle(value[0].zoom);
previousStopDomainValue = undefined;
stopDomainValues = {};
}
errors = errors.concat(validateObject({
key: (key + "[0]"),
value: value[0],
valueSpec: { zoom: {} },
style: options.style,
styleSpec: options.styleSpec,
objectElementValidators: { zoom: validateNumber, value: validateStopDomainValue }
}));
} else {
errors = errors.concat(validateStopDomainValue({
key: (key + "[0]"),
value: value[0],
valueSpec: {},
style: options.style,
styleSpec: options.styleSpec
}, value));
}
return errors.concat(validate({
key: (key + "[1]"),
value: value[1],
valueSpec: functionValueSpec,
style: options.style,
styleSpec: options.styleSpec
}));
}
function validateStopDomainValue(options, stop) {
var type = getType(options.value);
var value = unbundle(options.value);
var reportValue = options.value !== null ? options.value : stop;
if (!stopKeyType) {
stopKeyType = type;
} else if (type !== stopKeyType) {
return [new ValidationError(options.key, reportValue, (type + " stop domain type must match previous stop domain type " + stopKeyType))];
}
if (type !== 'number' && type !== 'string' && type !== 'boolean') {
return [new ValidationError(options.key, reportValue, 'stop domain value must be a number, string, or boolean')];
}
if (type !== 'number' && functionType !== 'categorical') {
var message = "number expected, " + type + " found";
if (supportsPropertyExpression(functionValueSpec) && functionType === undefined) {
message += '\nIf you intended to use a categorical function, specify `"type": "categorical"`.';
}
return [new ValidationError(options.key, reportValue, message)];
}
if (functionType === 'categorical' && type === 'number' && (!isFinite(value) || Math.floor(value) !== value)) {
return [new ValidationError(options.key, reportValue, ("integer expected, found " + value))];
}
if (functionType !== 'categorical' && type === 'number' && previousStopDomainValue !== undefined && value < previousStopDomainValue) {
return [new ValidationError(options.key, reportValue, 'stop domain values must appear in ascending order')];
} else {
previousStopDomainValue = value;
}
if (functionType === 'categorical' && value in stopDomainValues) {
return [new ValidationError(options.key, reportValue, 'stop domain values must be unique')];
} else {
stopDomainValues[value] = true;
}
return [];
}
function validateFunctionDefault(options) {
return validate({
key: options.key,
value: options.value,
valueSpec: functionValueSpec,
style: options.style,
styleSpec: options.styleSpec
});
}
}
//
function validateExpression(options ) {
var expression = (options.expressionContext === 'property' ? createPropertyExpression : createExpression)(deepUnbundle(options.value), options.valueSpec);
if (expression.result === 'error') {
return expression.value.map(function (error) {
return new ValidationError(("" + (options.key) + (error.key)), options.value, error.message);
});
}
if (options.expressionContext === 'property' && options.propertyKey === 'text-font' &&
(expression.value )._styleExpression.expression.possibleOutputs().indexOf(undefined) !== -1) {
return [new ValidationError(options.key, options.value, 'Invalid data expression for "text-font". Output values must be contained as literals within the expression.')];
}
if (options.expressionContext === 'property' && options.propertyType === 'layout' &&
(!isStateConstant((expression.value )._styleExpression.expression))) {
return [new ValidationError(options.key, options.value, '"feature-state" data expressions are not supported with layout properties.')];
}
return [];
}
function validateBoolean(options) {
var value = options.value;
var key = options.key;
var type = getType(value);
if (type !== 'boolean') {
return [new ValidationError(key, value, ("boolean expected, " + type + " found"))];
}
return [];
}
function validateColor(options) {
var key = options.key;
var value = options.value;
var type = getType(value);
if (type !== 'string') {
return [new ValidationError(key, value, ("color expected, " + type + " found"))];
}
if (csscolorparser_1(value) === null) {
return [new ValidationError(key, value, ("color expected, \"" + value + "\" found"))];
}
return [];
}
function validateEnum(options) {
var key = options.key;
var value = options.value;
var valueSpec = options.valueSpec;
var errors = [];
if (Array.isArray(valueSpec.values)) { // <=v7
if (valueSpec.values.indexOf(unbundle(value)) === -1) {
errors.push(new ValidationError(key, value, ("expected one of [" + (valueSpec.values.join(', ')) + "], " + (JSON.stringify(value)) + " found")));
}
} else { // >=v8
if (Object.keys(valueSpec.values).indexOf(unbundle(value)) === -1) {
errors.push(new ValidationError(key, value, ("expected one of [" + (Object.keys(valueSpec.values).join(', ')) + "], " + (JSON.stringify(value)) + " found")));
}
}
return errors;
}
//
function isExpressionFilter(filter ) {
if (!Array.isArray(filter) || filter.length === 0) {
return false;
}
switch (filter[0]) {
case 'has':
return filter.length >= 2 && filter[1] !== '$id' && filter[1] !== '$type';
case 'in':
case '!in':
case '!has':
case 'none':
return false;
case '==':
case '!=':
case '>':
case '>=':
case '<':
case '<=':
return filter.length !== 3 || (Array.isArray(filter[1]) || Array.isArray(filter[2]));
case 'any':
case 'all':
for (var i = 0, list = filter.slice(1); i < list.length; i += 1) {
var f = list[i];
if (!isExpressionFilter(f) && typeof f !== 'boolean') {
return false;
}
}
return true;
default:
return true;
}
}
var filterSpec = {
'type': 'boolean',
'default': false,
'transition': false,
'property-type': 'data-driven',
'expression': {
'interpolated': false,
'parameters': ['zoom', 'feature']
}
};
/**
* Given a filter expressed as nested arrays, return a new function
* that evaluates whether a given feature (with a .properties or .tags property)
* passes its test.
*
* @private
* @param {Array} filter mapbox gl filter
* @returns {Function} filter-evaluating function
*/
function createFilter(filter ) {
if (!filter) {
return function () { return true; };
}
if (!isExpressionFilter(filter)) {
filter = convertFilter(filter);
}
var compiled = createExpression(filter, filterSpec);
if (compiled.result === 'error') {
throw new Error(compiled.value.map(function (err) { return ((err.key) + ": " + (err.message)); }).join(', '));
} else {
return function (globalProperties , feature ) { return compiled.value.evaluate(globalProperties, feature); };
}
}
// Comparison function to sort numbers and strings
function compare(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
}
function convertFilter(filter ) {
if (!filter) { return true; }
var op = filter[0];
if (filter.length <= 1) { return (op !== 'any'); }
var converted =
op === '==' ? convertComparisonOp(filter[1], filter[2], '==') :
op === '!=' ? convertNegation(convertComparisonOp(filter[1], filter[2], '==')) :
op === '<' ||
op === '>' ||
op === '<=' ||
op === '>=' ? convertComparisonOp(filter[1], filter[2], op) :
op === 'any' ? convertDisjunctionOp(filter.slice(1)) :
op === 'all' ? ['all'].concat(filter.slice(1).map(convertFilter)) :
op === 'none' ? ['all'].concat(filter.slice(1).map(convertFilter).map(convertNegation)) :
op === 'in' ? convertInOp(filter[1], filter.slice(2)) :
op === '!in' ? convertNegation(convertInOp(filter[1], filter.slice(2))) :
op === 'has' ? convertHasOp(filter[1]) :
op === '!has' ? convertNegation(convertHasOp(filter[1])) :
true;
return converted;
}
function convertComparisonOp(property , value , op ) {
switch (property) {
case '$type':
return [("filter-type-" + op), value];
case '$id':
return [("filter-id-" + op), value];
default:
return [("filter-" + op), property, value];
}
}
function convertDisjunctionOp(filters ) {
return ['any'].concat(filters.map(convertFilter));
}
function convertInOp(property , values ) {
if (values.length === 0) { return false; }
switch (property) {
case '$type':
return ["filter-type-in", ['literal', values]];
case '$id':
return ["filter-id-in", ['literal', values]];
default:
if (values.length > 200 && !values.some(function (v) { return typeof v !== typeof values[0]; })) {
return ['filter-in-large', property, ['literal', values.sort(compare)]];
} else {
return ['filter-in-small', property, ['literal', values]];
}
}
}
function convertHasOp(property ) {
switch (property) {
case '$type':
return true;
case '$id':
return ["filter-has-id"];
default:
return ["filter-has", property];
}
}
function convertNegation(filter ) {
return ['!', filter];
}
function validateFilter(options) {
if (isExpressionFilter(deepUnbundle(options.value))) {
return validateExpression(extend$1({}, options, {
expressionContext: 'filter',
valueSpec: { value: 'boolean' }
}));
} else {
return validateNonExpressionFilter(options);
}
}
function validateNonExpressionFilter(options) {
var value = options.value;
var key = options.key;
if (getType(value) !== 'array') {
return [new ValidationError(key, value, ("array expected, " + (getType(value)) + " found"))];
}
var styleSpec = options.styleSpec;
var type;
var errors = [];
if (value.length < 1) {
return [new ValidationError(key, value, 'filter array must have at least 1 element')];
}
errors = errors.concat(validateEnum({
key: (key + "[0]"),
value: value[0],
valueSpec: styleSpec.filter_operator,
style: options.style,
styleSpec: options.styleSpec
}));
switch (unbundle(value[0])) {
case '<':
case '<=':
case '>':
case '>=':
if (value.length >= 2 && unbundle(value[1]) === '$type') {
errors.push(new ValidationError(key, value, ("\"$type\" cannot be use with operator \"" + (value[0]) + "\"")));
}
/* falls through */
case '==':
case '!=':
if (value.length !== 3) {
errors.push(new ValidationError(key, value, ("filter array for operator \"" + (value[0]) + "\" must have 3 elements")));
}
/* falls through */
case 'in':
case '!in':
if (value.length >= 2) {
type = getType(value[1]);
if (type !== 'string') {
errors.push(new ValidationError((key + "[1]"), value[1], ("string expected, " + type + " found")));
}
}
for (var i = 2; i < value.length; i++) {
type = getType(value[i]);
if (unbundle(value[1]) === '$type') {
errors = errors.concat(validateEnum({
key: (key + "[" + i + "]"),
value: value[i],
valueSpec: styleSpec.geometry_type,
style: options.style,
styleSpec: options.styleSpec
}));
} else if (type !== 'string' && type !== 'number' && type !== 'boolean') {
errors.push(new ValidationError((key + "[" + i + "]"), value[i], ("string, number, or boolean expected, " + type + " found")));
}
}
break;
case 'any':
case 'all':
case 'none':
for (var i$1 = 1; i$1 < value.length; i$1++) {
errors = errors.concat(validateNonExpressionFilter({
key: (key + "[" + i$1 + "]"),
value: value[i$1],
style: options.style,
styleSpec: options.styleSpec
}));
}
break;
case 'has':
case '!has':
type = getType(value[1]);
if (value.length !== 2) {
errors.push(new ValidationError(key, value, ("filter array for \"" + (value[0]) + "\" operator must have 2 elements")));
} else if (type !== 'string') {
errors.push(new ValidationError((key + "[1]"), value[1], ("string expected, " + type + " found")));
}
break;
}
return errors;
}
function validateProperty(options, propertyType) {
var key = options.key;
var style = options.style;
var styleSpec = options.styleSpec;
var value = options.value;
var propertyKey = options.objectKey;
var layerSpec = styleSpec[(propertyType + "_" + (options.layerType))];
if (!layerSpec) { return []; }
var transitionMatch = propertyKey.match(/^(.*)-transition$/);
if (propertyType === 'paint' && transitionMatch && layerSpec[transitionMatch[1]] && layerSpec[transitionMatch[1]].transition) {
return validate({
key: key,
value: value,
valueSpec: styleSpec.transition,
style: style,
styleSpec: styleSpec
});
}
var valueSpec = options.valueSpec || layerSpec[propertyKey];
if (!valueSpec) {
return [new ValidationError(key, value, ("unknown property \"" + propertyKey + "\""))];
}
var tokenMatch;
if (getType(value) === 'string' && supportsPropertyExpression(valueSpec) && !valueSpec.tokens && (tokenMatch = /^{([^}]+)}$/.exec(value))) {
return [new ValidationError(
key, value,
"\"" + propertyKey + "\" does not support interpolation syntax\n" +
"Use an identity property function instead: `{ \"type\": \"identity\", \"property\": " + (JSON.stringify(tokenMatch[1])) + " }`.")];
}
var errors = [];
if (options.layerType === 'symbol') {
if (propertyKey === 'text-field' && style && !style.glyphs) {
errors.push(new ValidationError(key, value, 'use of "text-field" requires a style "glyphs" property'));
}
if (propertyKey === 'text-font' && isFunction(deepUnbundle(value)) && unbundle(value.type) === 'identity') {
errors.push(new ValidationError(key, value, '"text-font" does not support identity functions'));
}
}
return errors.concat(validate({
key: options.key,
value: value,
valueSpec: valueSpec,
style: style,
styleSpec: styleSpec,
expressionContext: 'property',
propertyType: propertyType,
propertyKey: propertyKey
}));
}
function validatePaintProperty(options) {
return validateProperty(options, 'paint');
}
function validateLayoutProperty(options) {
return validateProperty(options, 'layout');
}
function validateLayer(options) {
var errors = [];
var layer = options.value;
var key = options.key;
var style = options.style;
var styleSpec = options.styleSpec;
if (!layer.type && !layer.ref) {
errors.push(new ValidationError(key, layer, 'either "type" or "ref" is required'));
}
var type = unbundle(layer.type);
var ref = unbundle(layer.ref);
if (layer.id) {
var layerId = unbundle(layer.id);
for (var i = 0; i < options.arrayIndex; i++) {
var otherLayer = style.layers[i];
if (unbundle(otherLayer.id) === layerId) {
errors.push(new ValidationError(key, layer.id, ("duplicate layer id \"" + (layer.id) + "\", previously used at line " + (otherLayer.id.__line__))));
}
}
}
if ('ref' in layer) {
['type', 'source', 'source-layer', 'filter', 'layout'].forEach(function (p) {
if (p in layer) {
errors.push(new ValidationError(key, layer[p], ("\"" + p + "\" is prohibited for ref layers")));
}
});
var parent;
style.layers.forEach(function (layer) {
if (unbundle(layer.id) === ref) { parent = layer; }
});
if (!parent) {
errors.push(new ValidationError(key, layer.ref, ("ref layer \"" + ref + "\" not found")));
} else if (parent.ref) {
errors.push(new ValidationError(key, layer.ref, 'ref cannot reference another ref layer'));
} else {
type = unbundle(parent.type);
}
} else if (type !== 'background') {
if (!layer.source) {
errors.push(new ValidationError(key, layer, 'missing required property "source"'));
} else {
var source = style.sources && style.sources[layer.source];
var sourceType = source && unbundle(source.type);
if (!source) {
errors.push(new ValidationError(key, layer.source, ("source \"" + (layer.source) + "\" not found")));
} else if (sourceType === 'vector' && type === 'raster') {
errors.push(new ValidationError(key, layer.source, ("layer \"" + (layer.id) + "\" requires a raster source")));
} else if (sourceType === 'raster' && type !== 'raster') {
errors.push(new ValidationError(key, layer.source, ("layer \"" + (layer.id) + "\" requires a vector source")));
} else if (sourceType === 'vector' && !layer['source-layer']) {
errors.push(new ValidationError(key, layer, ("layer \"" + (layer.id) + "\" must specify a \"source-layer\"")));
} else if (sourceType === 'raster-dem' && type !== 'hillshade') {
errors.push(new ValidationError(key, layer.source, 'raster-dem source can only be used with layer type \'hillshade\'.'));
} else if (type === 'line' && layer.paint && layer.paint['line-gradient'] &&
(sourceType !== 'geojson' || !source.lineMetrics)) {
errors.push(new ValidationError(key, layer, ("layer \"" + (layer.id) + "\" specifies a line-gradient, which requires a GeoJSON source with `lineMetrics` enabled.")));
}
}
}
errors = errors.concat(validateObject({
key: key,
value: layer,
valueSpec: styleSpec.layer,
style: options.style,
styleSpec: options.styleSpec,
objectElementValidators: {
'*': function() {
return [];
},
// We don't want to enforce the spec's `"requires": true` for backward compatibility with refs;
// the actual requirement is validated above. See https://github.com/mapbox/mapbox-gl-js/issues/5772.
type: function() {
return validate({
key: (key + ".type"),
value: layer.type,
valueSpec: styleSpec.layer.type,
style: options.style,
styleSpec: options.styleSpec,
object: layer,
objectKey: 'type'
});
},
filter: validateFilter,
layout: function(options) {
return validateObject({
layer: layer,
key: options.key,
value: options.value,
style: options.style,
styleSpec: options.styleSpec,
objectElementValidators: {
'*': function(options) {
return validateLayoutProperty(extend$1({layerType: type}, options));
}
}
});
},
paint: function(options) {
return validateObject({
layer: layer,
key: options.key,
value: options.value,
style: options.style,
styleSpec: options.styleSpec,
objectElementValidators: {
'*': function(options) {
return validatePaintProperty(extend$1({layerType: type}, options));
}
}
});
}
}
}));
return errors;
}
function validateSource(options) {
var value = options.value;
var key = options.key;
var styleSpec = options.styleSpec;
var style = options.style;
if (!value.type) {
return [new ValidationError(key, value, '"type" is required')];
}
var type = unbundle(value.type);
var errors = [];
switch (type) {
case 'vector':
case 'raster':
case 'raster-dem':
errors = errors.concat(validateObject({
key: key,
value: value,
valueSpec: styleSpec[("source_" + (type.replace('-', '_')))],
style: options.style,
styleSpec: styleSpec
}));
if ('url' in value) {
for (var prop in value) {
if (['type', 'url', 'tileSize'].indexOf(prop) < 0) {
errors.push(new ValidationError((key + "." + prop), value[prop], ("a source with a \"url\" property may not include a \"" + prop + "\" property")));
}
}
}
return errors;
case 'geojson':
return validateObject({
key: key,
value: value,
valueSpec: styleSpec.source_geojson,
style: style,
styleSpec: styleSpec
});
case 'video':
return validateObject({
key: key,
value: value,
valueSpec: styleSpec.source_video,
style: style,
styleSpec: styleSpec
});
case 'image':
return validateObject({
key: key,
value: value,
valueSpec: styleSpec.source_image,
style: style,
styleSpec: styleSpec
});
case 'canvas':
errors.push(new ValidationError(key, null, "Please use runtime APIs to add canvas sources, rather than including them in stylesheets.", 'source.canvas'));
return errors;
default:
return validateEnum({
key: (key + ".type"),
value: value.type,
valueSpec: {values: ['vector', 'raster', 'raster-dem', 'geojson', 'video', 'image']},
style: style,
styleSpec: styleSpec
});
}
}
function validateLight(options) {
var light = options.value;
var styleSpec = options.styleSpec;
var lightSpec = styleSpec.light;
var style = options.style;
var errors = [];
var rootType = getType(light);
if (light === undefined) {
return errors;
} else if (rootType !== 'object') {
errors = errors.concat([new ValidationError('light', light, ("object expected, " + rootType + " found"))]);
return errors;
}
for (var key in light) {
var transitionMatch = key.match(/^(.*)-transition$/);
if (transitionMatch && lightSpec[transitionMatch[1]] && lightSpec[transitionMatch[1]].transition) {
errors = errors.concat(validate({
key: key,
value: light[key],
valueSpec: styleSpec.transition,
style: style,
styleSpec: styleSpec
}));
} else if (lightSpec[key]) {
errors = errors.concat(validate({
key: key,
value: light[key],
valueSpec: lightSpec[key],
style: style,
styleSpec: styleSpec
}));
} else {
errors = errors.concat([new ValidationError(key, light[key], ("unknown property \"" + key + "\""))]);
}
}
return errors;
}
function validateString(options) {
var value = options.value;
var key = options.key;
var type = getType(value);
if (type !== 'string') {
return [new ValidationError(key, value, ("string expected, " + type + " found"))];
}
return [];
}
//
function validateFormatted(options ) {
if (validateString(options).length === 0) {
return [];
}
return validateExpression(options);
}
var VALIDATORS = {
'*': function() {
return [];
},
'array': validateArray,
'boolean': validateBoolean,
'number': validateNumber,
'color': validateColor,
'constants': validateConstants,
'enum': validateEnum,
'filter': validateFilter,
'function': validateFunction,
'layer': validateLayer,
'object': validateObject,
'source': validateSource,
'light': validateLight,
'string': validateString,
'formatted': validateFormatted
};
// Main recursive validation function. Tracks:
//
// - key: string representing location of validation in style tree. Used only
// for more informative error reporting.
// - value: current value from style being evaluated. May be anything from a
// high level object that needs to be descended into deeper or a simple
// scalar value.
// - valueSpec: current spec being evaluated. Tracks value.
// - styleSpec: current full spec being evaluated.
function validate(options) {
var value = options.value;
var valueSpec = options.valueSpec;
var styleSpec = options.styleSpec;
if (valueSpec.expression && isFunction(unbundle(value))) {
return validateFunction(options);
} else if (valueSpec.expression && isExpression(deepUnbundle(value))) {
return validateExpression(options);
} else if (valueSpec.type && VALIDATORS[valueSpec.type]) {
return VALIDATORS[valueSpec.type](options);
} else {
var valid = validateObject(extend$1({}, options, {
valueSpec: valueSpec.type ? styleSpec[valueSpec.type] : valueSpec
}));
return valid;
}
}
function validateGlyphsURL(options) {
var value = options.value;
var key = options.key;
var errors = validateString(options);
if (errors.length) { return errors; }
if (value.indexOf('{fontstack}') === -1) {
errors.push(new ValidationError(key, value, '"glyphs" url must include a "{fontstack}" token'));
}
if (value.indexOf('{range}') === -1) {
errors.push(new ValidationError(key, value, '"glyphs" url must include a "{range}" token'));
}
return errors;
}
/**
* Validate a Mapbox GL style against the style specification. This entrypoint,
* `mapbox-gl-style-spec/lib/validate_style.min`, is designed to produce as
* small a browserify bundle as possible by omitting unnecessary functionality
* and legacy style specifications.
*
* @private
* @param {Object} style The style to be validated.
* @param {Object} [styleSpec] The style specification to validate against.
* If omitted, the latest style spec is used.
* @returns {Array<ValidationError>}
* @example
* var validate = require('mapbox-gl-style-spec/lib/validate_style.min');
* var errors = validate(style);
*/
function validateStyleMin(style, styleSpec$$1) {
styleSpec$$1 = styleSpec$$1 || styleSpec;
var errors = [];
errors = errors.concat(validate({
key: '',
value: style,
valueSpec: styleSpec$$1.$root,
styleSpec: styleSpec$$1,
style: style,
objectElementValidators: {
glyphs: validateGlyphsURL,
'*': function() {
return [];
}
}
}));
if (style.constants) {
errors = errors.concat(validateConstants({
key: 'constants',
value: style.constants,
style: style,
styleSpec: styleSpec$$1
}));
}
return sortErrors(errors);
}
validateStyleMin.source = wrapCleanErrors(validateSource);
validateStyleMin.light = wrapCleanErrors(validateLight);
validateStyleMin.layer = wrapCleanErrors(validateLayer);
validateStyleMin.filter = wrapCleanErrors(validateFilter);
validateStyleMin.paintProperty = wrapCleanErrors(validatePaintProperty);
validateStyleMin.layoutProperty = wrapCleanErrors(validateLayoutProperty);
function sortErrors(errors) {
return [].concat(errors).sort(function (a, b) {
return a.line - b.line;
});
}
function wrapCleanErrors(inner) {
return function() {
return sortErrors(inner.apply(this, arguments));
};
}
//
var validateStyle = (validateStyleMin );
var validateSource$1 = (validateStyleMin.source );
var validateLight$1 = (validateStyleMin.light );
var validateFilter$1 = (validateStyleMin.filter );
var validatePaintProperty$1 = (validateStyleMin.paintProperty );
var validateLayoutProperty$1 = (validateStyleMin.layoutProperty );
function emitValidationErrors(emitter , errors ) {
var hasErrors = false;
if (errors && errors.length) {
for (var i = 0, list = errors; i < list.length; i += 1) {
var error = list[i];
emitter.fire(new ErrorEvent(new Error(error.message)));
hasErrors = true;
}
}
return hasErrors;
}
'use strict';
var gridIndex = GridIndex;
var NUM_PARAMS = 3;
function GridIndex(extent, n, padding) {
var cells = this.cells = [];
if (extent instanceof ArrayBuffer) {
this.arrayBuffer = extent;
var array = new Int32Array(this.arrayBuffer);
extent = array[0];
n = array[1];
padding = array[2];
this.d = n + 2 * padding;
for (var k = 0; k < this.d * this.d; k++) {
var start = array[NUM_PARAMS + k];
var end = array[NUM_PARAMS + k + 1];
cells.push(start === end ?
null :
array.subarray(start, end));
}
var keysOffset = array[NUM_PARAMS + cells.length];
var bboxesOffset = array[NUM_PARAMS + cells.length + 1];
this.keys = array.subarray(keysOffset, bboxesOffset);
this.bboxes = array.subarray(bboxesOffset);
this.insert = this._insertReadonly;
} else {
this.d = n + 2 * padding;
for (var i = 0; i < this.d * this.d; i++) {
cells.push([]);
}
this.keys = [];
this.bboxes = [];
}
this.n = n;
this.extent = extent;
this.padding = padding;
this.scale = n / extent;
this.uid = 0;
var p = (padding / n) * extent;
this.min = -p;
this.max = extent + p;
}
GridIndex.prototype.insert = function(key, x1, y1, x2, y2) {
this._forEachCell(x1, y1, x2, y2, this._insertCell, this.uid++);
this.keys.push(key);
this.bboxes.push(x1);
this.bboxes.push(y1);
this.bboxes.push(x2);
this.bboxes.push(y2);
};
GridIndex.prototype._insertReadonly = function() {
throw 'Cannot insert into a GridIndex created from an ArrayBuffer.';
};
GridIndex.prototype._insertCell = function(x1, y1, x2, y2, cellIndex, uid) {
this.cells[cellIndex].push(uid);
};
GridIndex.prototype.query = function(x1, y1, x2, y2) {
var min = this.min;
var max = this.max;
if (x1 <= min && y1 <= min && max <= x2 && max <= y2) {
// We use `Array#slice` because `this.keys` may be a `Int32Array` and
// some browsers (Safari and IE) do not support `TypedArray#slice`
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice#Browser_compatibility
return Array.prototype.slice.call(this.keys);
} else {
var result = [];
var seenUids = {};
this._forEachCell(x1, y1, x2, y2, this._queryCell, result, seenUids);
return result;
}
};
GridIndex.prototype._queryCell = function(x1, y1, x2, y2, cellIndex, result, seenUids) {
var cell = this.cells[cellIndex];
if (cell !== null) {
var keys = this.keys;
var bboxes = this.bboxes;
for (var u = 0; u < cell.length; u++) {
var uid = cell[u];
if (seenUids[uid] === undefined) {
var offset = uid * 4;
if ((x1 <= bboxes[offset + 2]) &&
(y1 <= bboxes[offset + 3]) &&
(x2 >= bboxes[offset + 0]) &&
(y2 >= bboxes[offset + 1])) {
seenUids[uid] = true;
result.push(keys[uid]);
} else {
seenUids[uid] = false;
}
}
}
}
};
GridIndex.prototype._forEachCell = function(x1, y1, x2, y2, fn, arg1, arg2) {
var this$1 = this;
var cx1 = this._convertToCellCoord(x1);
var cy1 = this._convertToCellCoord(y1);
var cx2 = this._convertToCellCoord(x2);
var cy2 = this._convertToCellCoord(y2);
for (var x = cx1; x <= cx2; x++) {
for (var y = cy1; y <= cy2; y++) {
var cellIndex = this$1.d * y + x;
if (fn.call(this$1, x1, y1, x2, y2, cellIndex, arg1, arg2)) { return; }
}
}
};
GridIndex.prototype._convertToCellCoord = function(x) {
return Math.max(0, Math.min(this.d - 1, Math.floor(x * this.scale) + this.padding));
};
GridIndex.prototype.toArrayBuffer = function() {
var this$1 = this;
if (this.arrayBuffer) { return this.arrayBuffer; }
var cells = this.cells;
var metadataLength = NUM_PARAMS + this.cells.length + 1 + 1;
var totalCellLength = 0;
for (var i = 0; i < this.cells.length; i++) {
totalCellLength += this$1.cells[i].length;
}
var array = new Int32Array(metadataLength + totalCellLength + this.keys.length + this.bboxes.length);
array[0] = this.extent;
array[1] = this.n;
array[2] = this.padding;
var offset = metadataLength;
for (var k = 0; k < cells.length; k++) {
var cell = cells[k];
array[NUM_PARAMS + k] = offset;
array.set(cell, offset);
offset += cell.length;
}
array[NUM_PARAMS + cells.length] = offset;
array.set(this.keys, offset);
offset += this.keys.length;
array[NUM_PARAMS + cells.length + 1] = offset;
array.set(this.bboxes, offset);
offset += this.bboxes.length;
return array.buffer;
};
//
var ImageData = self.ImageData;
// eslint-disable-line
var registry = {};
/**
* Register the given class as serializable.
*
* @param options
* @param options.omit List of properties to omit from serialization (e.g., cached/computed properties)
* @param options.shallow List of properties that should be serialized by a simple shallow copy, rather than by a recursive call to serialize().
*
* @private
*/
function register (name , klass , options) {
if ( options === void 0 ) options = {};
assert_1(!registry[name], (name + " is already registered."));
(Object.defineProperty )(klass, '_classRegistryKey', {
value: name,
writeable: false
});
registry[name] = {
klass: klass,
omit: options.omit || [],
shallow: options.shallow || []
};
}
register('Object', Object);
gridIndex.serialize = function serializeGrid(grid , transferables ) {
var buffer = grid.toArrayBuffer();
if (transferables) {
transferables.push(buffer);
}
return {buffer: buffer};
};
gridIndex.deserialize = function deserializeGrid(serialized ) {
return new gridIndex(serialized.buffer);
};
register('Grid', gridIndex);
register('Color', Color);
register('Error', Error);
register('StylePropertyFunction', StylePropertyFunction);
register('StyleExpression', StyleExpression, {omit: ['_evaluator']});
register('ZoomDependentExpression', ZoomDependentExpression);
register('ZoomConstantExpression', ZoomConstantExpression);
register('CompoundExpression', CompoundExpression, {omit: ['_evaluate']});
for (var name in expressions) {
if ((expressions[name] )._classRegistryKey) { continue; }
register(("Expression_" + name), expressions[name]);
}
/**
* Serialize the given object for transfer to or from a web worker.
*
* For non-builtin types, recursively serialize each property (possibly
* omitting certain properties - see register()), and package the result along
* with the constructor's `name` so that the appropriate constructor can be
* looked up in `deserialize()`.
*
* If a `transferables` array is provided, add any transferable objects (i.e.,
* any ArrayBuffers or ArrayBuffer views) to the list. (If a copy is needed,
* this should happen in the client code, before using serialize().)
*
* @private
*/
function serialize(input , transferables ) {
if (input === null ||
input === undefined ||
typeof input === 'boolean' ||
typeof input === 'number' ||
typeof input === 'string' ||
input instanceof Boolean ||
input instanceof Number ||
input instanceof String ||
input instanceof Date ||
input instanceof RegExp) {
return input;
}
if (input instanceof ArrayBuffer) {
if (transferables) {
transferables.push(input);
}
return input;
}
if (ArrayBuffer.isView(input)) {
var view = (input );
if (transferables) {
transferables.push(view.buffer);
}
return view;
}
if (input instanceof ImageData) {
if (transferables) {
transferables.push(input.data.buffer);
}
return input;
}
if (Array.isArray(input)) {
var serialized = [];
for (var i = 0, list = input; i < list.length; i += 1) {
var item = list[i];
serialized.push(serialize(item, transferables));
}
return serialized;
}
if (typeof input === 'object') {
var klass = (input.constructor );
var name = klass._classRegistryKey;
if (!name) {
throw new Error("can't serialize object of unregistered class");
}
assert_1(registry[name]);
var properties = klass.serialize ?
// (Temporary workaround) allow a class to provide static
// `serialize()` and `deserialize()` methods to bypass the generic
// approach.
// This temporary workaround lets us use the generic serialization
// approach for objects whose members include instances of dynamic
// StructArray types. Once we refactor StructArray to be static,
// we can remove this complexity.
(klass.serialize(input, transferables) ) : {};
if (!klass.serialize) {
for (var key in input) {
// any cast due to https://github.com/facebook/flow/issues/5393
if (!(input ).hasOwnProperty(key)) { continue; }
if (registry[name].omit.indexOf(key) >= 0) { continue; }
var property = (input )[key];
properties[key] = registry[name].shallow.indexOf(key) >= 0 ?
property :
serialize(property, transferables);
}
if (input instanceof Error) {
properties.message = input.message;
}
} else {
// make sure statically serialized object survives transfer of $name property
assert_1(!transferables || properties !== transferables[transferables.length - 1]);
}
if (properties.$name) {
throw new Error('$name property is reserved for worker serialization logic.');
}
if (name !== 'Object') {
properties.$name = name;
}
return properties;
}
throw new Error(("can't serialize object of type " + (typeof input)));
}
function deserialize(input ) {
if (input === null ||
input === undefined ||
typeof input === 'boolean' ||
typeof input === 'number' ||
typeof input === 'string' ||
input instanceof Boolean ||
input instanceof Number ||
input instanceof String ||
input instanceof Date ||
input instanceof RegExp ||
input instanceof ArrayBuffer ||
ArrayBuffer.isView(input) ||
input instanceof ImageData) {
return input;
}
if (Array.isArray(input)) {
return input.map(deserialize);
}
if (typeof input === 'object') {
var name = (input ).$name || 'Object';
var ref = registry[name];
var klass = ref.klass;
if (!klass) {
throw new Error(("can't deserialize unregistered class " + name));
}
if (klass.deserialize) {
return (klass.deserialize )(input);
}
var result = Object.create(klass.prototype);
for (var i = 0, list = Object.keys(input); i < list.length; i += 1) {
var key = list[i];
if (key === '$name') { continue; }
var value = (input )[key];
result[key] = registry[name].shallow.indexOf(key) >= 0 ? value : deserialize(value);
}
return result;
}
throw new Error(("can't deserialize object of type " + (typeof input)));
}
//
var ZoomHistory = function ZoomHistory() {
this.first = true;
};
ZoomHistory.prototype.update = function update (z , now ) {
var floorZ = Math.floor(z);
if (this.first) {
this.first = false;
this.lastIntegerZoom = floorZ;
this.lastIntegerZoomTime = 0;
this.lastZoom = z;
this.lastFloorZoom = floorZ;
return true;
}
if (this.lastFloorZoom > floorZ) {
this.lastIntegerZoom = floorZ + 1;
this.lastIntegerZoomTime = now;
} else if (this.lastFloorZoom < floorZ) {
this.lastIntegerZoom = floorZ;
this.lastIntegerZoomTime = now;
}
if (z !== this.lastZoom) {
this.lastZoom = z;
this.lastFloorZoom = floorZ;
return true;
}
return false;
};
//
// The following table comes from <http://www.unicode.org/Public/10.0.0/ucd/Blocks.txt>.
// Keep it synchronized with <http://www.unicode.org/Public/UCD/latest/ucd/Blocks.txt>.
var unicodeBlockLookup = {
// 'Basic Latin': (char) => char >= 0x0000 && char <= 0x007F,
'Latin-1 Supplement': function (char) { return char >= 0x0080 && char <= 0x00FF; },
// 'Latin Extended-A': (char) => char >= 0x0100 && char <= 0x017F,
// 'Latin Extended-B': (char) => char >= 0x0180 && char <= 0x024F,
// 'IPA Extensions': (char) => char >= 0x0250 && char <= 0x02AF,
// 'Spacing Modifier Letters': (char) => char >= 0x02B0 && char <= 0x02FF,
// 'Combining Diacritical Marks': (char) => char >= 0x0300 && char <= 0x036F,
// 'Greek and Coptic': (char) => char >= 0x0370 && char <= 0x03FF,
// 'Cyrillic': (char) => char >= 0x0400 && char <= 0x04FF,
// 'Cyrillic Supplement': (char) => char >= 0x0500 && char <= 0x052F,
// 'Armenian': (char) => char >= 0x0530 && char <= 0x058F,
//'Hebrew': (char) => char >= 0x0590 && char <= 0x05FF,
'Arabic': function (char) { return char >= 0x0600 && char <= 0x06FF; },
//'Syriac': (char) => char >= 0x0700 && char <= 0x074F,
'Arabic Supplement': function (char) { return char >= 0x0750 && char <= 0x077F; },
// 'Thaana': (char) => char >= 0x0780 && char <= 0x07BF,
// 'NKo': (char) => char >= 0x07C0 && char <= 0x07FF,
// 'Samaritan': (char) => char >= 0x0800 && char <= 0x083F,
// 'Mandaic': (char) => char >= 0x0840 && char <= 0x085F,
// 'Syriac Supplement': (char) => char >= 0x0860 && char <= 0x086F,
'Arabic Extended-A': function (char) { return char >= 0x08A0 && char <= 0x08FF; },
// 'Devanagari': (char) => char >= 0x0900 && char <= 0x097F,
// 'Bengali': (char) => char >= 0x0980 && char <= 0x09FF,
// 'Gurmukhi': (char) => char >= 0x0A00 && char <= 0x0A7F,
// 'Gujarati': (char) => char >= 0x0A80 && char <= 0x0AFF,
// 'Oriya': (char) => char >= 0x0B00 && char <= 0x0B7F,
// 'Tamil': (char) => char >= 0x0B80 && char <= 0x0BFF,
// 'Telugu': (char) => char >= 0x0C00 && char <= 0x0C7F,
// 'Kannada': (char) => char >= 0x0C80 && char <= 0x0CFF,
// 'Malayalam': (char) => char >= 0x0D00 && char <= 0x0D7F,
// 'Sinhala': (char) => char >= 0x0D80 && char <= 0x0DFF,
// 'Thai': (char) => char >= 0x0E00 && char <= 0x0E7F,
// 'Lao': (char) => char >= 0x0E80 && char <= 0x0EFF,
// 'Tibetan': (char) => char >= 0x0F00 && char <= 0x0FFF,
// 'Myanmar': (char) => char >= 0x1000 && char <= 0x109F,
// 'Georgian': (char) => char >= 0x10A0 && char <= 0x10FF,
'Hangul Jamo': function (char) { return char >= 0x1100 && char <= 0x11FF; },
// 'Ethiopic': (char) => char >= 0x1200 && char <= 0x137F,
// 'Ethiopic Supplement': (char) => char >= 0x1380 && char <= 0x139F,
// 'Cherokee': (char) => char >= 0x13A0 && char <= 0x13FF,
'Unified Canadian Aboriginal Syllabics': function (char) { return char >= 0x1400 && char <= 0x167F; },
// 'Ogham': (char) => char >= 0x1680 && char <= 0x169F,
// 'Runic': (char) => char >= 0x16A0 && char <= 0x16FF,
// 'Tagalog': (char) => char >= 0x1700 && char <= 0x171F,
// 'Hanunoo': (char) => char >= 0x1720 && char <= 0x173F,
// 'Buhid': (char) => char >= 0x1740 && char <= 0x175F,
// 'Tagbanwa': (char) => char >= 0x1760 && char <= 0x177F,
'Khmer': function (char) { return char >= 0x1780 && char <= 0x17FF; },
// 'Mongolian': (char) => char >= 0x1800 && char <= 0x18AF,
'Unified Canadian Aboriginal Syllabics Extended': function (char) { return char >= 0x18B0 && char <= 0x18FF; },
// 'Limbu': (char) => char >= 0x1900 && char <= 0x194F,
// 'Tai Le': (char) => char >= 0x1950 && char <= 0x197F,
// 'New Tai Lue': (char) => char >= 0x1980 && char <= 0x19DF,
// 'Khmer Symbols': (char) => char >= 0x19E0 && char <= 0x19FF,
// 'Buginese': (char) => char >= 0x1A00 && char <= 0x1A1F,
// 'Tai Tham': (char) => char >= 0x1A20 && char <= 0x1AAF,
// 'Combining Diacritical Marks Extended': (char) => char >= 0x1AB0 && char <= 0x1AFF,
// 'Balinese': (char) => char >= 0x1B00 && char <= 0x1B7F,
// 'Sundanese': (char) => char >= 0x1B80 && char <= 0x1BBF,
// 'Batak': (char) => char >= 0x1BC0 && char <= 0x1BFF,
// 'Lepcha': (char) => char >= 0x1C00 && char <= 0x1C4F,
// 'Ol Chiki': (char) => char >= 0x1C50 && char <= 0x1C7F,
// 'Cyrillic Extended-C': (char) => char >= 0x1C80 && char <= 0x1C8F,
// 'Sundanese Supplement': (char) => char >= 0x1CC0 && char <= 0x1CCF,
// 'Vedic Extensions': (char) => char >= 0x1CD0 && char <= 0x1CFF,
// 'Phonetic Extensions': (char) => char >= 0x1D00 && char <= 0x1D7F,
// 'Phonetic Extensions Supplement': (char) => char >= 0x1D80 && char <= 0x1DBF,
// 'Combining Diacritical Marks Supplement': (char) => char >= 0x1DC0 && char <= 0x1DFF,
// 'Latin Extended Additional': (char) => char >= 0x1E00 && char <= 0x1EFF,
// 'Greek Extended': (char) => char >= 0x1F00 && char <= 0x1FFF,
'General Punctuation': function (char) { return char >= 0x2000 && char <= 0x206F; },
// 'Superscripts and Subscripts': (char) => char >= 0x2070 && char <= 0x209F,
// 'Currency Symbols': (char) => char >= 0x20A0 && char <= 0x20CF,
// 'Combining Diacritical Marks for Symbols': (char) => char >= 0x20D0 && char <= 0x20FF,
'Letterlike Symbols': function (char) { return char >= 0x2100 && char <= 0x214F; },
'Number Forms': function (char) { return char >= 0x2150 && char <= 0x218F; },
// 'Arrows': (char) => char >= 0x2190 && char <= 0x21FF,
// 'Mathematical Operators': (char) => char >= 0x2200 && char <= 0x22FF,
'Miscellaneous Technical': function (char) { return char >= 0x2300 && char <= 0x23FF; },
'Control Pictures': function (char) { return char >= 0x2400 && char <= 0x243F; },
'Optical Character Recognition': function (char) { return char >= 0x2440 && char <= 0x245F; },
'Enclosed Alphanumerics': function (char) { return char >= 0x2460 && char <= 0x24FF; },
// 'Box Drawing': (char) => char >= 0x2500 && char <= 0x257F,
// 'Block Elements': (char) => char >= 0x2580 && char <= 0x259F,
'Geometric Shapes': function (char) { return char >= 0x25A0 && char <= 0x25FF; },
'Miscellaneous Symbols': function (char) { return char >= 0x2600 && char <= 0x26FF; },
// 'Dingbats': (char) => char >= 0x2700 && char <= 0x27BF,
// 'Miscellaneous Mathematical Symbols-A': (char) => char >= 0x27C0 && char <= 0x27EF,
// 'Supplemental Arrows-A': (char) => char >= 0x27F0 && char <= 0x27FF,
// 'Braille Patterns': (char) => char >= 0x2800 && char <= 0x28FF,
// 'Supplemental Arrows-B': (char) => char >= 0x2900 && char <= 0x297F,
// 'Miscellaneous Mathematical Symbols-B': (char) => char >= 0x2980 && char <= 0x29FF,
// 'Supplemental Mathematical Operators': (char) => char >= 0x2A00 && char <= 0x2AFF,
'Miscellaneous Symbols and Arrows': function (char) { return char >= 0x2B00 && char <= 0x2BFF; },
// 'Glagolitic': (char) => char >= 0x2C00 && char <= 0x2C5F,
// 'Latin Extended-C': (char) => char >= 0x2C60 && char <= 0x2C7F,
// 'Coptic': (char) => char >= 0x2C80 && char <= 0x2CFF,
// 'Georgian Supplement': (char) => char >= 0x2D00 && char <= 0x2D2F,
// 'Tifinagh': (char) => char >= 0x2D30 && char <= 0x2D7F,
// 'Ethiopic Extended': (char) => char >= 0x2D80 && char <= 0x2DDF,
// 'Cyrillic Extended-A': (char) => char >= 0x2DE0 && char <= 0x2DFF,
// 'Supplemental Punctuation': (char) => char >= 0x2E00 && char <= 0x2E7F,
'CJK Radicals Supplement': function (char) { return char >= 0x2E80 && char <= 0x2EFF; },
'Kangxi Radicals': function (char) { return char >= 0x2F00 && char <= 0x2FDF; },
'Ideographic Description Characters': function (char) { return char >= 0x2FF0 && char <= 0x2FFF; },
'CJK Symbols and Punctuation': function (char) { return char >= 0x3000 && char <= 0x303F; },
'Hiragana': function (char) { return char >= 0x3040 && char <= 0x309F; },
'Katakana': function (char) { return char >= 0x30A0 && char <= 0x30FF; },
'Bopomofo': function (char) { return char >= 0x3100 && char <= 0x312F; },
'Hangul Compatibility Jamo': function (char) { return char >= 0x3130 && char <= 0x318F; },
'Kanbun': function (char) { return char >= 0x3190 && char <= 0x319F; },
'Bopomofo Extended': function (char) { return char >= 0x31A0 && char <= 0x31BF; },
'CJK Strokes': function (char) { return char >= 0x31C0 && char <= 0x31EF; },
'Katakana Phonetic Extensions': function (char) { return char >= 0x31F0 && char <= 0x31FF; },
'Enclosed CJK Letters and Months': function (char) { return char >= 0x3200 && char <= 0x32FF; },
'CJK Compatibility': function (char) { return char >= 0x3300 && char <= 0x33FF; },
'CJK Unified Ideographs Extension A': function (char) { return char >= 0x3400 && char <= 0x4DBF; },
'Yijing Hexagram Symbols': function (char) { return char >= 0x4DC0 && char <= 0x4DFF; },
'CJK Unified Ideographs': function (char) { return char >= 0x4E00 && char <= 0x9FFF; },
'Yi Syllables': function (char) { return char >= 0xA000 && char <= 0xA48F; },
'Yi Radicals': function (char) { return char >= 0xA490 && char <= 0xA4CF; },
// 'Lisu': (char) => char >= 0xA4D0 && char <= 0xA4FF,
// 'Vai': (char) => char >= 0xA500 && char <= 0xA63F,
// 'Cyrillic Extended-B': (char) => char >= 0xA640 && char <= 0xA69F,
// 'Bamum': (char) => char >= 0xA6A0 && char <= 0xA6FF,
// 'Modifier Tone Letters': (char) => char >= 0xA700 && char <= 0xA71F,
// 'Latin Extended-D': (char) => char >= 0xA720 && char <= 0xA7FF,
// 'Syloti Nagri': (char) => char >= 0xA800 && char <= 0xA82F,
// 'Common Indic Number Forms': (char) => char >= 0xA830 && char <= 0xA83F,
// 'Phags-pa': (char) => char >= 0xA840 && char <= 0xA87F,
// 'Saurashtra': (char) => char >= 0xA880 && char <= 0xA8DF,
// 'Devanagari Extended': (char) => char >= 0xA8E0 && char <= 0xA8FF,
// 'Kayah Li': (char) => char >= 0xA900 && char <= 0xA92F,
// 'Rejang': (char) => char >= 0xA930 && char <= 0xA95F,
'Hangul Jamo Extended-A': function (char) { return char >= 0xA960 && char <= 0xA97F; },
// 'Javanese': (char) => char >= 0xA980 && char <= 0xA9DF,
// 'Myanmar Extended-B': (char) => char >= 0xA9E0 && char <= 0xA9FF,
// 'Cham': (char) => char >= 0xAA00 && char <= 0xAA5F,
// 'Myanmar Extended-A': (char) => char >= 0xAA60 && char <= 0xAA7F,
// 'Tai Viet': (char) => char >= 0xAA80 && char <= 0xAADF,
// 'Meetei Mayek Extensions': (char) => char >= 0xAAE0 && char <= 0xAAFF,
// 'Ethiopic Extended-A': (char) => char >= 0xAB00 && char <= 0xAB2F,
// 'Latin Extended-E': (char) => char >= 0xAB30 && char <= 0xAB6F,
// 'Cherokee Supplement': (char) => char >= 0xAB70 && char <= 0xABBF,
// 'Meetei Mayek': (char) => char >= 0xABC0 && char <= 0xABFF,
'Hangul Syllables': function (char) { return char >= 0xAC00 && char <= 0xD7AF; },
'Hangul Jamo Extended-B': function (char) { return char >= 0xD7B0 && char <= 0xD7FF; },
// 'High Surrogates': (char) => char >= 0xD800 && char <= 0xDB7F,
// 'High Private Use Surrogates': (char) => char >= 0xDB80 && char <= 0xDBFF,
// 'Low Surrogates': (char) => char >= 0xDC00 && char <= 0xDFFF,
'Private Use Area': function (char) { return char >= 0xE000 && char <= 0xF8FF; },
'CJK Compatibility Ideographs': function (char) { return char >= 0xF900 && char <= 0xFAFF; },
// 'Alphabetic Presentation Forms': (char) => char >= 0xFB00 && char <= 0xFB4F,
'Arabic Presentation Forms-A': function (char) { return char >= 0xFB50 && char <= 0xFDFF; },
// 'Variation Selectors': (char) => char >= 0xFE00 && char <= 0xFE0F,
'Vertical Forms': function (char) { return char >= 0xFE10 && char <= 0xFE1F; },
// 'Combining Half Marks': (char) => char >= 0xFE20 && char <= 0xFE2F,
'CJK Compatibility Forms': function (char) { return char >= 0xFE30 && char <= 0xFE4F; },
'Small Form Variants': function (char) { return char >= 0xFE50 && char <= 0xFE6F; },
'Arabic Presentation Forms-B': function (char) { return char >= 0xFE70 && char <= 0xFEFF; },
'Halfwidth and Fullwidth Forms': function (char) { return char >= 0xFF00 && char <= 0xFFEF; }
// 'Specials': (char) => char >= 0xFFF0 && char <= 0xFFFF,
// 'Linear B Syllabary': (char) => char >= 0x10000 && char <= 0x1007F,
// 'Linear B Ideograms': (char) => char >= 0x10080 && char <= 0x100FF,
// 'Aegean Numbers': (char) => char >= 0x10100 && char <= 0x1013F,
// 'Ancient Greek Numbers': (char) => char >= 0x10140 && char <= 0x1018F,
// 'Ancient Symbols': (char) => char >= 0x10190 && char <= 0x101CF,
// 'Phaistos Disc': (char) => char >= 0x101D0 && char <= 0x101FF,
// 'Lycian': (char) => char >= 0x10280 && char <= 0x1029F,
// 'Carian': (char) => char >= 0x102A0 && char <= 0x102DF,
// 'Coptic Epact Numbers': (char) => char >= 0x102E0 && char <= 0x102FF,
// 'Old Italic': (char) => char >= 0x10300 && char <= 0x1032F,
// 'Gothic': (char) => char >= 0x10330 && char <= 0x1034F,
// 'Old Permic': (char) => char >= 0x10350 && char <= 0x1037F,
// 'Ugaritic': (char) => char >= 0x10380 && char <= 0x1039F,
// 'Old Persian': (char) => char >= 0x103A0 && char <= 0x103DF,
// 'Deseret': (char) => char >= 0x10400 && char <= 0x1044F,
// 'Shavian': (char) => char >= 0x10450 && char <= 0x1047F,
// 'Osmanya': (char) => char >= 0x10480 && char <= 0x104AF,
// 'Osage': (char) => char >= 0x104B0 && char <= 0x104FF,
// 'Elbasan': (char) => char >= 0x10500 && char <= 0x1052F,
// 'Caucasian Albanian': (char) => char >= 0x10530 && char <= 0x1056F,
// 'Linear A': (char) => char >= 0x10600 && char <= 0x1077F,
// 'Cypriot Syllabary': (char) => char >= 0x10800 && char <= 0x1083F,
// 'Imperial Aramaic': (char) => char >= 0x10840 && char <= 0x1085F,
// 'Palmyrene': (char) => char >= 0x10860 && char <= 0x1087F,
// 'Nabataean': (char) => char >= 0x10880 && char <= 0x108AF,
// 'Hatran': (char) => char >= 0x108E0 && char <= 0x108FF,
// 'Phoenician': (char) => char >= 0x10900 && char <= 0x1091F,
// 'Lydian': (char) => char >= 0x10920 && char <= 0x1093F,
// 'Meroitic Hieroglyphs': (char) => char >= 0x10980 && char <= 0x1099F,
// 'Meroitic Cursive': (char) => char >= 0x109A0 && char <= 0x109FF,
// 'Kharoshthi': (char) => char >= 0x10A00 && char <= 0x10A5F,
// 'Old South Arabian': (char) => char >= 0x10A60 && char <= 0x10A7F,
// 'Old North Arabian': (char) => char >= 0x10A80 && char <= 0x10A9F,
// 'Manichaean': (char) => char >= 0x10AC0 && char <= 0x10AFF,
// 'Avestan': (char) => char >= 0x10B00 && char <= 0x10B3F,
// 'Inscriptional Parthian': (char) => char >= 0x10B40 && char <= 0x10B5F,
// 'Inscriptional Pahlavi': (char) => char >= 0x10B60 && char <= 0x10B7F,
// 'Psalter Pahlavi': (char) => char >= 0x10B80 && char <= 0x10BAF,
// 'Old Turkic': (char) => char >= 0x10C00 && char <= 0x10C4F,
// 'Old Hungarian': (char) => char >= 0x10C80 && char <= 0x10CFF,
// 'Rumi Numeral Symbols': (char) => char >= 0x10E60 && char <= 0x10E7F,
// 'Brahmi': (char) => char >= 0x11000 && char <= 0x1107F,
// 'Kaithi': (char) => char >= 0x11080 && char <= 0x110CF,
// 'Sora Sompeng': (char) => char >= 0x110D0 && char <= 0x110FF,
// 'Chakma': (char) => char >= 0x11100 && char <= 0x1114F,
// 'Mahajani': (char) => char >= 0x11150 && char <= 0x1117F,
// 'Sharada': (char) => char >= 0x11180 && char <= 0x111DF,
// 'Sinhala Archaic Numbers': (char) => char >= 0x111E0 && char <= 0x111FF,
// 'Khojki': (char) => char >= 0x11200 && char <= 0x1124F,
// 'Multani': (char) => char >= 0x11280 && char <= 0x112AF,
// 'Khudawadi': (char) => char >= 0x112B0 && char <= 0x112FF,
// 'Grantha': (char) => char >= 0x11300 && char <= 0x1137F,
// 'Newa': (char) => char >= 0x11400 && char <= 0x1147F,
// 'Tirhuta': (char) => char >= 0x11480 && char <= 0x114DF,
// 'Siddham': (char) => char >= 0x11580 && char <= 0x115FF,
// 'Modi': (char) => char >= 0x11600 && char <= 0x1165F,
// 'Mongolian Supplement': (char) => char >= 0x11660 && char <= 0x1167F,
// 'Takri': (char) => char >= 0x11680 && char <= 0x116CF,
// 'Ahom': (char) => char >= 0x11700 && char <= 0x1173F,
// 'Warang Citi': (char) => char >= 0x118A0 && char <= 0x118FF,
// 'Zanabazar Square': (char) => char >= 0x11A00 && char <= 0x11A4F,
// 'Soyombo': (char) => char >= 0x11A50 && char <= 0x11AAF,
// 'Pau Cin Hau': (char) => char >= 0x11AC0 && char <= 0x11AFF,
// 'Bhaiksuki': (char) => char >= 0x11C00 && char <= 0x11C6F,
// 'Marchen': (char) => char >= 0x11C70 && char <= 0x11CBF,
// 'Masaram Gondi': (char) => char >= 0x11D00 && char <= 0x11D5F,
// 'Cuneiform': (char) => char >= 0x12000 && char <= 0x123FF,
// 'Cuneiform Numbers and Punctuation': (char) => char >= 0x12400 && char <= 0x1247F,
// 'Early Dynastic Cuneiform': (char) => char >= 0x12480 && char <= 0x1254F,
// 'Egyptian Hieroglyphs': (char) => char >= 0x13000 && char <= 0x1342F,
// 'Anatolian Hieroglyphs': (char) => char >= 0x14400 && char <= 0x1467F,
// 'Bamum Supplement': (char) => char >= 0x16800 && char <= 0x16A3F,
// 'Mro': (char) => char >= 0x16A40 && char <= 0x16A6F,
// 'Bassa Vah': (char) => char >= 0x16AD0 && char <= 0x16AFF,
// 'Pahawh Hmong': (char) => char >= 0x16B00 && char <= 0x16B8F,
// 'Miao': (char) => char >= 0x16F00 && char <= 0x16F9F,
// 'Ideographic Symbols and Punctuation': (char) => char >= 0x16FE0 && char <= 0x16FFF,
// 'Tangut': (char) => char >= 0x17000 && char <= 0x187FF,
// 'Tangut Components': (char) => char >= 0x18800 && char <= 0x18AFF,
// 'Kana Supplement': (char) => char >= 0x1B000 && char <= 0x1B0FF,
// 'Kana Extended-A': (char) => char >= 0x1B100 && char <= 0x1B12F,
// 'Nushu': (char) => char >= 0x1B170 && char <= 0x1B2FF,
// 'Duployan': (char) => char >= 0x1BC00 && char <= 0x1BC9F,
// 'Shorthand Format Controls': (char) => char >= 0x1BCA0 && char <= 0x1BCAF,
// 'Byzantine Musical Symbols': (char) => char >= 0x1D000 && char <= 0x1D0FF,
// 'Musical Symbols': (char) => char >= 0x1D100 && char <= 0x1D1FF,
// 'Ancient Greek Musical Notation': (char) => char >= 0x1D200 && char <= 0x1D24F,
// 'Tai Xuan Jing Symbols': (char) => char >= 0x1D300 && char <= 0x1D35F,
// 'Counting Rod Numerals': (char) => char >= 0x1D360 && char <= 0x1D37F,
// 'Mathematical Alphanumeric Symbols': (char) => char >= 0x1D400 && char <= 0x1D7FF,
// 'Sutton SignWriting': (char) => char >= 0x1D800 && char <= 0x1DAAF,
// 'Glagolitic Supplement': (char) => char >= 0x1E000 && char <= 0x1E02F,
// 'Mende Kikakui': (char) => char >= 0x1E800 && char <= 0x1E8DF,
// 'Adlam': (char) => char >= 0x1E900 && char <= 0x1E95F,
// 'Arabic Mathematical Alphabetic Symbols': (char) => char >= 0x1EE00 && char <= 0x1EEFF,
// 'Mahjong Tiles': (char) => char >= 0x1F000 && char <= 0x1F02F,
// 'Domino Tiles': (char) => char >= 0x1F030 && char <= 0x1F09F,
// 'Playing Cards': (char) => char >= 0x1F0A0 && char <= 0x1F0FF,
// 'Enclosed Alphanumeric Supplement': (char) => char >= 0x1F100 && char <= 0x1F1FF,
// 'Enclosed Ideographic Supplement': (char) => char >= 0x1F200 && char <= 0x1F2FF,
// 'Miscellaneous Symbols and Pictographs': (char) => char >= 0x1F300 && char <= 0x1F5FF,
// 'Emoticons': (char) => char >= 0x1F600 && char <= 0x1F64F,
// 'Ornamental Dingbats': (char) => char >= 0x1F650 && char <= 0x1F67F,
// 'Transport and Map Symbols': (char) => char >= 0x1F680 && char <= 0x1F6FF,
// 'Alchemical Symbols': (char) => char >= 0x1F700 && char <= 0x1F77F,
// 'Geometric Shapes Extended': (char) => char >= 0x1F780 && char <= 0x1F7FF,
// 'Supplemental Arrows-C': (char) => char >= 0x1F800 && char <= 0x1F8FF,
// 'Supplemental Symbols and Pictographs': (char) => char >= 0x1F900 && char <= 0x1F9FF,
// 'CJK Unified Ideographs Extension B': (char) => char >= 0x20000 && char <= 0x2A6DF,
// 'CJK Unified Ideographs Extension C': (char) => char >= 0x2A700 && char <= 0x2B73F,
// 'CJK Unified Ideographs Extension D': (char) => char >= 0x2B740 && char <= 0x2B81F,
// 'CJK Unified Ideographs Extension E': (char) => char >= 0x2B820 && char <= 0x2CEAF,
// 'CJK Unified Ideographs Extension F': (char) => char >= 0x2CEB0 && char <= 0x2EBEF,
// 'CJK Compatibility Ideographs Supplement': (char) => char >= 0x2F800 && char <= 0x2FA1F,
// 'Tags': (char) => char >= 0xE0000 && char <= 0xE007F,
// 'Variation Selectors Supplement': (char) => char >= 0xE0100 && char <= 0xE01EF,
// 'Supplementary Private Use Area-A': (char) => char >= 0xF0000 && char <= 0xFFFFF,
// 'Supplementary Private Use Area-B': (char) => char >= 0x100000 && char <= 0x10FFFF,
};
//
function allowsIdeographicBreaking(chars ) {
for (var i = 0, list = chars; i < list.length; i += 1) {
var char = list[i];
if (!charAllowsIdeographicBreaking(char.charCodeAt(0))) { return false; }
}
return true;
}
function allowsVerticalWritingMode(chars ) {
for (var i = 0, list = chars; i < list.length; i += 1) {
var char = list[i];
if (charHasUprightVerticalOrientation(char.charCodeAt(0))) { return true; }
}
return false;
}
function allowsLetterSpacing(chars ) {
for (var i = 0, list = chars; i < list.length; i += 1) {
var char = list[i];
if (!charAllowsLetterSpacing(char.charCodeAt(0))) { return false; }
}
return true;
}
function charAllowsLetterSpacing(char ) {
if (unicodeBlockLookup['Arabic'](char)) { return false; }
if (unicodeBlockLookup['Arabic Supplement'](char)) { return false; }
if (unicodeBlockLookup['Arabic Extended-A'](char)) { return false; }
if (unicodeBlockLookup['Arabic Presentation Forms-A'](char)) { return false; }
if (unicodeBlockLookup['Arabic Presentation Forms-B'](char)) { return false; }
return true;
}
function charAllowsIdeographicBreaking(char ) {
// Return early for characters outside all ideographic ranges.
if (char < 0x2E80) { return false; }
if (unicodeBlockLookup['Bopomofo Extended'](char)) { return true; }
if (unicodeBlockLookup['Bopomofo'](char)) { return true; }
if (unicodeBlockLookup['CJK Compatibility Forms'](char)) { return true; }
if (unicodeBlockLookup['CJK Compatibility Ideographs'](char)) { return true; }
if (unicodeBlockLookup['CJK Compatibility'](char)) { return true; }
if (unicodeBlockLookup['CJK Radicals Supplement'](char)) { return true; }
if (unicodeBlockLookup['CJK Strokes'](char)) { return true; }
if (unicodeBlockLookup['CJK Symbols and Punctuation'](char)) { return true; }
if (unicodeBlockLookup['CJK Unified Ideographs Extension A'](char)) { return true; }
if (unicodeBlockLookup['CJK Unified Ideographs'](char)) { return true; }
if (unicodeBlockLookup['Enclosed CJK Letters and Months'](char)) { return true; }
if (unicodeBlockLookup['Halfwidth and Fullwidth Forms'](char)) { return true; }
if (unicodeBlockLookup['Hiragana'](char)) { return true; }
if (unicodeBlockLookup['Ideographic Description Characters'](char)) { return true; }
if (unicodeBlockLookup['Kangxi Radicals'](char)) { return true; }
if (unicodeBlockLookup['Katakana Phonetic Extensions'](char)) { return true; }
if (unicodeBlockLookup['Katakana'](char)) { return true; }
if (unicodeBlockLookup['Vertical Forms'](char)) { return true; }
if (unicodeBlockLookup['Yi Radicals'](char)) { return true; }
if (unicodeBlockLookup['Yi Syllables'](char)) { return true; }
return false;
}
// The following logic comes from
// <http://www.unicode.org/Public/vertical/revision-17/VerticalOrientation-17.txt>.
// The data file denotes with “U” or “Tu” any codepoint that may be drawn
// upright in vertical text but does not distinguish between upright and
// “neutral” characters.
// Blocks in the Unicode supplementary planes are excluded from this module due
// to <https://github.com/mapbox/mapbox-gl/issues/29>.
/**
* Returns true if the given Unicode codepoint identifies a character with
* upright orientation.
*
* A character has upright orientation if it is drawn upright (unrotated)
* whether the line is oriented horizontally or vertically, even if both
* adjacent characters can be rotated. For example, a Chinese character is
* always drawn upright. An uprightly oriented character causes an adjacent
* “neutral” character to be drawn upright as well.
* @private
*/
function charHasUprightVerticalOrientation(char ) {
if (char === 0x02EA /* modifier letter yin departing tone mark */ ||
char === 0x02EB /* modifier letter yang departing tone mark */) {
return true;
}
// Return early for characters outside all ranges whose characters remain
// upright in vertical writing mode.
if (char < 0x1100) { return false; }
if (unicodeBlockLookup['Bopomofo Extended'](char)) { return true; }
if (unicodeBlockLookup['Bopomofo'](char)) { return true; }
if (unicodeBlockLookup['CJK Compatibility Forms'](char)) {
if (!((char >= 0xFE49 /* dashed overline */ && char <= 0xFE4F) /* wavy low line */)) {
return true;
}
}
if (unicodeBlockLookup['CJK Compatibility Ideographs'](char)) { return true; }
if (unicodeBlockLookup['CJK Compatibility'](char)) { return true; }
if (unicodeBlockLookup['CJK Radicals Supplement'](char)) { return true; }
if (unicodeBlockLookup['CJK Strokes'](char)) { return true; }
if (unicodeBlockLookup['CJK Symbols and Punctuation'](char)) {
if (!((char >= 0x3008 /* left angle bracket */ && char <= 0x3011) /* right black lenticular bracket */) &&
!((char >= 0x3014 /* left tortoise shell bracket */ && char <= 0x301F) /* low double prime quotation mark */) &&
char !== 0x3030 /* wavy dash */) {
return true;
}
}
if (unicodeBlockLookup['CJK Unified Ideographs Extension A'](char)) { return true; }
if (unicodeBlockLookup['CJK Unified Ideographs'](char)) { return true; }
if (unicodeBlockLookup['Enclosed CJK Letters and Months'](char)) { return true; }
if (unicodeBlockLookup['Hangul Compatibility Jamo'](char)) { return true; }
if (unicodeBlockLookup['Hangul Jamo Extended-A'](char)) { return true; }
if (unicodeBlockLookup['Hangul Jamo Extended-B'](char)) { return true; }
if (unicodeBlockLookup['Hangul Jamo'](char)) { return true; }
if (unicodeBlockLookup['Hangul Syllables'](char)) { return true; }
if (unicodeBlockLookup['Hiragana'](char)) { return true; }
if (unicodeBlockLookup['Ideographic Description Characters'](char)) { return true; }
if (unicodeBlockLookup['Kanbun'](char)) { return true; }
if (unicodeBlockLookup['Kangxi Radicals'](char)) { return true; }
if (unicodeBlockLookup['Katakana Phonetic Extensions'](char)) { return true; }
if (unicodeBlockLookup['Katakana'](char)) {
if (char !== 0x30FC /* katakana-hiragana prolonged sound mark */) {
return true;
}
}
if (unicodeBlockLookup['Halfwidth and Fullwidth Forms'](char)) {
if (char !== 0xFF08 /* fullwidth left parenthesis */ &&
char !== 0xFF09 /* fullwidth right parenthesis */ &&
char !== 0xFF0D /* fullwidth hyphen-minus */ &&
!((char >= 0xFF1A /* fullwidth colon */ && char <= 0xFF1E) /* fullwidth greater-than sign */) &&
char !== 0xFF3B /* fullwidth left square bracket */ &&
char !== 0xFF3D /* fullwidth right square bracket */ &&
char !== 0xFF3F /* fullwidth low line */ &&
!(char >= 0xFF5B /* fullwidth left curly bracket */ && char <= 0xFFDF) &&
char !== 0xFFE3 /* fullwidth macron */ &&
!(char >= 0xFFE8 /* halfwidth forms light vertical */ && char <= 0xFFEF)) {
return true;
}
}
if (unicodeBlockLookup['Small Form Variants'](char)) {
if (!((char >= 0xFE58 /* small em dash */ && char <= 0xFE5E) /* small right tortoise shell bracket */) &&
!((char >= 0xFE63 /* small hyphen-minus */ && char <= 0xFE66) /* small equals sign */)) {
return true;
}
}
if (unicodeBlockLookup['Unified Canadian Aboriginal Syllabics'](char)) { return true; }
if (unicodeBlockLookup['Unified Canadian Aboriginal Syllabics Extended'](char)) { return true; }
if (unicodeBlockLookup['Vertical Forms'](char)) { return true; }
if (unicodeBlockLookup['Yijing Hexagram Symbols'](char)) { return true; }
if (unicodeBlockLookup['Yi Syllables'](char)) { return true; }
if (unicodeBlockLookup['Yi Radicals'](char)) { return true; }
return false;
}
/**
* Returns true if the given Unicode codepoint identifies a character with
* neutral orientation.
*
* A character has neutral orientation if it may be drawn rotated or unrotated
* when the line is oriented vertically, depending on the orientation of the
* adjacent characters. For example, along a verticlly oriented line, the vulgar
* fraction ½ is drawn upright among Chinese characters but rotated among Latin
* letters. A neutrally oriented character does not influence whether an
* adjacent character is drawn upright or rotated.
* @private
*/
function charHasNeutralVerticalOrientation(char ) {
if (unicodeBlockLookup['Latin-1 Supplement'](char)) {
if (char === 0x00A7 /* section sign */ ||
char === 0x00A9 /* copyright sign */ ||
char === 0x00AE /* registered sign */ ||
char === 0x00B1 /* plus-minus sign */ ||
char === 0x00BC /* vulgar fraction one quarter */ ||
char === 0x00BD /* vulgar fraction one half */ ||
char === 0x00BE /* vulgar fraction three quarters */ ||
char === 0x00D7 /* multiplication sign */ ||
char === 0x00F7 /* division sign */) {
return true;
}
}
if (unicodeBlockLookup['General Punctuation'](char)) {
if (char === 0x2016 /* double vertical line */ ||
char === 0x2020 /* dagger */ ||
char === 0x2021 /* double dagger */ ||
char === 0x2030 /* per mille sign */ ||
char === 0x2031 /* per ten thousand sign */ ||
char === 0x203B /* reference mark */ ||
char === 0x203C /* double exclamation mark */ ||
char === 0x2042 /* asterism */ ||
char === 0x2047 /* double question mark */ ||
char === 0x2048 /* question exclamation mark */ ||
char === 0x2049 /* exclamation question mark */ ||
char === 0x2051 /* two asterisks aligned vertically */) {
return true;
}
}
if (unicodeBlockLookup['Letterlike Symbols'](char)) { return true; }
if (unicodeBlockLookup['Number Forms'](char)) { return true; }
if (unicodeBlockLookup['Miscellaneous Technical'](char)) {
if ((char >= 0x2300 /* diameter sign */ && char <= 0x2307 /* wavy line */) ||
(char >= 0x230C /* bottom right crop */ && char <= 0x231F /* bottom right corner */) ||
(char >= 0x2324 /* up arrowhead between two horizontal bars */ && char <= 0x2328 /* keyboard */) ||
char === 0x232B /* erase to the left */ ||
(char >= 0x237D /* shouldered open box */ && char <= 0x239A /* clear screen symbol */) ||
(char >= 0x23BE /* dentistry symbol light vertical and top right */ && char <= 0x23CD /* square foot */) ||
char === 0x23CF /* eject symbol */ ||
(char >= 0x23D1 /* metrical breve */ && char <= 0x23DB /* fuse */) ||
(char >= 0x23E2 /* white trapezium */ && char <= 0x23FF)) {
return true;
}
}
if (unicodeBlockLookup['Control Pictures'](char) && char !== 0x2423 /* open box */) { return true; }
if (unicodeBlockLookup['Optical Character Recognition'](char)) { return true; }
if (unicodeBlockLookup['Enclosed Alphanumerics'](char)) { return true; }
if (unicodeBlockLookup['Geometric Shapes'](char)) { return true; }
if (unicodeBlockLookup['Miscellaneous Symbols'](char)) {
if (!((char >= 0x261A /* black left pointing index */ && char <= 0x261F) /* white down pointing index */)) {
return true;
}
}
if (unicodeBlockLookup['Miscellaneous Symbols and Arrows'](char)) {
if ((char >= 0x2B12 /* square with top half black */ && char <= 0x2B2F /* white vertical ellipse */) ||
(char >= 0x2B50 /* white medium star */ && char <= 0x2B59 /* heavy circled saltire */) ||
(char >= 0x2BB8 /* upwards white arrow from bar with horizontal bar */ && char <= 0x2BEB)) {
return true;
}
}
if (unicodeBlockLookup['CJK Symbols and Punctuation'](char)) { return true; }
if (unicodeBlockLookup['Katakana'](char)) { return true; }
if (unicodeBlockLookup['Private Use Area'](char)) { return true; }
if (unicodeBlockLookup['CJK Compatibility Forms'](char)) { return true; }
if (unicodeBlockLookup['Small Form Variants'](char)) { return true; }
if (unicodeBlockLookup['Halfwidth and Fullwidth Forms'](char)) { return true; }
if (char === 0x221E /* infinity */ ||
char === 0x2234 /* therefore */ ||
char === 0x2235 /* because */ ||
(char >= 0x2700 /* black safety scissors */ && char <= 0x2767 /* rotated floral heart bullet */) ||
(char >= 0x2776 /* dingbat negative circled digit one */ && char <= 0x2793 /* dingbat negative circled sans-serif number ten */) ||
char === 0xFFFC /* object replacement character */ ||
char === 0xFFFD /* replacement character */) {
return true;
}
return false;
}
/**
* Returns true if the given Unicode codepoint identifies a character with
* rotated orientation.
*
* A character has rotated orientation if it is drawn rotated when the line is
* oriented vertically, even if both adjacent characters are upright. For
* example, a Latin letter is drawn rotated along a vertical line. A rotated
* character causes an adjacent “neutral” character to be drawn rotated as well.
* @private
*/
function charHasRotatedVerticalOrientation(char ) {
return !(charHasUprightVerticalOrientation(char) ||
charHasNeutralVerticalOrientation(char));
}
function charInSupportedScript(char , canRenderRTL ) {
// This is a rough heuristic: whether we "can render" a script
// actually depends on the properties of the font being used
// and whether differences from the ideal rendering are considered
// semantically significant.
// Even in Latin script, we "can't render" combinations such as the fi
// ligature, but we don't consider that semantically significant.
if (!canRenderRTL &&
((char >= 0x0590 && char <= 0x08FF) ||
unicodeBlockLookup['Arabic Presentation Forms-A'](char) ||
unicodeBlockLookup['Arabic Presentation Forms-B'](char))) {
// Main blocks for Hebrew, Arabic, Thaana and other RTL scripts
return false;
}
if ((char >= 0x0900 && char <= 0x0DFF) ||
// Main blocks for Indic scripts and Sinhala
(char >= 0x0F00 && char <= 0x109F) ||
// Main blocks for Tibetan and Myanmar
unicodeBlockLookup['Khmer'](char)) {
// These blocks cover common scripts that require
// complex text shaping, based on unicode script metadata:
// http://www.unicode.org/repos/cldr/trunk/common/properties/scriptMetadata.txt
// where "Web Rank <= 32" "Shaping Required = YES"
return false;
}
return true;
}
function isStringInSupportedScript(chars , canRenderRTL ) {
for (var i = 0, list = chars; i < list.length; i += 1) {
var char = list[i];
if (!charInSupportedScript(char.charCodeAt(0), canRenderRTL)) {
return false;
}
}
return true;
}
//
var pluginRequested = false;
var pluginURL = null;
var foregroundLoadComplete = false;
var evented = new Evented();
var _completionCallback;
var registerForPluginAvailability = function(
callback
) {
if (pluginURL) {
callback({ pluginURL: pluginURL, completionCallback: _completionCallback});
} else {
evented.once('pluginAvailable', callback);
}
return callback;
};
var clearRTLTextPlugin = function() {
pluginRequested = false;
pluginURL = null;
};
var setRTLTextPlugin = function(url , callback ) {
if (pluginRequested) {
throw new Error('setRTLTextPlugin cannot be called multiple times.');
}
pluginRequested = true;
pluginURL = exported.resolveURL(url);
_completionCallback = function (error ) {
if (error) {
// Clear loaded state to allow retries
clearRTLTextPlugin();
if (callback) {
callback(error);
}
} else {
// Called once for each worker
foregroundLoadComplete = true;
}
};
evented.fire(new Event('pluginAvailable', { pluginURL: pluginURL, completionCallback: _completionCallback }));
};
var plugin
= {
applyArabicShaping: null,
processBidirectionalText: null,
processStyledBidirectionalText: null,
isLoaded: function() {
return foregroundLoadComplete || // Foreground: loaded if the completion callback returned successfully
plugin.applyArabicShaping != null; // Background: loaded if the plugin functions have been compiled
}
};
//
var EvaluationParameters = function EvaluationParameters(zoom , options) {
this.zoom = zoom;
if (options) {
this.now = options.now;
this.fadeDuration = options.fadeDuration;
this.zoomHistory = options.zoomHistory;
this.transition = options.transition;
} else {
this.now = 0;
this.fadeDuration = 0;
this.zoomHistory = new ZoomHistory();
this.transition = {};
}
};
EvaluationParameters.prototype.isSupportedScript = function isSupportedScript (str ) {
return isStringInSupportedScript(str, plugin.isLoaded());
};
EvaluationParameters.prototype.crossFadingFactor = function crossFadingFactor () {
if (this.fadeDuration === 0) {
return 1;
} else {
return Math.min((this.now - this.zoomHistory.lastIntegerZoomTime) / this.fadeDuration, 1);
}
};
//
/**
* Implements a number of classes that define state and behavior for paint and layout properties, most
* importantly their respective evaluation chains:
*
* Transitionable paint property value
* → Transitioning paint property value
* → Possibly evaluated paint property value
* → Fully evaluated paint property value
*
* Layout property value
* → Possibly evaluated layout property value
* → Fully evaluated layout property value
*
* @module
* @private
*/
/**
* Implementations of the `Property` interface:
*
* * Hold metadata about a property that's independent of any specific value: stuff like the type of the value,
* the default value, etc. This comes from the style specification JSON.
* * Define behavior that needs to be polymorphic across different properties: "possibly evaluating"
* an input value (see below), and interpolating between two possibly-evaluted values.
*
* The type `T` is the fully-evaluated value type (e.g. `number`, `string`, `Color`).
* The type `R` is the intermediate "possibly evaluated" value type. See below.
*
* There are two main implementations of the interface -- one for properties that allow data-driven values,
* and one for properties that don't. There are a few "special case" implementations as well: one for properties
* which cross-fade between two values rather than interpolating, one for `heatmap-color` and `line-gradient`,
* and one for `light-position`.
*
* @private
*/
/**
* `PropertyValue` represents the value part of a property key-value unit. It's used to represent both
* paint and layout property values, and regardless of whether or not their property supports data-driven
* expressions.
*
* `PropertyValue` stores the raw input value as seen in a style or a runtime styling API call, i.e. one of the
* following:
*
* * A constant value of the type appropriate for the property
* * A function which produces a value of that type (but functions are quasi-deprecated in favor of expressions)
* * An expression which produces a value of that type
* * "undefined"/"not present", in which case the property is assumed to take on its default value.
*
* In addition to storing the original input value, `PropertyValue` also stores a normalized representation,
* effectively treating functions as if they are expressions, and constant or default values as if they are
* (constant) expressions.
*
* @private
*/
var PropertyValue = function PropertyValue(property , value ) {
this.property = property;
this.value = value;
this.expression = normalizePropertyExpression(value === undefined ? property.specification.default : value, property.specification);
};
PropertyValue.prototype.isDataDriven = function isDataDriven () {
return this.expression.kind === 'source' || this.expression.kind === 'composite';
};
PropertyValue.prototype.possiblyEvaluate = function possiblyEvaluate (parameters ) {
return this.property.possiblyEvaluate(this, parameters);
};
// ------- Transitionable -------
/**
* Paint properties are _transitionable_: they can change in a fluid manner, interpolating or cross-fading between
* old and new value. The duration of the transition, and the delay before it begins, is configurable.
*
* `TransitionablePropertyValue` is a compositional class that stores both the property value and that transition
* configuration.
*
* A `TransitionablePropertyValue` can calculate the next step in the evaluation chain for paint property values:
* `TransitioningPropertyValue`.
*
* @private
*/
var TransitionablePropertyValue = function TransitionablePropertyValue(property ) {
this.property = property;
this.value = new PropertyValue(property, undefined);
};
TransitionablePropertyValue.prototype.transitioned = function transitioned (parameters ,
prior ) {
return new TransitioningPropertyValue(this.property, this.value, prior, // eslint-disable-line no-use-before-define
extend({}, parameters.transition, this.transition), parameters.now);
};
TransitionablePropertyValue.prototype.untransitioned = function untransitioned () {
return new TransitioningPropertyValue(this.property, this.value, null, {}, 0); // eslint-disable-line no-use-before-define
};
/**
* A helper type: given an object type `Properties` whose values are each of type `Property<T, R>`, it calculates
* an object type with the same keys and values of type `TransitionablePropertyValue<T, R>`.
*
* @private
*/
/**
* `Transitionable` stores a map of all (property name, `TransitionablePropertyValue`) pairs for paint properties of a
* given layer type. It can calculate the `TransitioningPropertyValue`s for all of them at once, producing a
* `Transitioning` instance for the same set of properties.
*
* @private
*/
var Transitionable = function Transitionable(properties ) {
this._properties = properties;
this._values = (Object.create(properties.defaultTransitionablePropertyValues) );
};
Transitionable.prototype.getValue = function getValue (name ) {
return clone(this._values[name].value.value);
};
Transitionable.prototype.setValue = function setValue (name , value ) {
if (!this._values.hasOwnProperty(name)) {
this._values[name] = new TransitionablePropertyValue(this._values[name].property);
}
// Note that we do not _remove_ an own property in the case where a value is being reset
// to the default: the transition might still be non-default.
this._values[name].value = new PropertyValue(this._values[name].property, value === null ? undefined : clone(value));
};
Transitionable.prototype.getTransition = function getTransition (name ) {
return clone(this._values[name].transition);
};
Transitionable.prototype.setTransition = function setTransition (name , value ) {
if (!this._values.hasOwnProperty(name)) {
this._values[name] = new TransitionablePropertyValue(this._values[name].property);
}
this._values[name].transition = clone(value) || undefined;
};
Transitionable.prototype.serialize = function serialize$$1 () {
var this$1 = this;
var result = {};
for (var i = 0, list = Object.keys(this$1._values); i < list.length; i += 1) {
var property = list[i];
var value = this$1.getValue(property);
if (value !== undefined) {
result[property] = value;
}
var transition = this$1.getTransition(property);
if (transition !== undefined) {
result[(property + "-transition")] = transition;
}
}
return result;
};
Transitionable.prototype.transitioned = function transitioned (parameters , prior ) {
var this$1 = this;
var result = new Transitioning(this._properties); // eslint-disable-line no-use-before-define
for (var i = 0, list = Object.keys(this$1._values); i < list.length; i += 1) {
var property = list[i];
result._values[property] = this$1._values[property].transitioned(parameters, prior._values[property]);
}
return result;
};
Transitionable.prototype.untransitioned = function untransitioned () {
var this$1 = this;
var result = new Transitioning(this._properties); // eslint-disable-line no-use-before-define
for (var i = 0, list = Object.keys(this$1._values); i < list.length; i += 1) {
var property = list[i];
result._values[property] = this$1._values[property].untransitioned();
}
return result;
};
// ------- Transitioning -------
/**
* `TransitioningPropertyValue` implements the first of two intermediate steps in the evaluation chain of a paint
* property value. In this step, transitions between old and new values are handled: as long as the transition is in
* progress, `TransitioningPropertyValue` maintains a reference to the prior value, and interpolates between it and
* the new value based on the current time and the configured transition duration and delay. The product is the next
* step in the evaluation chain: the "possibly evaluated" result type `R`. See below for more on this concept.
*
* @private
*/
var TransitioningPropertyValue = function TransitioningPropertyValue(property ,
value ,
prior ,
transition ,
now ) {
this.property = property;
this.value = value;
this.begin = now + transition.delay || 0;
this.end = this.begin + transition.duration || 0;
if (property.specification.transition && (transition.delay || transition.duration)) {
this.prior = prior;
}
};
TransitioningPropertyValue.prototype.possiblyEvaluate = function possiblyEvaluate (parameters ) {
var now = parameters.now || 0;
var finalValue = this.value.possiblyEvaluate(parameters);
var prior = this.prior;
if (!prior) {
// No prior value.
return finalValue;
} else if (now > this.end) {
// Transition from prior value is now complete.
this.prior = null;
return finalValue;
} else if (this.value.isDataDriven()) {
// Transitions to data-driven properties are not supported.
// We snap immediately to the data-driven value so that, when we perform layout,
// we see the data-driven function and can use it to populate vertex buffers.
this.prior = null;
return finalValue;
} else if (now < this.begin) {
// Transition hasn't started yet.
return prior.possiblyEvaluate(parameters);
} else {
// Interpolate between recursively-calculated prior value and final.
var t = (now - this.begin) / (this.end - this.begin);
return this.property.interpolate(prior.possiblyEvaluate(parameters), finalValue, easeCubicInOut(t));
}
};
/**
* A helper type: given an object type `Properties` whose values are each of type `Property<T, R>`, it calculates
* an object type with the same keys and values of type `TransitioningPropertyValue<T, R>`.
*
* @private
*/
/**
* `Transitioning` stores a map of all (property name, `TransitioningPropertyValue`) pairs for paint properties of a
* given layer type. It can calculate the possibly-evaluated values for all of them at once, producing a
* `PossiblyEvaluated` instance for the same set of properties.
*
* @private
*/
var Transitioning = function Transitioning(properties ) {
this._properties = properties;
this._values = (Object.create(properties.defaultTransitioningPropertyValues) );
};
Transitioning.prototype.possiblyEvaluate = function possiblyEvaluate (parameters ) {
var this$1 = this;
var result = new PossiblyEvaluated(this._properties); // eslint-disable-line no-use-before-define
for (var i = 0, list = Object.keys(this$1._values); i < list.length; i += 1) {
var property = list[i];
result._values[property] = this$1._values[property].possiblyEvaluate(parameters);
}
return result;
};
Transitioning.prototype.hasTransition = function hasTransition () {
var this$1 = this;
for (var i = 0, list = Object.keys(this$1._values); i < list.length; i += 1) {
var property = list[i];
if (this$1._values[property].prior) {
return true;
}
}
return false;
};
// ------- Layout -------
/**
* A helper type: given an object type `Properties` whose values are each of type `Property<T, R>`, it calculates
* an object type with the same keys and values of type `PropertyValue<T, R>`.
*
* @private
*/
/**
* Because layout properties are not transitionable, they have a simpler representation and evaluation chain than
* paint properties: `PropertyValue`s are possibly evaluated, producing possibly evaluated values, which are then
* fully evaluated.
*
* `Layout` stores a map of all (property name, `PropertyValue`) pairs for layout properties of a
* given layer type. It can calculate the possibly-evaluated values for all of them at once, producing a
* `PossiblyEvaluated` instance for the same set of properties.
*
* @private
*/
var Layout = function Layout(properties ) {
this._properties = properties;
this._values = (Object.create(properties.defaultPropertyValues) );
};
Layout.prototype.getValue = function getValue (name ) {
return clone(this._values[name].value);
};
Layout.prototype.setValue = function setValue (name , value ) {
this._values[name] = new PropertyValue(this._values[name].property, value === null ? undefined : clone(value));
};
Layout.prototype.serialize = function serialize$$1 () {
var this$1 = this;
var result = {};
for (var i = 0, list = Object.keys(this$1._values); i < list.length; i += 1) {
var property = list[i];
var value = this$1.getValue(property);
if (value !== undefined) {
result[property] = value;
}
}
return result;
};
Layout.prototype.possiblyEvaluate = function possiblyEvaluate (parameters ) {
var this$1 = this;
var result = new PossiblyEvaluated(this._properties); // eslint-disable-line no-use-before-define
for (var i = 0, list = Object.keys(this$1._values); i < list.length; i += 1) {
var property = list[i];
result._values[property] = this$1._values[property].possiblyEvaluate(parameters);
}
return result;
};
// ------- PossiblyEvaluated -------
/**
* "Possibly evaluated value" is an intermediate stage in the evaluation chain for both paint and layout property
* values. The purpose of this stage is to optimize away unnecessary recalculations for data-driven properties. Code
* which uses data-driven property values must assume that the value is dependent on feature data, and request that it
* be evaluated for each feature. But when that property value is in fact a constant or camera function, the calculation
* will not actually depend on the feature, and we can benefit from returning the prior result of having done the
* evaluation once, ahead of time, in an intermediate step whose inputs are just the value and "global" parameters
* such as current zoom level.
*
* `PossiblyEvaluatedValue` represents the three possible outcomes of this step: if the input value was a constant or
* camera expression, then the "possibly evaluated" result is a constant value. Otherwise, the input value was either
* a source or composite expression, and we must defer final evaluation until supplied a feature. We separate
* the source and composite cases because they are handled differently when generating GL attributes, buffers, and
* uniforms.
*
* Note that `PossiblyEvaluatedValue` (and `PossiblyEvaluatedPropertyValue`, below) are _not_ used for properties that
* do not allow data-driven values. For such properties, we know that the "possibly evaluated" result is always a constant
* scalar value. See below.
*
* @private
*/
/**
* `PossiblyEvaluatedPropertyValue` is used for data-driven paint and layout property values. It holds a
* `PossiblyEvaluatedValue` and the `GlobalProperties` that were used to generate it. You're not allowed to supply
* a different set of `GlobalProperties` when performing the final evaluation because they would be ignored in the
* case where the input value was a constant or camera function.
*
* @private
*/
var PossiblyEvaluatedPropertyValue = function PossiblyEvaluatedPropertyValue(property , value , globals ) {
this.property = property;
this.value = value;
this.globals = globals;
};
PossiblyEvaluatedPropertyValue.prototype.isConstant = function isConstant () {
return this.value.kind === 'constant';
};
PossiblyEvaluatedPropertyValue.prototype.constantOr = function constantOr (value ) {
if (this.value.kind === 'constant') {
return this.value.value;
} else {
return value;
}
};
PossiblyEvaluatedPropertyValue.prototype.evaluate = function evaluate (feature , featureState ) {
return this.property.evaluate(this.value, this.globals, feature, featureState);
};
/**
* A helper type: given an object type `Properties` whose values are each of type `Property<T, R>`, it calculates
* an object type with the same keys, and values of type `R`.
*
* For properties that don't allow data-driven values, `R` is a scalar type such as `number`, `string`, or `Color`.
* For data-driven properties, it is `PossiblyEvaluatedPropertyValue`. Critically, the type definitions are set up
* in a way that allows flow to know which of these two cases applies for any given property name, and if you attempt
* to use a `PossiblyEvaluatedPropertyValue` as if it was a scalar, or vice versa, you will get a type error. (However,
* there's at least one case in which flow fails to produce a type error that you should be aware of: in a context such
* as `layer.paint.get('foo-opacity') === 0`, if `foo-opacity` is data-driven, than the left-hand side is of type
* `PossiblyEvaluatedPropertyValue<number>`, but flow will not complain about comparing this to a number using `===`.
* See https://github.com/facebook/flow/issues/2359.)
*
* There's also a third, special case possiblity for `R`: for cross-faded properties, it's `?CrossFaded<T>`.
*
* @private
*/
/**
* `PossiblyEvaluated` stores a map of all (property name, `R`) pairs for paint or layout properties of a
* given layer type.
* @private
*/
var PossiblyEvaluated = function PossiblyEvaluated(properties ) {
this._properties = properties;
this._values = (Object.create(properties.defaultPossiblyEvaluatedValues) );
};
PossiblyEvaluated.prototype.get = function get (name ) {
return this._values[name];
};
/**
* An implementation of `Property` for properties that do not permit data-driven (source or composite) expressions.
* This restriction allows us to declare statically that the result of possibly evaluating this kind of property
* is in fact always the scalar type `T`, and can be used without further evaluating the value on a per-feature basis.
*
* @private
*/
var DataConstantProperty = function DataConstantProperty(specification ) {
this.specification = specification;
};
DataConstantProperty.prototype.possiblyEvaluate = function possiblyEvaluate (value , parameters ) {
assert_1(!value.isDataDriven());
return value.expression.evaluate(parameters);
};
DataConstantProperty.prototype.interpolate = function interpolate$1 (a , b , t ) {
var interp = (interpolate )[this.specification.type];
if (interp) {
return interp(a, b, t);
} else {
return a;
}
};
/**
* An implementation of `Property` for properties that permit data-driven (source or composite) expressions.
* The result of possibly evaluating this kind of property is `PossiblyEvaluatedPropertyValue<T>`; obtaining
* a scalar value `T` requires further evaluation on a per-feature basis.
*
* @private
*/
var DataDrivenProperty = function DataDrivenProperty(specification ) {
this.specification = specification;
};
DataDrivenProperty.prototype.possiblyEvaluate = function possiblyEvaluate (value , parameters ) {
if (value.expression.kind === 'constant' || value.expression.kind === 'camera') {
return new PossiblyEvaluatedPropertyValue(this, {kind: 'constant', value: value.expression.evaluate(parameters)}, parameters);
} else {
return new PossiblyEvaluatedPropertyValue(this, value.expression, parameters);
}
};
DataDrivenProperty.prototype.interpolate = function interpolate$2 (a ,
b ,
t ) {
// If either possibly-evaluated value is non-constant, give up: we aren't able to interpolate data-driven values.
if (a.value.kind !== 'constant' || b.value.kind !== 'constant') {
return a;
}
// Special case hack solely for fill-outline-color. The undefined value is subsequently handled in
// FillStyleLayer#recalculate, which sets fill-outline-color to the fill-color value if the former
// is a PossiblyEvaluatedPropertyValue containing a constant undefined value. In addition to the
// return value here, the other source of a PossiblyEvaluatedPropertyValue containing a constant
// undefined value is the "default value" for fill-outline-color held in
// `Properties#defaultPossiblyEvaluatedValues`, which serves as the prototype of
// `PossiblyEvaluated#_values`.
if (a.value.value === undefined || b.value.value === undefined) {
return new PossiblyEvaluatedPropertyValue(this, {kind: 'constant', value: (undefined )}, a.globals);
}
var interp = (interpolate )[this.specification.type];
if (interp) {
return new PossiblyEvaluatedPropertyValue(this, {kind: 'constant', value: interp(a.value.value, b.value.value, t)}, a.globals);
} else {
return a;
}
};
DataDrivenProperty.prototype.evaluate = function evaluate (value , globals , feature , featureState ) {
if (value.kind === 'constant') {
return value.value;
} else {
return value.evaluate(globals, feature, featureState);
}
};
/**
* An implementation of `Property` for `*-pattern` and `line-dasharray`, which are transitioned by cross-fading
* rather than interpolation.
*
* @private
*/
var CrossFadedProperty = function CrossFadedProperty(specification ) {
this.specification = specification;
};
CrossFadedProperty.prototype.possiblyEvaluate = function possiblyEvaluate (value , parameters ) {
if (value.value === undefined) {
return undefined;
} else if (value.expression.kind === 'constant') {
var constant = value.expression.evaluate(parameters);
return this._calculate(constant, constant, constant, parameters);
} else {
assert_1(!value.isDataDriven());
return this._calculate(
value.expression.evaluate(new EvaluationParameters(Math.floor(parameters.zoom - 1.0), parameters)),
value.expression.evaluate(new EvaluationParameters(Math.floor(parameters.zoom), parameters)),
value.expression.evaluate(new EvaluationParameters(Math.floor(parameters.zoom + 1.0), parameters)),
parameters);
}
};
CrossFadedProperty.prototype._calculate = function _calculate (min , mid , max , parameters ) {
var z = parameters.zoom;
var fraction = z - Math.floor(z);
var t = parameters.crossFadingFactor();
return z > parameters.zoomHistory.lastIntegerZoom ?
{ from: min, to: mid, fromScale: 2, toScale: 1, t: fraction + (1 - fraction) * t } :
{ from: max, to: mid, fromScale: 0.5, toScale: 1, t: 1 - (1 - t) * fraction };
};
CrossFadedProperty.prototype.interpolate = function interpolate (a ) {
return a;
};
/**
* An implementation of `Property` for `heatmap-color` and `line-gradient`. Interpolation is a no-op, and
* evaluation returns a boolean value in order to indicate its presence, but the real
* evaluation happens in StyleLayer classes.
*
* @private
*/
var ColorRampProperty = function ColorRampProperty(specification ) {
this.specification = specification;
};
ColorRampProperty.prototype.possiblyEvaluate = function possiblyEvaluate (value , parameters ) {
return !!value.expression.evaluate(parameters);
};
ColorRampProperty.prototype.interpolate = function interpolate () { return false; };
/**
* `Properties` holds objects containing default values for the layout or paint property set of a given
* layer type. These objects are immutable, and they are used as the prototypes for the `_values` members of
* `Transitionable`, `Transitioning`, `Layout`, and `PossiblyEvaluated`. This allows these classes to avoid
* doing work in the common case where a property has no explicit value set and should be considered to take
* on the default value: using `for (const property of Object.keys(this._values))`, they can iterate over
* only the _own_ properties of `_values`, skipping repeated calculation of transitions and possible/final
* evaluations for defaults, the result of which will always be the same.
*
* @private
*/
var Properties = function Properties(properties ) {
var this$1 = this;
this.properties = properties;
this.defaultPropertyValues = ({} );
this.defaultTransitionablePropertyValues = ({} );
this.defaultTransitioningPropertyValues = ({} );
this.defaultPossiblyEvaluatedValues = ({} );
for (var property in properties) {
var prop = properties[property];
var defaultPropertyValue = this$1.defaultPropertyValues[property] =
new PropertyValue(prop, undefined);
var defaultTransitionablePropertyValue = this$1.defaultTransitionablePropertyValues[property] =
new TransitionablePropertyValue(prop);
this$1.defaultTransitioningPropertyValues[property] =
defaultTransitionablePropertyValue.untransitioned();
this$1.defaultPossiblyEvaluatedValues[property] =
defaultPropertyValue.possiblyEvaluate(({} ));
}
};
register('DataDrivenProperty', DataDrivenProperty);
register('DataConstantProperty', DataConstantProperty);
register('CrossFadedProperty', CrossFadedProperty);
register('ColorRampProperty', ColorRampProperty);
//
var TRANSITION_SUFFIX = '-transition';
var StyleLayer = (function (Evented$$1) {
function StyleLayer(layer , properties ) {
var this$1 = this;
Evented$$1.call(this);
this.id = layer.id;
this.metadata = layer.metadata;
this.type = layer.type;
this.minzoom = layer.minzoom;
this.maxzoom = layer.maxzoom;
this.visibility = 'visible';
if (layer.type !== 'background') {
this.source = layer.source;
this.sourceLayer = layer['source-layer'];
this.filter = layer.filter;
}
this._featureFilter = function () { return true; };
if (properties.layout) {
this._unevaluatedLayout = new Layout(properties.layout);
}
this._transitionablePaint = new Transitionable(properties.paint);
for (var property in layer.paint) {
this$1.setPaintProperty(property, layer.paint[property], {validate: false});
}
for (var property$1 in layer.layout) {
this$1.setLayoutProperty(property$1, layer.layout[property$1], {validate: false});
}
this._transitioningPaint = this._transitionablePaint.untransitioned();
}
if ( Evented$$1 ) StyleLayer.__proto__ = Evented$$1;
StyleLayer.prototype = Object.create( Evented$$1 && Evented$$1.prototype );
StyleLayer.prototype.constructor = StyleLayer;
StyleLayer.prototype.getLayoutProperty = function getLayoutProperty (name ) {
if (name === 'visibility') {
return this.visibility;
}
return this._unevaluatedLayout.getValue(name);
};
StyleLayer.prototype.setLayoutProperty = function setLayoutProperty (name , value , options ) {
if (value !== null && value !== undefined) {
var key = "layers." + (this.id) + ".layout." + name;
if (this._validate(validateLayoutProperty$1, key, name, value, options)) {
return;
}
}
if (name === 'visibility') {
this.visibility = value === 'none' ? value : 'visible';
return;
}
this._unevaluatedLayout.setValue(name, value);
};
StyleLayer.prototype.getPaintProperty = function getPaintProperty (name ) {
if (endsWith(name, TRANSITION_SUFFIX)) {
return this._transitionablePaint.getTransition(name.slice(0, -TRANSITION_SUFFIX.length));
} else {
return this._transitionablePaint.getValue(name);
}
};
StyleLayer.prototype.setPaintProperty = function setPaintProperty (name , value , options ) {
if (value !== null && value !== undefined) {
var key = "layers." + (this.id) + ".paint." + name;
if (this._validate(validatePaintProperty$1, key, name, value, options)) {
return false;
}
}
if (endsWith(name, TRANSITION_SUFFIX)) {
this._transitionablePaint.setTransition(name.slice(0, -TRANSITION_SUFFIX.length), (value ) || undefined);
return false;
} else {
var wasDataDriven = this._transitionablePaint._values[name].value.isDataDriven();
this._transitionablePaint.setValue(name, value);
var isDataDriven = this._transitionablePaint._values[name].value.isDataDriven();
this._handleSpecialPaintPropertyUpdate(name);
return isDataDriven || wasDataDriven;
}
};
StyleLayer.prototype._handleSpecialPaintPropertyUpdate = function _handleSpecialPaintPropertyUpdate (_ ) {
// No-op; can be overridden by derived classes.
};
StyleLayer.prototype.isHidden = function isHidden (zoom ) {
if (this.minzoom && zoom < this.minzoom) { return true; }
if (this.maxzoom && zoom >= this.maxzoom) { return true; }
return this.visibility === 'none';
};
StyleLayer.prototype.updateTransitions = function updateTransitions (parameters ) {
this._transitioningPaint = this._transitionablePaint.transitioned(parameters, this._transitioningPaint);
};
StyleLayer.prototype.hasTransition = function hasTransition () {
return this._transitioningPaint.hasTransition();
};
StyleLayer.prototype.recalculate = function recalculate (parameters ) {
if (this._unevaluatedLayout) {
(this ).layout = this._unevaluatedLayout.possiblyEvaluate(parameters);
}
(this ).paint = this._transitioningPaint.possiblyEvaluate(parameters);
};
StyleLayer.prototype.serialize = function serialize () {
var output = {
'id': this.id,
'type': this.type,
'source': this.source,
'source-layer': this.sourceLayer,
'metadata': this.metadata,
'minzoom': this.minzoom,
'maxzoom': this.maxzoom,
'filter': this.filter,
'layout': this._unevaluatedLayout && this._unevaluatedLayout.serialize(),
'paint': this._transitionablePaint && this._transitionablePaint.serialize()
};
if (this.visibility === 'none') {
output.layout = output.layout || {};
output.layout.visibility = 'none';
}
return filterObject(output, function (value, key) {
return value !== undefined &&
!(key === 'layout' && !Object.keys(value).length) &&
!(key === 'paint' && !Object.keys(value).length);
});
};
StyleLayer.prototype._validate = function _validate (validate , key , name , value , options ) {
if (options && options.validate === false) {
return false;
}
return emitValidationErrors(this, validate.call(validateStyle, {
key: key,
layerType: this.type,
objectKey: name,
value: value,
styleSpec: styleSpec,
// Workaround for https://github.com/mapbox/mapbox-gl-js/issues/2407
style: {glyphs: true, sprite: true}
}));
};
StyleLayer.prototype.hasOffscreenPass = function hasOffscreenPass () {
return false;
};
StyleLayer.prototype.resize = function resize () {
// noop
};
StyleLayer.prototype.isStateDependent = function isStateDependent () {
var this$1 = this;
for (var property in (this$1 ).paint._values) {
var value = (this$1 ).paint.get(property);
if (!(value instanceof PossiblyEvaluatedPropertyValue) || !supportsPropertyExpression(value.property.specification)) {
continue;
}
if ((value.value.kind === 'source' || value.value.kind === 'composite') &&
value.value.isStateDependent) {
return true;
}
}
return false;
};
return StyleLayer;
}(Evented));
//
var viewTypes = {
'Int8': Int8Array,
'Uint8': Uint8Array,
'Int16': Int16Array,
'Uint16': Uint16Array,
'Int32': Int32Array,
'Uint32': Uint32Array,
'Float32': Float32Array
};
/**
* @private
*/
var Struct = function Struct(structArray , index ) {
(this )._structArray = structArray;
this._pos1 = index * this.size;
this._pos2 = this._pos1 / 2;
this._pos4 = this._pos1 / 4;
this._pos8 = this._pos1 / 8;
};
var DEFAULT_CAPACITY = 128;
var RESIZE_MULTIPLIER = 5;
/**
* `StructArray` provides an abstraction over `ArrayBuffer` and `TypedArray`
* making it behave like an array of typed structs.
*
* Conceptually, a StructArray is comprised of elements, i.e., instances of its
* associated struct type. Each particular struct type, together with an
* alignment size, determines the memory layout of a StructArray whose elements
* are of that type. Thus, for each such layout that we need, we have
* a corrseponding StructArrayLayout class, inheriting from StructArray and
* implementing `emplaceBack()` and `_refreshViews()`.
*
* In some cases, where we need to access particular elements of a StructArray,
* we implement a more specific subclass that inherits from one of the
* StructArrayLayouts and adds a `get(i): T` accessor that returns a structured
* object whose properties are proxies into the underlying memory space for the
* i-th element. This affords the convience of working with (seemingly) plain
* Javascript objects without the overhead of serializing/deserializing them
* into ArrayBuffers for efficient web worker transfer.
*
* @private
*/
var StructArray = function StructArray() {
this.isTransferred = false;
this.capacity = -1;
this.resize(0);
};
/**
* Serialize a StructArray instance.Serializes both the raw data and the
* metadata needed to reconstruct the StructArray base class during
* deserialization.
*/
StructArray.serialize = function serialize (array , transferables ) {
assert_1(!array.isTransferred);
array._trim();
if (transferables) {
array.isTransferred = true;
transferables.push(array.arrayBuffer);
}
return {
length: array.length,
arrayBuffer: array.arrayBuffer,
};
};
StructArray.deserialize = function deserialize (input ) {
var structArray = Object.create(this.prototype);
structArray.arrayBuffer = input.arrayBuffer;
structArray.length = input.length;
structArray.capacity = input.arrayBuffer.byteLength / structArray.bytesPerElement;
structArray._refreshViews();
return structArray;
};
/**
* Resize the array to discard unused capacity.
*/
StructArray.prototype._trim = function _trim () {
if (this.length !== this.capacity) {
this.capacity = this.length;
this.arrayBuffer = this.arrayBuffer.slice(0, this.length * this.bytesPerElement);
this._refreshViews();
}
};
/**
* Resets the the length of the array to 0 without de-allocating capcacity.
*/
StructArray.prototype.clear = function clear () {
this.length = 0;
};
/**
* Resize the array.
* If `n` is greater than the current length then additional elements with undefined values are added.
* If `n` is less than the current length then the array will be reduced to the first `n` elements.
* @param {number} n The new size of the array.
*/
StructArray.prototype.resize = function resize (n ) {
assert_1(!this.isTransferred);
this.reserve(n);
this.length = n;
};
/**
* Indicate a planned increase in size, so that any necessary allocation may
* be done once, ahead of time.
* @param {number} n The expected size of the array.
*/
StructArray.prototype.reserve = function reserve (n ) {
if (n > this.capacity) {
this.capacity = Math.max(n, Math.floor(this.capacity * RESIZE_MULTIPLIER), DEFAULT_CAPACITY);
this.arrayBuffer = new ArrayBuffer(this.capacity * this.bytesPerElement);
var oldUint8Array = this.uint8;
this._refreshViews();
if (oldUint8Array) { this.uint8.set(oldUint8Array); }
}
};
/**
* Create TypedArray views for the current ArrayBuffer.
*/
StructArray.prototype._refreshViews = function _refreshViews () {
throw new Error('_refreshViews() must be implemented by each concrete StructArray layout');
};
/**
* Given a list of member fields, create a full StructArrayLayout, in
* particular calculating the correct byte offset for each field. This data
* is used at build time to generate StructArrayLayout_*#emplaceBack() and
* other accessors, and at runtime for binding vertex buffer attributes.
*
* @private
*/
function createLayout(
members ,
alignment
) {
if ( alignment === void 0 ) alignment = 1;
var offset = 0;
var maxSize = 0;
var layoutMembers = members.map(function (member) {
assert_1(member.name.length);
var typeSize = sizeOf(member.type);
var memberOffset = offset = align(offset, Math.max(alignment, typeSize));
var components = member.components || 1;
maxSize = Math.max(maxSize, typeSize);
offset += typeSize * components;
return {
name: member.name,
type: member.type,
components: components,
offset: memberOffset,
};
});
var size = align(offset, Math.max(maxSize, alignment));
return {
members: layoutMembers,
size: size,
alignment: alignment
};
}
function sizeOf(type ) {
return viewTypes[type].BYTES_PER_ELEMENT;
}
function align(offset , size ) {
return Math.ceil(offset / size) * size;
}
// This file is generated. Edit build/generate-struct-arrays.js, then run `yarn run codegen`.
/**
* Implementation of the StructArray layout:
* [0]: Int16[2]
*
* @private
*/
var StructArrayLayout2i4 = (function (StructArray$$1) {
function StructArrayLayout2i4 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout2i4.__proto__ = StructArray$$1;
StructArrayLayout2i4.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout2i4.prototype.constructor = StructArrayLayout2i4;
StructArrayLayout2i4.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.int16 = new Int16Array(this.arrayBuffer);
};
StructArrayLayout2i4.prototype.emplaceBack = function emplaceBack (v0 , v1 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 2;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
return i;
};
StructArrayLayout2i4.prototype.emplace = function emplace (i , v0 , v1 ) {
var o2 = i * 2;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
return i;
};
return StructArrayLayout2i4;
}(StructArray));
StructArrayLayout2i4.prototype.bytesPerElement = 4;
register('StructArrayLayout2i4', StructArrayLayout2i4);
/**
* Implementation of the StructArray layout:
* [0]: Int16[4]
*
* @private
*/
var StructArrayLayout4i8 = (function (StructArray$$1) {
function StructArrayLayout4i8 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout4i8.__proto__ = StructArray$$1;
StructArrayLayout4i8.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout4i8.prototype.constructor = StructArrayLayout4i8;
StructArrayLayout4i8.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.int16 = new Int16Array(this.arrayBuffer);
};
StructArrayLayout4i8.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 , v3 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 4;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
return i;
};
StructArrayLayout4i8.prototype.emplace = function emplace (i , v0 , v1 , v2 , v3 ) {
var o2 = i * 4;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
return i;
};
return StructArrayLayout4i8;
}(StructArray));
StructArrayLayout4i8.prototype.bytesPerElement = 8;
register('StructArrayLayout4i8', StructArrayLayout4i8);
/**
* Implementation of the StructArray layout:
* [0]: Int16[2]
* [4]: Int16[4]
*
* @private
*/
var StructArrayLayout2i4i12 = (function (StructArray$$1) {
function StructArrayLayout2i4i12 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout2i4i12.__proto__ = StructArray$$1;
StructArrayLayout2i4i12.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout2i4i12.prototype.constructor = StructArrayLayout2i4i12;
StructArrayLayout2i4i12.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.int16 = new Int16Array(this.arrayBuffer);
};
StructArrayLayout2i4i12.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 , v3 , v4 , v5 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 6;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.int16[o2 + 4] = v4;
this.int16[o2 + 5] = v5;
return i;
};
StructArrayLayout2i4i12.prototype.emplace = function emplace (i , v0 , v1 , v2 , v3 , v4 , v5 ) {
var o2 = i * 6;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.int16[o2 + 4] = v4;
this.int16[o2 + 5] = v5;
return i;
};
return StructArrayLayout2i4i12;
}(StructArray));
StructArrayLayout2i4i12.prototype.bytesPerElement = 12;
register('StructArrayLayout2i4i12', StructArrayLayout2i4i12);
/**
* Implementation of the StructArray layout:
* [0]: Int16[4]
* [8]: Uint8[4]
*
* @private
*/
var StructArrayLayout4i4ub12 = (function (StructArray$$1) {
function StructArrayLayout4i4ub12 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout4i4ub12.__proto__ = StructArray$$1;
StructArrayLayout4i4ub12.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout4i4ub12.prototype.constructor = StructArrayLayout4i4ub12;
StructArrayLayout4i4ub12.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.int16 = new Int16Array(this.arrayBuffer);
};
StructArrayLayout4i4ub12.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 , v3 , v4 , v5 , v6 , v7 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 6;
var o1 = i * 12;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.uint8[o1 + 8] = v4;
this.uint8[o1 + 9] = v5;
this.uint8[o1 + 10] = v6;
this.uint8[o1 + 11] = v7;
return i;
};
StructArrayLayout4i4ub12.prototype.emplace = function emplace (i , v0 , v1 , v2 , v3 , v4 , v5 , v6 , v7 ) {
var o2 = i * 6;
var o1 = i * 12;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.uint8[o1 + 8] = v4;
this.uint8[o1 + 9] = v5;
this.uint8[o1 + 10] = v6;
this.uint8[o1 + 11] = v7;
return i;
};
return StructArrayLayout4i4ub12;
}(StructArray));
StructArrayLayout4i4ub12.prototype.bytesPerElement = 12;
register('StructArrayLayout4i4ub12', StructArrayLayout4i4ub12);
/**
* Implementation of the StructArray layout:
* [0]: Int16[4]
* [8]: Uint16[4]
*
* @private
*/
var StructArrayLayout4i4ui16 = (function (StructArray$$1) {
function StructArrayLayout4i4ui16 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout4i4ui16.__proto__ = StructArray$$1;
StructArrayLayout4i4ui16.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout4i4ui16.prototype.constructor = StructArrayLayout4i4ui16;
StructArrayLayout4i4ui16.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.int16 = new Int16Array(this.arrayBuffer);
this.uint16 = new Uint16Array(this.arrayBuffer);
};
StructArrayLayout4i4ui16.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 , v3 , v4 , v5 , v6 , v7 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 8;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.uint16[o2 + 4] = v4;
this.uint16[o2 + 5] = v5;
this.uint16[o2 + 6] = v6;
this.uint16[o2 + 7] = v7;
return i;
};
StructArrayLayout4i4ui16.prototype.emplace = function emplace (i , v0 , v1 , v2 , v3 , v4 , v5 , v6 , v7 ) {
var o2 = i * 8;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.uint16[o2 + 4] = v4;
this.uint16[o2 + 5] = v5;
this.uint16[o2 + 6] = v6;
this.uint16[o2 + 7] = v7;
return i;
};
return StructArrayLayout4i4ui16;
}(StructArray));
StructArrayLayout4i4ui16.prototype.bytesPerElement = 16;
register('StructArrayLayout4i4ui16', StructArrayLayout4i4ui16);
/**
* Implementation of the StructArray layout:
* [0]: Float32[3]
*
* @private
*/
var StructArrayLayout3f12 = (function (StructArray$$1) {
function StructArrayLayout3f12 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout3f12.__proto__ = StructArray$$1;
StructArrayLayout3f12.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout3f12.prototype.constructor = StructArrayLayout3f12;
StructArrayLayout3f12.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.float32 = new Float32Array(this.arrayBuffer);
};
StructArrayLayout3f12.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 ) {
var i = this.length;
this.resize(i + 1);
var o4 = i * 3;
this.float32[o4 + 0] = v0;
this.float32[o4 + 1] = v1;
this.float32[o4 + 2] = v2;
return i;
};
StructArrayLayout3f12.prototype.emplace = function emplace (i , v0 , v1 , v2 ) {
var o4 = i * 3;
this.float32[o4 + 0] = v0;
this.float32[o4 + 1] = v1;
this.float32[o4 + 2] = v2;
return i;
};
return StructArrayLayout3f12;
}(StructArray));
StructArrayLayout3f12.prototype.bytesPerElement = 12;
register('StructArrayLayout3f12', StructArrayLayout3f12);
/**
* Implementation of the StructArray layout:
* [0]: Uint32[1]
*
* @private
*/
var StructArrayLayout1ul4 = (function (StructArray$$1) {
function StructArrayLayout1ul4 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout1ul4.__proto__ = StructArray$$1;
StructArrayLayout1ul4.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout1ul4.prototype.constructor = StructArrayLayout1ul4;
StructArrayLayout1ul4.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.uint32 = new Uint32Array(this.arrayBuffer);
};
StructArrayLayout1ul4.prototype.emplaceBack = function emplaceBack (v0 ) {
var i = this.length;
this.resize(i + 1);
var o4 = i * 1;
this.uint32[o4 + 0] = v0;
return i;
};
StructArrayLayout1ul4.prototype.emplace = function emplace (i , v0 ) {
var o4 = i * 1;
this.uint32[o4 + 0] = v0;
return i;
};
return StructArrayLayout1ul4;
}(StructArray));
StructArrayLayout1ul4.prototype.bytesPerElement = 4;
register('StructArrayLayout1ul4', StructArrayLayout1ul4);
/**
* Implementation of the StructArray layout:
* [0]: Int16[6]
* [12]: Uint32[1]
* [16]: Uint16[2]
* [20]: Int16[2]
*
* @private
*/
var StructArrayLayout6i1ul2ui2i24 = (function (StructArray$$1) {
function StructArrayLayout6i1ul2ui2i24 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout6i1ul2ui2i24.__proto__ = StructArray$$1;
StructArrayLayout6i1ul2ui2i24.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout6i1ul2ui2i24.prototype.constructor = StructArrayLayout6i1ul2ui2i24;
StructArrayLayout6i1ul2ui2i24.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.int16 = new Int16Array(this.arrayBuffer);
this.uint32 = new Uint32Array(this.arrayBuffer);
this.uint16 = new Uint16Array(this.arrayBuffer);
};
StructArrayLayout6i1ul2ui2i24.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 , v3 , v4 , v5 , v6 , v7 , v8 , v9 , v10 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 12;
var o4 = i * 6;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.int16[o2 + 4] = v4;
this.int16[o2 + 5] = v5;
this.uint32[o4 + 3] = v6;
this.uint16[o2 + 8] = v7;
this.uint16[o2 + 9] = v8;
this.int16[o2 + 10] = v9;
this.int16[o2 + 11] = v10;
return i;
};
StructArrayLayout6i1ul2ui2i24.prototype.emplace = function emplace (i , v0 , v1 , v2 , v3 , v4 , v5 , v6 , v7 , v8 , v9 , v10 ) {
var o2 = i * 12;
var o4 = i * 6;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.int16[o2 + 4] = v4;
this.int16[o2 + 5] = v5;
this.uint32[o4 + 3] = v6;
this.uint16[o2 + 8] = v7;
this.uint16[o2 + 9] = v8;
this.int16[o2 + 10] = v9;
this.int16[o2 + 11] = v10;
return i;
};
return StructArrayLayout6i1ul2ui2i24;
}(StructArray));
StructArrayLayout6i1ul2ui2i24.prototype.bytesPerElement = 24;
register('StructArrayLayout6i1ul2ui2i24', StructArrayLayout6i1ul2ui2i24);
/**
* Implementation of the StructArray layout:
* [0]: Int16[2]
* [4]: Int16[2]
* [8]: Int16[2]
*
* @private
*/
var StructArrayLayout2i2i2i12 = (function (StructArray$$1) {
function StructArrayLayout2i2i2i12 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout2i2i2i12.__proto__ = StructArray$$1;
StructArrayLayout2i2i2i12.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout2i2i2i12.prototype.constructor = StructArrayLayout2i2i2i12;
StructArrayLayout2i2i2i12.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.int16 = new Int16Array(this.arrayBuffer);
};
StructArrayLayout2i2i2i12.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 , v3 , v4 , v5 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 6;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.int16[o2 + 4] = v4;
this.int16[o2 + 5] = v5;
return i;
};
StructArrayLayout2i2i2i12.prototype.emplace = function emplace (i , v0 , v1 , v2 , v3 , v4 , v5 ) {
var o2 = i * 6;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.int16[o2 + 4] = v4;
this.int16[o2 + 5] = v5;
return i;
};
return StructArrayLayout2i2i2i12;
}(StructArray));
StructArrayLayout2i2i2i12.prototype.bytesPerElement = 12;
register('StructArrayLayout2i2i2i12', StructArrayLayout2i2i2i12);
/**
* Implementation of the StructArray layout:
* [0]: Uint8[2]
*
* @private
*/
var StructArrayLayout2ub4 = (function (StructArray$$1) {
function StructArrayLayout2ub4 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout2ub4.__proto__ = StructArray$$1;
StructArrayLayout2ub4.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout2ub4.prototype.constructor = StructArrayLayout2ub4;
StructArrayLayout2ub4.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
};
StructArrayLayout2ub4.prototype.emplaceBack = function emplaceBack (v0 , v1 ) {
var i = this.length;
this.resize(i + 1);
var o1 = i * 4;
this.uint8[o1 + 0] = v0;
this.uint8[o1 + 1] = v1;
return i;
};
StructArrayLayout2ub4.prototype.emplace = function emplace (i , v0 , v1 ) {
var o1 = i * 4;
this.uint8[o1 + 0] = v0;
this.uint8[o1 + 1] = v1;
return i;
};
return StructArrayLayout2ub4;
}(StructArray));
StructArrayLayout2ub4.prototype.bytesPerElement = 4;
register('StructArrayLayout2ub4', StructArrayLayout2ub4);
/**
* Implementation of the StructArray layout:
* [0]: Int16[2]
* [4]: Uint16[2]
* [8]: Uint32[3]
* [20]: Uint16[3]
* [28]: Float32[2]
* [36]: Uint8[2]
*
* @private
*/
var StructArrayLayout2i2ui3ul3ui2f2ub40 = (function (StructArray$$1) {
function StructArrayLayout2i2ui3ul3ui2f2ub40 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout2i2ui3ul3ui2f2ub40.__proto__ = StructArray$$1;
StructArrayLayout2i2ui3ul3ui2f2ub40.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout2i2ui3ul3ui2f2ub40.prototype.constructor = StructArrayLayout2i2ui3ul3ui2f2ub40;
StructArrayLayout2i2ui3ul3ui2f2ub40.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.int16 = new Int16Array(this.arrayBuffer);
this.uint16 = new Uint16Array(this.arrayBuffer);
this.uint32 = new Uint32Array(this.arrayBuffer);
this.float32 = new Float32Array(this.arrayBuffer);
};
StructArrayLayout2i2ui3ul3ui2f2ub40.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 , v3 , v4 , v5 , v6 , v7 , v8 , v9 , v10 , v11 , v12 , v13 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 20;
var o4 = i * 10;
var o1 = i * 40;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.uint16[o2 + 2] = v2;
this.uint16[o2 + 3] = v3;
this.uint32[o4 + 2] = v4;
this.uint32[o4 + 3] = v5;
this.uint32[o4 + 4] = v6;
this.uint16[o2 + 10] = v7;
this.uint16[o2 + 11] = v8;
this.uint16[o2 + 12] = v9;
this.float32[o4 + 7] = v10;
this.float32[o4 + 8] = v11;
this.uint8[o1 + 36] = v12;
this.uint8[o1 + 37] = v13;
return i;
};
StructArrayLayout2i2ui3ul3ui2f2ub40.prototype.emplace = function emplace (i , v0 , v1 , v2 , v3 , v4 , v5 , v6 , v7 , v8 , v9 , v10 , v11 , v12 , v13 ) {
var o2 = i * 20;
var o4 = i * 10;
var o1 = i * 40;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.uint16[o2 + 2] = v2;
this.uint16[o2 + 3] = v3;
this.uint32[o4 + 2] = v4;
this.uint32[o4 + 3] = v5;
this.uint32[o4 + 4] = v6;
this.uint16[o2 + 10] = v7;
this.uint16[o2 + 11] = v8;
this.uint16[o2 + 12] = v9;
this.float32[o4 + 7] = v10;
this.float32[o4 + 8] = v11;
this.uint8[o1 + 36] = v12;
this.uint8[o1 + 37] = v13;
return i;
};
return StructArrayLayout2i2ui3ul3ui2f2ub40;
}(StructArray));
StructArrayLayout2i2ui3ul3ui2f2ub40.prototype.bytesPerElement = 40;
register('StructArrayLayout2i2ui3ul3ui2f2ub40', StructArrayLayout2i2ui3ul3ui2f2ub40);
/**
* Implementation of the StructArray layout:
* [0]: Float32[1]
*
* @private
*/
var StructArrayLayout1f4 = (function (StructArray$$1) {
function StructArrayLayout1f4 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout1f4.__proto__ = StructArray$$1;
StructArrayLayout1f4.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout1f4.prototype.constructor = StructArrayLayout1f4;
StructArrayLayout1f4.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.float32 = new Float32Array(this.arrayBuffer);
};
StructArrayLayout1f4.prototype.emplaceBack = function emplaceBack (v0 ) {
var i = this.length;
this.resize(i + 1);
var o4 = i * 1;
this.float32[o4 + 0] = v0;
return i;
};
StructArrayLayout1f4.prototype.emplace = function emplace (i , v0 ) {
var o4 = i * 1;
this.float32[o4 + 0] = v0;
return i;
};
return StructArrayLayout1f4;
}(StructArray));
StructArrayLayout1f4.prototype.bytesPerElement = 4;
register('StructArrayLayout1f4', StructArrayLayout1f4);
/**
* Implementation of the StructArray layout:
* [0]: Int16[3]
*
* @private
*/
var StructArrayLayout3i6 = (function (StructArray$$1) {
function StructArrayLayout3i6 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout3i6.__proto__ = StructArray$$1;
StructArrayLayout3i6.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout3i6.prototype.constructor = StructArrayLayout3i6;
StructArrayLayout3i6.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.int16 = new Int16Array(this.arrayBuffer);
};
StructArrayLayout3i6.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 3;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
return i;
};
StructArrayLayout3i6.prototype.emplace = function emplace (i , v0 , v1 , v2 ) {
var o2 = i * 3;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
return i;
};
return StructArrayLayout3i6;
}(StructArray));
StructArrayLayout3i6.prototype.bytesPerElement = 6;
register('StructArrayLayout3i6', StructArrayLayout3i6);
/**
* Implementation of the StructArray layout:
* [0]: Uint32[1]
* [4]: Uint16[2]
*
* @private
*/
var StructArrayLayout1ul2ui8 = (function (StructArray$$1) {
function StructArrayLayout1ul2ui8 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout1ul2ui8.__proto__ = StructArray$$1;
StructArrayLayout1ul2ui8.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout1ul2ui8.prototype.constructor = StructArrayLayout1ul2ui8;
StructArrayLayout1ul2ui8.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.uint32 = new Uint32Array(this.arrayBuffer);
this.uint16 = new Uint16Array(this.arrayBuffer);
};
StructArrayLayout1ul2ui8.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 ) {
var i = this.length;
this.resize(i + 1);
var o4 = i * 2;
var o2 = i * 4;
this.uint32[o4 + 0] = v0;
this.uint16[o2 + 2] = v1;
this.uint16[o2 + 3] = v2;
return i;
};
StructArrayLayout1ul2ui8.prototype.emplace = function emplace (i , v0 , v1 , v2 ) {
var o4 = i * 2;
var o2 = i * 4;
this.uint32[o4 + 0] = v0;
this.uint16[o2 + 2] = v1;
this.uint16[o2 + 3] = v2;
return i;
};
return StructArrayLayout1ul2ui8;
}(StructArray));
StructArrayLayout1ul2ui8.prototype.bytesPerElement = 8;
register('StructArrayLayout1ul2ui8', StructArrayLayout1ul2ui8);
/**
* Implementation of the StructArray layout:
* [0]: Uint16[3]
*
* @private
*/
var StructArrayLayout3ui6 = (function (StructArray$$1) {
function StructArrayLayout3ui6 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout3ui6.__proto__ = StructArray$$1;
StructArrayLayout3ui6.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout3ui6.prototype.constructor = StructArrayLayout3ui6;
StructArrayLayout3ui6.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.uint16 = new Uint16Array(this.arrayBuffer);
};
StructArrayLayout3ui6.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 3;
this.uint16[o2 + 0] = v0;
this.uint16[o2 + 1] = v1;
this.uint16[o2 + 2] = v2;
return i;
};
StructArrayLayout3ui6.prototype.emplace = function emplace (i , v0 , v1 , v2 ) {
var o2 = i * 3;
this.uint16[o2 + 0] = v0;
this.uint16[o2 + 1] = v1;
this.uint16[o2 + 2] = v2;
return i;
};
return StructArrayLayout3ui6;
}(StructArray));
StructArrayLayout3ui6.prototype.bytesPerElement = 6;
register('StructArrayLayout3ui6', StructArrayLayout3ui6);
/**
* Implementation of the StructArray layout:
* [0]: Uint16[2]
*
* @private
*/
var StructArrayLayout2ui4 = (function (StructArray$$1) {
function StructArrayLayout2ui4 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout2ui4.__proto__ = StructArray$$1;
StructArrayLayout2ui4.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout2ui4.prototype.constructor = StructArrayLayout2ui4;
StructArrayLayout2ui4.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.uint16 = new Uint16Array(this.arrayBuffer);
};
StructArrayLayout2ui4.prototype.emplaceBack = function emplaceBack (v0 , v1 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 2;
this.uint16[o2 + 0] = v0;
this.uint16[o2 + 1] = v1;
return i;
};
StructArrayLayout2ui4.prototype.emplace = function emplace (i , v0 , v1 ) {
var o2 = i * 2;
this.uint16[o2 + 0] = v0;
this.uint16[o2 + 1] = v1;
return i;
};
return StructArrayLayout2ui4;
}(StructArray));
StructArrayLayout2ui4.prototype.bytesPerElement = 4;
register('StructArrayLayout2ui4', StructArrayLayout2ui4);
/**
* Implementation of the StructArray layout:
* [0]: Uint16[1]
*
* @private
*/
var StructArrayLayout1ui2 = (function (StructArray$$1) {
function StructArrayLayout1ui2 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout1ui2.__proto__ = StructArray$$1;
StructArrayLayout1ui2.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout1ui2.prototype.constructor = StructArrayLayout1ui2;
StructArrayLayout1ui2.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.uint16 = new Uint16Array(this.arrayBuffer);
};
StructArrayLayout1ui2.prototype.emplaceBack = function emplaceBack (v0 ) {
var i = this.length;
this.resize(i + 1);
var o2 = i * 1;
this.uint16[o2 + 0] = v0;
return i;
};
return StructArrayLayout1ui2;
}(StructArray));
StructArrayLayout1ui2.prototype.bytesPerElement = 2;
register('StructArrayLayout1ui2', StructArrayLayout1ui2);
/**
* Implementation of the StructArray layout:
* [0]: Float32[2]
*
* @private
*/
var StructArrayLayout2f8 = (function (StructArray$$1) {
function StructArrayLayout2f8 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout2f8.__proto__ = StructArray$$1;
StructArrayLayout2f8.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout2f8.prototype.constructor = StructArrayLayout2f8;
StructArrayLayout2f8.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.float32 = new Float32Array(this.arrayBuffer);
};
StructArrayLayout2f8.prototype.emplaceBack = function emplaceBack (v0 , v1 ) {
var i = this.length;
this.resize(i + 1);
var o4 = i * 2;
this.float32[o4 + 0] = v0;
this.float32[o4 + 1] = v1;
return i;
};
StructArrayLayout2f8.prototype.emplace = function emplace (i , v0 , v1 ) {
var o4 = i * 2;
this.float32[o4 + 0] = v0;
this.float32[o4 + 1] = v1;
return i;
};
return StructArrayLayout2f8;
}(StructArray));
StructArrayLayout2f8.prototype.bytesPerElement = 8;
register('StructArrayLayout2f8', StructArrayLayout2f8);
/**
* Implementation of the StructArray layout:
* [0]: Float32[4]
*
* @private
*/
var StructArrayLayout4f16 = (function (StructArray$$1) {
function StructArrayLayout4f16 () {
StructArray$$1.apply(this, arguments);
}
if ( StructArray$$1 ) StructArrayLayout4f16.__proto__ = StructArray$$1;
StructArrayLayout4f16.prototype = Object.create( StructArray$$1 && StructArray$$1.prototype );
StructArrayLayout4f16.prototype.constructor = StructArrayLayout4f16;
StructArrayLayout4f16.prototype._refreshViews = function _refreshViews () {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.float32 = new Float32Array(this.arrayBuffer);
};
StructArrayLayout4f16.prototype.emplaceBack = function emplaceBack (v0 , v1 , v2 , v3 ) {
var i = this.length;
this.resize(i + 1);
var o4 = i * 4;
this.float32[o4 + 0] = v0;
this.float32[o4 + 1] = v1;
this.float32[o4 + 2] = v2;
this.float32[o4 + 3] = v3;
return i;
};
StructArrayLayout4f16.prototype.emplace = function emplace (i , v0 , v1 , v2 , v3 ) {
var o4 = i * 4;
this.float32[o4 + 0] = v0;
this.float32[o4 + 1] = v1;
this.float32[o4 + 2] = v2;
this.float32[o4 + 3] = v3;
return i;
};
return StructArrayLayout4f16;
}(StructArray));
StructArrayLayout4f16.prototype.bytesPerElement = 16;
register('StructArrayLayout4f16', StructArrayLayout4f16);
var CollisionBoxStruct = (function (Struct$$1) {
function CollisionBoxStruct () {
Struct$$1.apply(this, arguments);
}
if ( Struct$$1 ) CollisionBoxStruct.__proto__ = Struct$$1;
CollisionBoxStruct.prototype = Object.create( Struct$$1 && Struct$$1.prototype );
CollisionBoxStruct.prototype.constructor = CollisionBoxStruct;
var prototypeAccessors = { anchorPointX: { configurable: true },anchorPointY: { configurable: true },x1: { configurable: true },y1: { configurable: true },x2: { configurable: true },y2: { configurable: true },featureIndex: { configurable: true },sourceLayerIndex: { configurable: true },bucketIndex: { configurable: true },radius: { configurable: true },signedDistanceFromAnchor: { configurable: true },anchorPoint: { configurable: true } };
prototypeAccessors.anchorPointX.get = function () { return this._structArray.int16[this._pos2 + 0]; };
prototypeAccessors.anchorPointX.set = function (x) { this._structArray.int16[this._pos2 + 0] = x; };
prototypeAccessors.anchorPointY.get = function () { return this._structArray.int16[this._pos2 + 1]; };
prototypeAccessors.anchorPointY.set = function (x) { this._structArray.int16[this._pos2 + 1] = x; };
prototypeAccessors.x1.get = function () { return this._structArray.int16[this._pos2 + 2]; };
prototypeAccessors.x1.set = function (x) { this._structArray.int16[this._pos2 + 2] = x; };
prototypeAccessors.y1.get = function () { return this._structArray.int16[this._pos2 + 3]; };
prototypeAccessors.y1.set = function (x) { this._structArray.int16[this._pos2 + 3] = x; };
prototypeAccessors.x2.get = function () { return this._structArray.int16[this._pos2 + 4]; };
prototypeAccessors.x2.set = function (x) { this._structArray.int16[this._pos2 + 4] = x; };
prototypeAccessors.y2.get = function () { return this._structArray.int16[this._pos2 + 5]; };
prototypeAccessors.y2.set = function (x) { this._structArray.int16[this._pos2 + 5] = x; };
prototypeAccessors.featureIndex.get = function () { return this._structArray.uint32[this._pos4 + 3]; };
prototypeAccessors.featureIndex.set = function (x) { this._structArray.uint32[this._pos4 + 3] = x; };
prototypeAccessors.sourceLayerIndex.get = function () { return this._structArray.uint16[this._pos2 + 8]; };
prototypeAccessors.sourceLayerIndex.set = function (x) { this._structArray.uint16[this._pos2 + 8] = x; };
prototypeAccessors.bucketIndex.get = function () { return this._structArray.uint16[this._pos2 + 9]; };
prototypeAccessors.bucketIndex.set = function (x) { this._structArray.uint16[this._pos2 + 9] = x; };
prototypeAccessors.radius.get = function () { return this._structArray.int16[this._pos2 + 10]; };
prototypeAccessors.radius.set = function (x) { this._structArray.int16[this._pos2 + 10] = x; };
prototypeAccessors.signedDistanceFromAnchor.get = function () { return this._structArray.int16[this._pos2 + 11]; };
prototypeAccessors.signedDistanceFromAnchor.set = function (x) { this._structArray.int16[this._pos2 + 11] = x; };
prototypeAccessors.anchorPoint.get = function () { return new pointGeometry(this.anchorPointX, this.anchorPointY); };
Object.defineProperties( CollisionBoxStruct.prototype, prototypeAccessors );
return CollisionBoxStruct;
}(Struct));
CollisionBoxStruct.prototype.size = 24;
/**
* @private
*/
var CollisionBoxArray = (function (StructArrayLayout6i1ul2ui2i24) {
function CollisionBoxArray () {
StructArrayLayout6i1ul2ui2i24.apply(this, arguments);
}
if ( StructArrayLayout6i1ul2ui2i24 ) CollisionBoxArray.__proto__ = StructArrayLayout6i1ul2ui2i24;
CollisionBoxArray.prototype = Object.create( StructArrayLayout6i1ul2ui2i24 && StructArrayLayout6i1ul2ui2i24.prototype );
CollisionBoxArray.prototype.constructor = CollisionBoxArray;
CollisionBoxArray.prototype.get = function get (index ) {
assert_1(!this.isTransferred);
return new CollisionBoxStruct(this, index);
};
return CollisionBoxArray;
}(StructArrayLayout6i1ul2ui2i24));
register('CollisionBoxArray', CollisionBoxArray);
var PlacedSymbolStruct = (function (Struct$$1) {
function PlacedSymbolStruct () {
Struct$$1.apply(this, arguments);
}
if ( Struct$$1 ) PlacedSymbolStruct.__proto__ = Struct$$1;
PlacedSymbolStruct.prototype = Object.create( Struct$$1 && Struct$$1.prototype );
PlacedSymbolStruct.prototype.constructor = PlacedSymbolStruct;
var prototypeAccessors$1 = { anchorX: { configurable: true },anchorY: { configurable: true },glyphStartIndex: { configurable: true },numGlyphs: { configurable: true },vertexStartIndex: { configurable: true },lineStartIndex: { configurable: true },lineLength: { configurable: true },segment: { configurable: true },lowerSize: { configurable: true },upperSize: { configurable: true },lineOffsetX: { configurable: true },lineOffsetY: { configurable: true },writingMode: { configurable: true },hidden: { configurable: true } };
prototypeAccessors$1.anchorX.get = function () { return this._structArray.int16[this._pos2 + 0]; };
prototypeAccessors$1.anchorX.set = function (x) { this._structArray.int16[this._pos2 + 0] = x; };
prototypeAccessors$1.anchorY.get = function () { return this._structArray.int16[this._pos2 + 1]; };
prototypeAccessors$1.anchorY.set = function (x) { this._structArray.int16[this._pos2 + 1] = x; };
prototypeAccessors$1.glyphStartIndex.get = function () { return this._structArray.uint16[this._pos2 + 2]; };
prototypeAccessors$1.glyphStartIndex.set = function (x) { this._structArray.uint16[this._pos2 + 2] = x; };
prototypeAccessors$1.numGlyphs.get = function () { return this._structArray.uint16[this._pos2 + 3]; };
prototypeAccessors$1.numGlyphs.set = function (x) { this._structArray.uint16[this._pos2 + 3] = x; };
prototypeAccessors$1.vertexStartIndex.get = function () { return this._structArray.uint32[this._pos4 + 2]; };
prototypeAccessors$1.vertexStartIndex.set = function (x) { this._structArray.uint32[this._pos4 + 2] = x; };
prototypeAccessors$1.lineStartIndex.get = function () { return this._structArray.uint32[this._pos4 + 3]; };
prototypeAccessors$1.lineStartIndex.set = function (x) { this._structArray.uint32[this._pos4 + 3] = x; };
prototypeAccessors$1.lineLength.get = function () { return this._structArray.uint32[this._pos4 + 4]; };
prototypeAccessors$1.lineLength.set = function (x) { this._structArray.uint32[this._pos4 + 4] = x; };
prototypeAccessors$1.segment.get = function () { return this._structArray.uint16[this._pos2 + 10]; };
prototypeAccessors$1.segment.set = function (x) { this._structArray.uint16[this._pos2 + 10] = x; };
prototypeAccessors$1.lowerSize.get = function () { return this._structArray.uint16[this._pos2 + 11]; };
prototypeAccessors$1.lowerSize.set = function (x) { this._structArray.uint16[this._pos2 + 11] = x; };
prototypeAccessors$1.upperSize.get = function () { return this._structArray.uint16[this._pos2 + 12]; };
prototypeAccessors$1.upperSize.set = function (x) { this._structArray.uint16[this._pos2 + 12] = x; };
prototypeAccessors$1.lineOffsetX.get = function () { return this._structArray.float32[this._pos4 + 7]; };
prototypeAccessors$1.lineOffsetX.set = function (x) { this._structArray.float32[this._pos4 + 7] = x; };
prototypeAccessors$1.lineOffsetY.get = function () { return this._structArray.float32[this._pos4 + 8]; };
prototypeAccessors$1.lineOffsetY.set = function (x) { this._structArray.float32[this._pos4 + 8] = x; };
prototypeAccessors$1.writingMode.get = function () { return this._structArray.uint8[this._pos1 + 36]; };
prototypeAccessors$1.writingMode.set = function (x) { this._structArray.uint8[this._pos1 + 36] = x; };
prototypeAccessors$1.hidden.get = function () { return this._structArray.uint8[this._pos1 + 37]; };
prototypeAccessors$1.hidden.set = function (x) { this._structArray.uint8[this._pos1 + 37] = x; };
Object.defineProperties( PlacedSymbolStruct.prototype, prototypeAccessors$1 );
return PlacedSymbolStruct;
}(Struct));
PlacedSymbolStruct.prototype.size = 40;
/**
* @private
*/
var PlacedSymbolArray = (function (StructArrayLayout2i2ui3ul3ui2f2ub40) {
function PlacedSymbolArray () {
StructArrayLayout2i2ui3ul3ui2f2ub40.apply(this, arguments);
}
if ( StructArrayLayout2i2ui3ul3ui2f2ub40 ) PlacedSymbolArray.__proto__ = StructArrayLayout2i2ui3ul3ui2f2ub40;
PlacedSymbolArray.prototype = Object.create( StructArrayLayout2i2ui3ul3ui2f2ub40 && StructArrayLayout2i2ui3ul3ui2f2ub40.prototype );
PlacedSymbolArray.prototype.constructor = PlacedSymbolArray;
PlacedSymbolArray.prototype.get = function get (index ) {
assert_1(!this.isTransferred);
return new PlacedSymbolStruct(this, index);
};
return PlacedSymbolArray;
}(StructArrayLayout2i2ui3ul3ui2f2ub40));
register('PlacedSymbolArray', PlacedSymbolArray);
var GlyphOffsetStruct = (function (Struct$$1) {
function GlyphOffsetStruct () {
Struct$$1.apply(this, arguments);
}
if ( Struct$$1 ) GlyphOffsetStruct.__proto__ = Struct$$1;
GlyphOffsetStruct.prototype = Object.create( Struct$$1 && Struct$$1.prototype );
GlyphOffsetStruct.prototype.constructor = GlyphOffsetStruct;
var prototypeAccessors$2 = { offsetX: { configurable: true } };
prototypeAccessors$2.offsetX.get = function () { return this._structArray.float32[this._pos4 + 0]; };
prototypeAccessors$2.offsetX.set = function (x) { this._structArray.float32[this._pos4 + 0] = x; };
Object.defineProperties( GlyphOffsetStruct.prototype, prototypeAccessors$2 );
return GlyphOffsetStruct;
}(Struct));
GlyphOffsetStruct.prototype.size = 4;
/**
* @private
*/
var GlyphOffsetArray = (function (StructArrayLayout1f4) {
function GlyphOffsetArray () {
StructArrayLayout1f4.apply(this, arguments);
}
if ( StructArrayLayout1f4 ) GlyphOffsetArray.__proto__ = StructArrayLayout1f4;
GlyphOffsetArray.prototype = Object.create( StructArrayLayout1f4 && StructArrayLayout1f4.prototype );
GlyphOffsetArray.prototype.constructor = GlyphOffsetArray;
GlyphOffsetArray.prototype.getoffsetX = function getoffsetX (index ) { return this.float32[index * 1 + 0]; };
/**
* Return the GlyphOffsetStruct at the given location in the array.
* @param {number} index The index of the element.
*/
GlyphOffsetArray.prototype.get = function get (index ) {
assert_1(!this.isTransferred);
return new GlyphOffsetStruct(this, index);
};
return GlyphOffsetArray;
}(StructArrayLayout1f4));
register('GlyphOffsetArray', GlyphOffsetArray);
var SymbolLineVertexStruct = (function (Struct$$1) {
function SymbolLineVertexStruct () {
Struct$$1.apply(this, arguments);
}
if ( Struct$$1 ) SymbolLineVertexStruct.__proto__ = Struct$$1;
SymbolLineVertexStruct.prototype = Object.create( Struct$$1 && Struct$$1.prototype );
SymbolLineVertexStruct.prototype.constructor = SymbolLineVertexStruct;
var prototypeAccessors$3 = { x: { configurable: true },y: { configurable: true },tileUnitDistanceFromAnchor: { configurable: true } };
prototypeAccessors$3.x.get = function () { return this._structArray.int16[this._pos2 + 0]; };
prototypeAccessors$3.x.set = function (x) { this._structArray.int16[this._pos2 + 0] = x; };
prototypeAccessors$3.y.get = function () { return this._structArray.int16[this._pos2 + 1]; };
prototypeAccessors$3.y.set = function (x) { this._structArray.int16[this._pos2 + 1] = x; };
prototypeAccessors$3.tileUnitDistanceFromAnchor.get = function () { return this._structArray.int16[this._pos2 + 2]; };
prototypeAccessors$3.tileUnitDistanceFromAnchor.set = function (x) { this._structArray.int16[this._pos2 + 2] = x; };
Object.defineProperties( SymbolLineVertexStruct.prototype, prototypeAccessors$3 );
return SymbolLineVertexStruct;
}(Struct));
SymbolLineVertexStruct.prototype.size = 6;
/**
* @private
*/
var SymbolLineVertexArray = (function (StructArrayLayout3i6) {
function SymbolLineVertexArray () {
StructArrayLayout3i6.apply(this, arguments);
}
if ( StructArrayLayout3i6 ) SymbolLineVertexArray.__proto__ = StructArrayLayout3i6;
SymbolLineVertexArray.prototype = Object.create( StructArrayLayout3i6 && StructArrayLayout3i6.prototype );
SymbolLineVertexArray.prototype.constructor = SymbolLineVertexArray;
SymbolLineVertexArray.prototype.getx = function getx (index ) { return this.int16[index * 3 + 0]; };
SymbolLineVertexArray.prototype.gety = function gety (index ) { return this.int16[index * 3 + 1]; };
SymbolLineVertexArray.prototype.gettileUnitDistanceFromAnchor = function gettileUnitDistanceFromAnchor (index ) { return this.int16[index * 3 + 2]; };
/**
* Return the SymbolLineVertexStruct at the given location in the array.
* @param {number} index The index of the element.
*/
SymbolLineVertexArray.prototype.get = function get (index ) {
assert_1(!this.isTransferred);
return new SymbolLineVertexStruct(this, index);
};
return SymbolLineVertexArray;
}(StructArrayLayout3i6));
register('SymbolLineVertexArray', SymbolLineVertexArray);
var FeatureIndexStruct = (function (Struct$$1) {
function FeatureIndexStruct () {
Struct$$1.apply(this, arguments);
}
if ( Struct$$1 ) FeatureIndexStruct.__proto__ = Struct$$1;
FeatureIndexStruct.prototype = Object.create( Struct$$1 && Struct$$1.prototype );
FeatureIndexStruct.prototype.constructor = FeatureIndexStruct;
var prototypeAccessors$4 = { featureIndex: { configurable: true },sourceLayerIndex: { configurable: true },bucketIndex: { configurable: true } };
prototypeAccessors$4.featureIndex.get = function () { return this._structArray.uint32[this._pos4 + 0]; };
prototypeAccessors$4.featureIndex.set = function (x) { this._structArray.uint32[this._pos4 + 0] = x; };
prototypeAccessors$4.sourceLayerIndex.get = function () { return this._structArray.uint16[this._pos2 + 2]; };
prototypeAccessors$4.sourceLayerIndex.set = function (x) { this._structArray.uint16[this._pos2 + 2] = x; };
prototypeAccessors$4.bucketIndex.get = function () { return this._structArray.uint16[this._pos2 + 3]; };
prototypeAccessors$4.bucketIndex.set = function (x) { this._structArray.uint16[this._pos2 + 3] = x; };
Object.defineProperties( FeatureIndexStruct.prototype, prototypeAccessors$4 );
return FeatureIndexStruct;
}(Struct));
FeatureIndexStruct.prototype.size = 8;
/**
* @private
*/
var FeatureIndexArray = (function (StructArrayLayout1ul2ui8) {
function FeatureIndexArray () {
StructArrayLayout1ul2ui8.apply(this, arguments);
}
if ( StructArrayLayout1ul2ui8 ) FeatureIndexArray.__proto__ = StructArrayLayout1ul2ui8;
FeatureIndexArray.prototype = Object.create( StructArrayLayout1ul2ui8 && StructArrayLayout1ul2ui8.prototype );
FeatureIndexArray.prototype.constructor = FeatureIndexArray;
FeatureIndexArray.prototype.get = function get (index ) {
assert_1(!this.isTransferred);
return new FeatureIndexStruct(this, index);
};
return FeatureIndexArray;
}(StructArrayLayout1ul2ui8));
register('FeatureIndexArray', FeatureIndexArray);
//
var layout$1 = createLayout([
{name: 'a_pos', components: 2, type: 'Int16'}
], 4);
var members = layout$1.members;
var size = layout$1.size;
var alignment = layout$1.alignment;
//
var SegmentVector = function SegmentVector(segments) {
if ( segments === void 0 ) segments = [];
this.segments = segments;
};
SegmentVector.prototype.prepareSegment = function prepareSegment (numVertices , layoutVertexArray , indexArray ) {
var segment = this.segments[this.segments.length - 1];
if (numVertices > SegmentVector.MAX_VERTEX_ARRAY_LENGTH) { warnOnce(("Max vertices per segment is " + (SegmentVector.MAX_VERTEX_ARRAY_LENGTH) + ": bucket requested " + numVertices)); }
if (!segment || segment.vertexLength + numVertices > SegmentVector.MAX_VERTEX_ARRAY_LENGTH) {
segment = ({
vertexOffset: layoutVertexArray.length,
primitiveOffset: indexArray.length,
vertexLength: 0,
primitiveLength: 0
} );
this.segments.push(segment);
}
return segment;
};
SegmentVector.prototype.get = function get () {
return this.segments;
};
SegmentVector.prototype.destroy = function destroy () {
var this$1 = this;
for (var i = 0, list = this$1.segments; i < list.length; i += 1) {
var segment = list[i];
for (var k in segment.vaos) {
segment.vaos[k].destroy();
}
}
};
SegmentVector.simpleSegment = function simpleSegment (vertexOffset , primitiveOffset , vertexLength , primitiveLength ) {
return new SegmentVector([{
vertexOffset: vertexOffset,
primitiveOffset: primitiveOffset,
vertexLength: vertexLength,
primitiveLength: primitiveLength,
vaos: {}
}]);
};
/*
* The maximum size of a vertex array. This limit is imposed by WebGL's 16 bit
* addressing of vertex buffers.
* @private
* @readonly
*/
SegmentVector.MAX_VERTEX_ARRAY_LENGTH = Math.pow(2, 16) - 1;
register('SegmentVector', SegmentVector);
//
/**
* Packs two numbers, interpreted as 8-bit unsigned integers, into a single
* float. Unpack them in the shader using the `unpack_float()` function,
* defined in _prelude.vertex.glsl
*
* @private
*/
var packUint8ToFloat = function pack(a , b ) {
// coerce a and b to 8-bit ints
a = clamp(Math.floor(a), 0, 255);
b = clamp(Math.floor(b), 0, 255);
return 256 * a + b;
};
//
var Uniform = function Uniform(context , location ) {
this.gl = context.gl;
this.location = location;
};
var Uniform1i = (function (Uniform) {
function Uniform1i(context , location ) {
Uniform.call(this, context, location);
this.current = 0;
}
if ( Uniform ) Uniform1i.__proto__ = Uniform;
Uniform1i.prototype = Object.create( Uniform && Uniform.prototype );
Uniform1i.prototype.constructor = Uniform1i;
Uniform1i.prototype.set = function set (v ) {
if (this.current !== v) {
this.current = v;
this.gl.uniform1i(this.location, v);
}
};
return Uniform1i;
}(Uniform));
var Uniform1f = (function (Uniform) {
function Uniform1f(context , location ) {
Uniform.call(this, context, location);
this.current = 0;
}
if ( Uniform ) Uniform1f.__proto__ = Uniform;
Uniform1f.prototype = Object.create( Uniform && Uniform.prototype );
Uniform1f.prototype.constructor = Uniform1f;
Uniform1f.prototype.set = function set (v ) {
if (this.current !== v) {
this.current = v;
this.gl.uniform1f(this.location, v);
}
};
return Uniform1f;
}(Uniform));
var Uniform2f = (function (Uniform) {
function Uniform2f(context , location ) {
Uniform.call(this, context, location);
this.current = [0, 0];
}
if ( Uniform ) Uniform2f.__proto__ = Uniform;
Uniform2f.prototype = Object.create( Uniform && Uniform.prototype );
Uniform2f.prototype.constructor = Uniform2f;
Uniform2f.prototype.set = function set (v ) {
if (v[0] !== this.current[0] || v[1] !== this.current[1]) {
this.current = v;
this.gl.uniform2f(this.location, v[0], v[1]);
}
};
return Uniform2f;
}(Uniform));
var Uniform3f = (function (Uniform) {
function Uniform3f(context , location ) {
Uniform.call(this, context, location);
this.current = [0, 0, 0];
}
if ( Uniform ) Uniform3f.__proto__ = Uniform;
Uniform3f.prototype = Object.create( Uniform && Uniform.prototype );
Uniform3f.prototype.constructor = Uniform3f;
Uniform3f.prototype.set = function set (v ) {
if (v[0] !== this.current[0] || v[1] !== this.current[1] || v[2] !== this.current[2]) {
this.current = v;
this.gl.uniform3f(this.location, v[0], v[1], v[2]);
}
};
return Uniform3f;
}(Uniform));
var Uniform4f = (function (Uniform) {
function Uniform4f(context , location ) {
Uniform.call(this, context, location);
this.current = [0, 0, 0, 0];
}
if ( Uniform ) Uniform4f.__proto__ = Uniform;
Uniform4f.prototype = Object.create( Uniform && Uniform.prototype );
Uniform4f.prototype.constructor = Uniform4f;
Uniform4f.prototype.set = function set (v ) {
if (v[0] !== this.current[0] || v[1] !== this.current[1] ||
v[2] !== this.current[2] || v[3] !== this.current[3]) {
this.current = v;
this.gl.uniform4f(this.location, v[0], v[1], v[2], v[3]);
}
};
return Uniform4f;
}(Uniform));
var UniformColor = (function (Uniform) {
function UniformColor(context , location ) {
Uniform.call(this, context, location);
this.current = Color.transparent;
}
if ( Uniform ) UniformColor.__proto__ = Uniform;
UniformColor.prototype = Object.create( Uniform && Uniform.prototype );
UniformColor.prototype.constructor = UniformColor;
UniformColor.prototype.set = function set (v ) {
if (v.r !== this.current.r || v.g !== this.current.g ||
v.b !== this.current.b || v.a !== this.current.a) {
this.current = v;
this.gl.uniform4f(this.location, v.r, v.g, v.b, v.a);
}
};
return UniformColor;
}(Uniform));
var emptyMat4 = new Float32Array(16);
var UniformMatrix4f = (function (Uniform) {
function UniformMatrix4f(context , location ) {
Uniform.call(this, context, location);
this.current = emptyMat4;
}
if ( Uniform ) UniformMatrix4f.__proto__ = Uniform;
UniformMatrix4f.prototype = Object.create( Uniform && Uniform.prototype );
UniformMatrix4f.prototype.constructor = UniformMatrix4f;
UniformMatrix4f.prototype.set = function set (v ) {
var this$1 = this;
// The vast majority of matrix comparisons that will trip this set
// happen at i=12 or i=0, so we check those first to avoid lots of
// unnecessary iteration:
if (v[12] !== this.current[12] || v[0] !== this.current[0]) {
this.current = v;
this.gl.uniformMatrix4fv(this.location, false, v);
return;
}
for (var i = 1; i < 16; i++) {
if (v[i] !== this$1.current[i]) {
this$1.current = v;
this$1.gl.uniformMatrix4fv(this$1.location, false, v);
break;
}
}
};
return UniformMatrix4f;
}(Uniform));
//
function packColor(color ) {
return [
packUint8ToFloat(255 * color.r, 255 * color.g),
packUint8ToFloat(255 * color.b, 255 * color.a)
];
}
/**
* `Binder` is the interface definition for the strategies for constructing,
* uploading, and binding paint property data as GLSL attributes.
*
* It has three implementations, one for each of the three strategies we use:
*
* * For _constant_ properties -- those whose value is a constant, or the constant
* result of evaluating a camera expression at a particular camera position -- we
* don't need a vertex buffer, and instead use a uniform.
* * For data expressions, we use a vertex buffer with a single attribute value,
* the evaluated result of the source function for the given feature.
* * For composite expressions, we use a vertex buffer with two attributes: min and
* max values covering the range of zooms at which we expect the tile to be
* displayed. These values are calculated by evaluating the composite expression for
* the given feature at strategically chosen zoom levels. In addition to this
* attribute data, we also use a uniform value which the shader uses to interpolate
* between the min and max value at the final displayed zoom level. The use of a
* uniform allows us to cheaply update the value on every frame.
*
* Note that the shader source varies depending on whether we're using a uniform or
* attribute. We dynamically compile shaders at runtime to accomodate this.
*
* @private
*/
var ConstantBinder = function ConstantBinder(value , name , type ) {
this.value = value;
this.name = name;
this.uniformName = "u_" + (this.name);
this.type = type;
this.maxValue = -Infinity;
};
ConstantBinder.prototype.defines = function defines () {
return [("#define HAS_UNIFORM_u_" + (this.name))];
};
ConstantBinder.prototype.populatePaintArray = function populatePaintArray () {};
ConstantBinder.prototype.updatePaintArray = function updatePaintArray () {};
ConstantBinder.prototype.upload = function upload () {};
ConstantBinder.prototype.destroy = function destroy () {};
ConstantBinder.prototype.setUniforms = function setUniforms (context , uniform , globals ,
currentValue ) {
uniform.set(currentValue.constantOr(this.value));
};
ConstantBinder.prototype.getBinding = function getBinding (context , location ) {
return (this.type === 'color') ?
new UniformColor(context, location) :
new Uniform1f(context, location);
};
ConstantBinder.serialize = function serialize$1 (binder ) {
var value = binder.value;
var name = binder.name;
var type = binder.type;
return {value: serialize(value), name: name, type: type};
};
ConstantBinder.deserialize = function deserialize$1 (serialized ) {
var value = serialized.value;
var name = serialized.name;
var type = serialized.type;
return new ConstantBinder(deserialize(value), name, type);
};
var SourceExpressionBinder = function SourceExpressionBinder(expression , name , type ) {
this.expression = expression;
this.name = name;
this.type = type;
this.uniformName = "a_" + name;
this.maxValue = -Infinity;
var PaintVertexArray = type === 'color' ? StructArrayLayout2f8 : StructArrayLayout1f4;
this.paintVertexAttributes = [{
name: ("a_" + name),
type: 'Float32',
components: type === 'color' ? 2 : 1,
offset: 0
}];
this.paintVertexArray = new PaintVertexArray();
};
SourceExpressionBinder.prototype.defines = function defines () {
return [];
};
SourceExpressionBinder.prototype.populatePaintArray = function populatePaintArray (newLength , feature ) {
var paintArray = this.paintVertexArray;
var start = paintArray.length;
paintArray.reserve(newLength);
var value = this.expression.evaluate(new EvaluationParameters(0), feature, {});
if (this.type === 'color') {
var color = packColor(value);
for (var i = start; i < newLength; i++) {
paintArray.emplaceBack(color[0], color[1]);
}
} else {
for (var i$1 = start; i$1 < newLength; i$1++) {
paintArray.emplaceBack(value);
}
this.maxValue = Math.max(this.maxValue, value);
}
};
SourceExpressionBinder.prototype.updatePaintArray = function updatePaintArray (start , end , feature , featureState ) {
var paintArray = this.paintVertexArray;
var value = this.expression.evaluate({zoom: 0}, feature, featureState);
if (this.type === 'color') {
var color = packColor(value);
for (var i = start; i < end; i++) {
paintArray.emplace(i, color[0], color[1]);
}
} else {
for (var i$1 = start; i$1 < end; i$1++) {
paintArray.emplace(i$1, value);
}
this.maxValue = Math.max(this.maxValue, value);
}
};
SourceExpressionBinder.prototype.upload = function upload (context ) {
if (this.paintVertexArray && this.paintVertexArray.arrayBuffer) {
if (this.paintVertexBuffer && this.paintVertexBuffer.buffer) {
this.paintVertexBuffer.updateData(this.paintVertexArray);
} else {
this.paintVertexBuffer = context.createVertexBuffer(this.paintVertexArray, this.paintVertexAttributes, this.expression.isStateDependent);
}
}
};
SourceExpressionBinder.prototype.destroy = function destroy () {
if (this.paintVertexBuffer) {
this.paintVertexBuffer.destroy();
}
};
SourceExpressionBinder.prototype.setUniforms = function setUniforms (context , uniform ) {
uniform.set(0);
};
SourceExpressionBinder.prototype.getBinding = function getBinding (context , location ) {
return new Uniform1f(context, location);
};
var CompositeExpressionBinder = function CompositeExpressionBinder(expression , name , type , useIntegerZoom , zoom ) {
this.expression = expression;
this.name = name;
this.uniformName = "a_" + (this.name) + "_t";
this.type = type;
this.useIntegerZoom = useIntegerZoom;
this.zoom = zoom;
this.maxValue = -Infinity;
var PaintVertexArray = type === 'color' ? StructArrayLayout4f16 : StructArrayLayout2f8;
this.paintVertexAttributes = [{
name: ("a_" + name),
type: 'Float32',
components: type === 'color' ? 4 : 2,
offset: 0
}];
this.paintVertexArray = new PaintVertexArray();
};
CompositeExpressionBinder.prototype.defines = function defines () {
return [];
};
CompositeExpressionBinder.prototype.populatePaintArray = function populatePaintArray (newLength , feature ) {
var paintArray = this.paintVertexArray;
var start = paintArray.length;
paintArray.reserve(newLength);
var min = this.expression.evaluate(new EvaluationParameters(this.zoom), feature, {});
var max = this.expression.evaluate(new EvaluationParameters(this.zoom + 1), feature, {});
if (this.type === 'color') {
var minColor = packColor(min);
var maxColor = packColor(max);
for (var i = start; i < newLength; i++) {
paintArray.emplaceBack(minColor[0], minColor[1], maxColor[0], maxColor[1]);
}
} else {
for (var i$1 = start; i$1 < newLength; i$1++) {
paintArray.emplaceBack(min, max);
}
this.maxValue = Math.max(this.maxValue, min, max);
}
};
CompositeExpressionBinder.prototype.updatePaintArray = function updatePaintArray (start , end , feature , featureState ) {
var paintArray = this.paintVertexArray;
var min = this.expression.evaluate({zoom: this.zoom }, feature, featureState);
var max = this.expression.evaluate({zoom: this.zoom + 1}, feature, featureState);
if (this.type === 'color') {
var minColor = packColor(min);
var maxColor = packColor(max);
for (var i = start; i < end; i++) {
paintArray.emplace(i, minColor[0], minColor[1], maxColor[0], maxColor[1]);
}
} else {
for (var i$1 = start; i$1 < end; i$1++) {
paintArray.emplace(i$1, min, max);
}
this.maxValue = Math.max(this.maxValue, min, max);
}
};
CompositeExpressionBinder.prototype.upload = function upload (context ) {
if (this.paintVertexArray && this.paintVertexArray.arrayBuffer) {
if (this.paintVertexBuffer && this.paintVertexBuffer.buffer) {
this.paintVertexBuffer.updateData(this.paintVertexArray);
} else {
this.paintVertexBuffer = context.createVertexBuffer(this.paintVertexArray, this.paintVertexAttributes, this.expression.isStateDependent);
}
}
};
CompositeExpressionBinder.prototype.destroy = function destroy () {
if (this.paintVertexBuffer) {
this.paintVertexBuffer.destroy();
}
};
CompositeExpressionBinder.prototype.interpolationFactor = function interpolationFactor (currentZoom ) {
if (this.useIntegerZoom) {
return this.expression.interpolationFactor(Math.floor(currentZoom), this.zoom, this.zoom + 1);
} else {
return this.expression.interpolationFactor(currentZoom, this.zoom, this.zoom + 1);
}
};
CompositeExpressionBinder.prototype.setUniforms = function setUniforms (context , uniform ,
globals ) {
uniform.set(this.interpolationFactor(globals.zoom));
};
CompositeExpressionBinder.prototype.getBinding = function getBinding (context , location ) {
return new Uniform1f(context, location);
};
/**
* ProgramConfiguration contains the logic for binding style layer properties and tile
* layer feature data into GL program uniforms and vertex attributes.
*
* Non-data-driven property values are bound to shader uniforms. Data-driven property
* values are bound to vertex attributes. In order to support a uniform GLSL syntax over
* both, [Mapbox GL Shaders](https://github.com/mapbox/mapbox-gl-shaders) defines a `#pragma`
* abstraction, which ProgramConfiguration is responsible for implementing. At runtime,
* it examines the attributes of a particular layer, combines this with fixed knowledge
* about how layers of the particular type are implemented, and determines which uniforms
* and vertex attributes will be required. It can then substitute the appropriate text
* into the shader source code, create and link a program, and bind the uniforms and
* vertex attributes in preparation for drawing.
*
* When a vector tile is parsed, this same configuration information is used to
* populate the attribute buffers needed for data-driven styling using the zoom
* level and feature property data.
*
* @private
*/
var ProgramConfiguration = function ProgramConfiguration() {
this.binders = {};
this.cacheKey = '';
this._buffers = [];
this._idMap = {};
this._bufferOffset = 0;
};
ProgramConfiguration.createDynamic = function createDynamic (layer , zoom , filterProperties ) {
var self = new ProgramConfiguration();
var keys = [];
for (var property in layer.paint._values) {
if (!filterProperties(property)) { continue; }
var value = layer.paint.get(property);
if (!(value instanceof PossiblyEvaluatedPropertyValue) || !supportsPropertyExpression(value.property.specification)) {
continue;
}
var name = paintAttributeName(property, layer.type);
var type = value.property.specification.type;
var useIntegerZoom = value.property.useIntegerZoom;
if (value.value.kind === 'constant') {
self.binders[property] = new ConstantBinder(value.value.value, name, type);
keys.push(("/u_" + name));
} else if (value.value.kind === 'source') {
self.binders[property] = new SourceExpressionBinder(value.value, name, type);
keys.push(("/a_" + name));
} else {
self.binders[property] = new CompositeExpressionBinder(value.value, name, type, useIntegerZoom, zoom);
keys.push(("/z_" + name));
}
}
self.cacheKey = keys.sort().join('');
return self;
};
ProgramConfiguration.prototype.populatePaintArrays = function populatePaintArrays (newLength , feature , index ) {
var this$1 = this;
for (var property in this$1.binders) {
this$1.binders[property].populatePaintArray(newLength, feature);
}
if (feature.id) {
var featureId = String(feature.id);
this._idMap[featureId] = this._idMap[featureId] || [];
this._idMap[featureId].push({
index: index,
start: this._bufferOffset,
end: newLength
});
}
this._bufferOffset = newLength;
};
ProgramConfiguration.prototype.updatePaintArrays = function updatePaintArrays (featureStates , vtLayer , layer ) {
var this$1 = this;
var dirty = false;
for (var id in featureStates) {
var posArray = this$1._idMap[id];
if (!posArray) { continue; }
var featureState = featureStates[id];
for (var i = 0, list = posArray; i < list.length; i += 1) {
var pos = list[i];
var feature = vtLayer.feature(pos.index);
for (var property in this$1.binders) {
var binder = this$1.binders[property];
if (binder instanceof ConstantBinder) { continue; }
if ((binder ).expression.isStateDependent === true) {
//AHM: Remove after https://github.com/mapbox/mapbox-gl-js/issues/6255
var value = layer.paint.get(property);
(binder ).expression = value.value;
binder.updatePaintArray(pos.start, pos.end, feature, featureState);
dirty = true;
}
}
}
}
return dirty;
};
ProgramConfiguration.prototype.defines = function defines () {
var this$1 = this;
var result = [];
for (var property in this$1.binders) {
result.push.apply(result, this$1.binders[property].defines());
}
return result;
};
ProgramConfiguration.prototype.getPaintVertexBuffers = function getPaintVertexBuffers () {
return this._buffers;
};
ProgramConfiguration.prototype.getUniforms = function getUniforms (context , locations ) {
var this$1 = this;
var result = {};
for (var property in this$1.binders) {
var binder = this$1.binders[property];
result[binder.uniformName] = binder.getBinding(context, locations[binder.uniformName]);
}
return result;
};
ProgramConfiguration.prototype.setUniforms = function setUniforms (context , uniformBindings , properties , globals ) {
var this$1 = this;
// Uniform state bindings are owned by the Program, but we set them
// from within the ProgramConfiguraton's binder members.
for (var property in this$1.binders) {
var binder = this$1.binders[property];
binder.setUniforms(context, uniformBindings[binder.uniformName], globals, properties.get(property));
}
};
ProgramConfiguration.prototype.upload = function upload (context ) {
var this$1 = this;
for (var property in this$1.binders) {
this$1.binders[property].upload(context);
}
var buffers = [];
for (var property$1 in this$1.binders) {
var binder = this$1.binders[property$1];
if ((binder instanceof SourceExpressionBinder ||
binder instanceof CompositeExpressionBinder) &&
binder.paintVertexBuffer
) {
buffers.push(binder.paintVertexBuffer);
}
}
this._buffers = buffers;
};
ProgramConfiguration.prototype.destroy = function destroy () {
var this$1 = this;
for (var property in this$1.binders) {
this$1.binders[property].destroy();
}
};
var ProgramConfigurationSet = function ProgramConfigurationSet(layoutAttributes , layers , zoom , filterProperties) {
var this$1 = this;
if ( filterProperties === void 0 ) filterProperties = function () { return true; };
this.programConfigurations = {};
for (var i = 0, list = layers; i < list.length; i += 1) {
var layer = list[i];
this$1.programConfigurations[layer.id] = ProgramConfiguration.createDynamic(layer, zoom, filterProperties);
this$1.programConfigurations[layer.id].layoutAttributes = layoutAttributes;
}
this.needsUpload = false;
};
ProgramConfigurationSet.prototype.populatePaintArrays = function populatePaintArrays (length , feature , index ) {
var this$1 = this;
for (var key in this$1.programConfigurations) {
this$1.programConfigurations[key].populatePaintArrays(length, feature, index);
}
this.needsUpload = true;
};
ProgramConfigurationSet.prototype.updatePaintArrays = function updatePaintArrays (featureStates , vtLayer , layers ) {
var this$1 = this;
for (var i = 0, list = layers; i < list.length; i += 1) {
var layer = list[i];
this$1.needsUpload = this$1.programConfigurations[layer.id].updatePaintArrays(featureStates, vtLayer, layer) || this$1.needsUpload;
}
};
ProgramConfigurationSet.prototype.get = function get (layerId ) {
return this.programConfigurations[layerId];
};
ProgramConfigurationSet.prototype.upload = function upload (context ) {
var this$1 = this;
if (!this.needsUpload) { return; }
for (var layerId in this$1.programConfigurations) {
this$1.programConfigurations[layerId].upload(context);
}
this.needsUpload = false;
};
ProgramConfigurationSet.prototype.destroy = function destroy () {
var this$1 = this;
for (var layerId in this$1.programConfigurations) {
this$1.programConfigurations[layerId].destroy();
}
};
// paint property arrays
function paintAttributeName(property, type) {
var attributeNameExceptions = {
'text-opacity': 'opacity',
'icon-opacity': 'opacity',
'text-color': 'fill_color',
'icon-color': 'fill_color',
'text-halo-color': 'halo_color',
'icon-halo-color': 'halo_color',
'text-halo-blur': 'halo_blur',
'icon-halo-blur': 'halo_blur',
'text-halo-width': 'halo_width',
'icon-halo-width': 'halo_width',
'line-gap-width': 'gapwidth'
};
return attributeNameExceptions[property] ||
property.replace((type + "-"), '').replace(/-/g, '_');
}
register('ConstantBinder', ConstantBinder);
register('SourceExpressionBinder', SourceExpressionBinder);
register('CompositeExpressionBinder', CompositeExpressionBinder);
register('ProgramConfiguration', ProgramConfiguration, {omit: ['_buffers']});
register('ProgramConfigurationSet', ProgramConfigurationSet);
//
//
/**
* The maximum value of a coordinate in the internal tile coordinate system. Coordinates of
* all source features normalized to this extent upon load.
*
* The value is a consequence of the following:
*
* * Vertex buffer store positions as signed 16 bit integers.
* * One bit is lost for signedness to support tile buffers.
* * One bit is lost because the line vertex buffer used to pack 1 bit of other data into the int.
* This is no longer the case but we're reserving this bit anyway.
* * One bit is lost to support features extending past the extent on the right edge of the tile.
* * This leaves us with 2^13 = 8192
*
* @private
* @readonly
*/
var EXTENT = 8192;
//
// These bounds define the minimum and maximum supported coordinate values.
// While visible coordinates are within [0, EXTENT], tiles may theoretically
// contain cordinates within [-Infinity, Infinity]. Our range is limited by the
// number of bits used to represent the coordinate.
function createBounds(bits) {
return {
min: -1 * Math.pow(2, bits - 1),
max: Math.pow(2, bits - 1) - 1
};
}
var bounds = createBounds(16);
/**
* Loads a geometry from a VectorTileFeature and scales it to the common extent
* used internally.
* @param {VectorTileFeature} feature
* @private
*/
function loadGeometry(feature ) {
var scale = EXTENT / feature.extent;
var geometry = feature.loadGeometry();
for (var r = 0; r < geometry.length; r++) {
var ring = geometry[r];
for (var p = 0; p < ring.length; p++) {
var point = ring[p];
// round here because mapbox-gl-native uses integers to represent
// points and we need to do the same to avoid renering differences.
point.x = Math.round(point.x * scale);
point.y = Math.round(point.y * scale);
if (point.x < bounds.min || point.x > bounds.max || point.y < bounds.min || point.y > bounds.max) {
warnOnce('Geometry exceeds allowed extent, reduce your vector tile buffer size');
}
}
}
return geometry;
}
//
function addCircleVertex(layoutVertexArray, x, y, extrudeX, extrudeY) {
layoutVertexArray.emplaceBack(
(x * 2) + ((extrudeX + 1) / 2),
(y * 2) + ((extrudeY + 1) / 2));
}
/**
* Circles are represented by two triangles.
*
* Each corner has a pos that is the center of the circle and an extrusion
* vector that is where it points.
* @private
*/
var CircleBucket = function CircleBucket(options ) {
this.zoom = options.zoom;
this.overscaling = options.overscaling;
this.layers = options.layers;
this.layerIds = this.layers.map(function (layer) { return layer.id; });
this.index = options.index;
this.layoutVertexArray = new StructArrayLayout2i4();
this.indexArray = new StructArrayLayout3ui6();
this.segments = new SegmentVector();
this.programConfigurations = new ProgramConfigurationSet(members, options.layers, options.zoom);
};
CircleBucket.prototype.populate = function populate (features , options ) {
var this$1 = this;
for (var i = 0, list = features; i < list.length; i += 1) {
var ref = list[i];
var feature = ref.feature;
var index = ref.index;
var sourceLayerIndex = ref.sourceLayerIndex;
if (this$1.layers[0]._featureFilter(new EvaluationParameters(this$1.zoom), feature)) {
var geometry = loadGeometry(feature);
this$1.addFeature(feature, geometry, index);
options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this$1.index);
}
}
};
CircleBucket.prototype.update = function update (states , vtLayer ) {
if (!this.stateDependentLayers.length) { return; }
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers);
};
CircleBucket.prototype.isEmpty = function isEmpty () {
return this.layoutVertexArray.length === 0;
};
CircleBucket.prototype.uploadPending = function uploadPending () {
return !this.uploaded || this.programConfigurations.needsUpload;
};
CircleBucket.prototype.upload = function upload (context ) {
if (!this.uploaded) {
this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, members);
this.indexBuffer = context.createIndexBuffer(this.indexArray);
}
this.programConfigurations.upload(context);
this.uploaded = true;
};
CircleBucket.prototype.destroy = function destroy () {
if (!this.layoutVertexBuffer) { return; }
this.layoutVertexBuffer.destroy();
this.indexBuffer.destroy();
this.programConfigurations.destroy();
this.segments.destroy();
};
CircleBucket.prototype.addFeature = function addFeature (feature , geometry , index ) {
var this$1 = this;
for (var i$1 = 0, list$1 = geometry; i$1 < list$1.length; i$1 += 1) {
var ring = list$1[i$1];
for (var i = 0, list = ring; i < list.length; i += 1) {
var point = list[i];
var x = point.x;
var y = point.y;
// Do not include points that are outside the tile boundaries.
if (x < 0 || x >= EXTENT || y < 0 || y >= EXTENT) { continue; }
// this geometry will be of the Point type, and we'll derive
// two triangles from it.
//
// ┌─────────┐
// │ 3 2 │
// │ │
// │ 0 1 │
// └─────────┘
var segment = this$1.segments.prepareSegment(4, this$1.layoutVertexArray, this$1.indexArray);
var index$1 = segment.vertexLength;
addCircleVertex(this$1.layoutVertexArray, x, y, -1, -1);
addCircleVertex(this$1.layoutVertexArray, x, y, 1, -1);
addCircleVertex(this$1.layoutVertexArray, x, y, 1, 1);
addCircleVertex(this$1.layoutVertexArray, x, y, -1, 1);
this$1.indexArray.emplaceBack(index$1, index$1 + 1, index$1 + 2);
this$1.indexArray.emplaceBack(index$1, index$1 + 3, index$1 + 2);
segment.vertexLength += 4;
segment.primitiveLength += 2;
}
}
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index);
};
register('CircleBucket', CircleBucket, {omit: ['layers']});
//
function polygonIntersectsPolygon(polygonA , polygonB ) {
for (var i = 0; i < polygonA.length; i++) {
if (polygonContainsPoint(polygonB, polygonA[i])) { return true; }
}
for (var i$1 = 0; i$1 < polygonB.length; i$1++) {
if (polygonContainsPoint(polygonA, polygonB[i$1])) { return true; }
}
if (lineIntersectsLine(polygonA, polygonB)) { return true; }
return false;
}
function multiPolygonIntersectsBufferedPoint(multiPolygon , point , radius ) {
for (var j = 0; j < multiPolygon.length; j++) {
var polygon = multiPolygon[j];
if (polygonContainsPoint(polygon, point)) { return true; }
if (pointIntersectsBufferedLine(point, polygon, radius)) { return true; }
}
return false;
}
function multiPolygonIntersectsBufferedMultiPoint(multiPolygon , rings , radius ) {
for (var i = 0; i < rings.length; i++) {
var ring = rings[i];
for (var k = 0; k < ring.length; k++) {
if (multiPolygonIntersectsBufferedPoint(multiPolygon, ring[k], radius)) { return true; }
}
}
return false;
}
function multiPolygonIntersectsMultiPolygon(multiPolygonA , multiPolygonB ) {
if (multiPolygonA.length === 1 && multiPolygonA[0].length === 1) {
return multiPolygonContainsPoint(multiPolygonB, multiPolygonA[0][0]);
}
for (var m = 0; m < multiPolygonB.length; m++) {
var ring = multiPolygonB[m];
for (var n = 0; n < ring.length; n++) {
if (multiPolygonContainsPoint(multiPolygonA, ring[n])) { return true; }
}
}
for (var j = 0; j < multiPolygonA.length; j++) {
var polygon = multiPolygonA[j];
for (var i = 0; i < polygon.length; i++) {
if (multiPolygonContainsPoint(multiPolygonB, polygon[i])) { return true; }
}
for (var k = 0; k < multiPolygonB.length; k++) {
if (lineIntersectsLine(polygon, multiPolygonB[k])) { return true; }
}
}
return false;
}
function multiPolygonIntersectsBufferedMultiLine(multiPolygon , multiLine , radius ) {
for (var i = 0; i < multiLine.length; i++) {
var line = multiLine[i];
for (var j = 0; j < multiPolygon.length; j++) {
var polygon = multiPolygon[j];
if (polygon.length >= 3) {
for (var k = 0; k < line.length; k++) {
if (polygonContainsPoint(polygon, line[k])) { return true; }
}
}
if (lineIntersectsBufferedLine(polygon, line, radius)) { return true; }
}
}
return false;
}
function lineIntersectsBufferedLine(lineA , lineB , radius ) {
if (lineA.length > 1) {
if (lineIntersectsLine(lineA, lineB)) { return true; }
// Check whether any point in either line is within radius of the other line
for (var j = 0; j < lineB.length; j++) {
if (pointIntersectsBufferedLine(lineB[j], lineA, radius)) { return true; }
}
}
for (var k = 0; k < lineA.length; k++) {
if (pointIntersectsBufferedLine(lineA[k], lineB, radius)) { return true; }
}
return false;
}
function lineIntersectsLine(lineA , lineB ) {
if (lineA.length === 0 || lineB.length === 0) { return false; }
for (var i = 0; i < lineA.length - 1; i++) {
var a0 = lineA[i];
var a1 = lineA[i + 1];
for (var j = 0; j < lineB.length - 1; j++) {
var b0 = lineB[j];
var b1 = lineB[j + 1];
if (lineSegmentIntersectsLineSegment(a0, a1, b0, b1)) { return true; }
}
}
return false;
}
function lineSegmentIntersectsLineSegment(a0 , a1 , b0 , b1 ) {
return isCounterClockwise(a0, b0, b1) !== isCounterClockwise(a1, b0, b1) &&
isCounterClockwise(a0, a1, b0) !== isCounterClockwise(a0, a1, b1);
}
function pointIntersectsBufferedLine(p , line , radius ) {
var radiusSquared = radius * radius;
if (line.length === 1) { return p.distSqr(line[0]) < radiusSquared; }
for (var i = 1; i < line.length; i++) {
// Find line segments that have a distance <= radius^2 to p
// In that case, we treat the line as "containing point p".
var v = line[i - 1], w = line[i];
if (distToSegmentSquared(p, v, w) < radiusSquared) { return true; }
}
return false;
}
// Code from http://stackoverflow.com/a/1501725/331379.
function distToSegmentSquared(p , v , w ) {
var l2 = v.distSqr(w);
if (l2 === 0) { return p.distSqr(v); }
var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
if (t < 0) { return p.distSqr(v); }
if (t > 1) { return p.distSqr(w); }
return p.distSqr(w.sub(v)._mult(t)._add(v));
}
// point in polygon ray casting algorithm
function multiPolygonContainsPoint(rings , p ) {
var c = false,
ring, p1, p2;
for (var k = 0; k < rings.length; k++) {
ring = rings[k];
for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
p1 = ring[i];
p2 = ring[j];
if (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {
c = !c;
}
}
}
return c;
}
function polygonContainsPoint(ring , p ) {
var c = false;
for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
var p1 = ring[i];
var p2 = ring[j];
if (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {
c = !c;
}
}
return c;
}
//
function getMaximumPaintValue(property , layer , bucket ) {
var value = ((layer.paint ).get(property) ).value;
if (value.kind === 'constant') {
return value.value;
} else {
var binders = bucket.programConfigurations.get(layer.id).binders;
return binders[property].maxValue;
}
}
function translateDistance(translate ) {
return Math.sqrt(translate[0] * translate[0] + translate[1] * translate[1]);
}
function translate(queryGeometry ,
translate ,
translateAnchor ,
bearing ,
pixelsToTileUnits ) {
if (!translate[0] && !translate[1]) {
return queryGeometry;
}
var pt = pointGeometry.convert(translate);
if (translateAnchor === "viewport") {
pt._rotate(-bearing);
}
var translated = [];
for (var i = 0; i < queryGeometry.length; i++) {
var ring = queryGeometry[i];
var translatedRing = [];
for (var k = 0; k < ring.length; k++) {
translatedRing.push(ring[k].sub(pt._mult(pixelsToTileUnits)));
}
translated.push(translatedRing);
}
return translated;
}
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
var paint$1 = new Properties({
"circle-radius": new DataDrivenProperty(styleSpec["paint_circle"]["circle-radius"]),
"circle-color": new DataDrivenProperty(styleSpec["paint_circle"]["circle-color"]),
"circle-blur": new DataDrivenProperty(styleSpec["paint_circle"]["circle-blur"]),
"circle-opacity": new DataDrivenProperty(styleSpec["paint_circle"]["circle-opacity"]),
"circle-translate": new DataConstantProperty(styleSpec["paint_circle"]["circle-translate"]),
"circle-translate-anchor": new DataConstantProperty(styleSpec["paint_circle"]["circle-translate-anchor"]),
"circle-pitch-scale": new DataConstantProperty(styleSpec["paint_circle"]["circle-pitch-scale"]),
"circle-pitch-alignment": new DataConstantProperty(styleSpec["paint_circle"]["circle-pitch-alignment"]),
"circle-stroke-width": new DataDrivenProperty(styleSpec["paint_circle"]["circle-stroke-width"]),
"circle-stroke-color": new DataDrivenProperty(styleSpec["paint_circle"]["circle-stroke-color"]),
"circle-stroke-opacity": new DataDrivenProperty(styleSpec["paint_circle"]["circle-stroke-opacity"]),
});
// Note: without adding the explicit type annotation, Flow infers weaker types
// for these objects from their use in the constructor to StyleLayer, as
// {layout?: Properties<...>, paint: Properties<...>}
var properties = ({ paint: paint$1 }
);
/**
* Common utilities
* @module glMatrix
*/
// Configuration Constants
var EPSILON = 0.000001;
var ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
var RANDOM = Math.random;
/**
* Sets the type of array used when creating new vectors and matrices
*
* @param {Type} type Array type, such as Float32Array or Array
*/
function setMatrixArrayType(type) {
ARRAY_TYPE = type;
}
var degree = Math.PI / 180;
/**
* Convert Degree To Radian
*
* @param {Number} a Angle in Degrees
*/
function toRadian(a) {
return a * degree;
}
/**
* Tests whether or not the arguments have approximately the same value, within an absolute
* or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less
* than or equal to 1.0, and a relative tolerance is used for larger values)
*
* @param {Number} a The first number to test.
* @param {Number} b The second number to test.
* @returns {Boolean} True if the numbers are approximately equal, false otherwise.
*/
function equals(a, b) {
return Math.abs(a - b) <= EPSILON*Math.max(1.0, Math.abs(a), Math.abs(b));
}
/**
* 2x2 Matrix
* @module mat2
*/
/**
* Creates a new identity mat2
*
* @returns {mat2} a new 2x2 matrix
*/
function create() {
var out = new ARRAY_TYPE(4);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
}
/**
* Creates a new mat2 initialized with values from an existing matrix
*
* @param {mat2} a matrix to clone
* @returns {mat2} a new 2x2 matrix
*/
function clone$1(a) {
var out = new ARRAY_TYPE(4);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
}
/**
* Copy the values from one mat2 to another
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
function copy(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
}
/**
* Set a mat2 to the identity matrix
*
* @param {mat2} out the receiving matrix
* @returns {mat2} out
*/
function identity(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
}
/**
* Create a new mat2 with the given values
*
* @param {Number} m00 Component in column 0, row 0 position (index 0)
* @param {Number} m01 Component in column 0, row 1 position (index 1)
* @param {Number} m10 Component in column 1, row 0 position (index 2)
* @param {Number} m11 Component in column 1, row 1 position (index 3)
* @returns {mat2} out A new 2x2 matrix
*/
function fromValues(m00, m01, m10, m11) {
var out = new ARRAY_TYPE(4);
out[0] = m00;
out[1] = m01;
out[2] = m10;
out[3] = m11;
return out;
}
/**
* Set the components of a mat2 to the given values
*
* @param {mat2} out the receiving matrix
* @param {Number} m00 Component in column 0, row 0 position (index 0)
* @param {Number} m01 Component in column 0, row 1 position (index 1)
* @param {Number} m10 Component in column 1, row 0 position (index 2)
* @param {Number} m11 Component in column 1, row 1 position (index 3)
* @returns {mat2} out
*/
function set(out, m00, m01, m10, m11) {
out[0] = m00;
out[1] = m01;
out[2] = m10;
out[3] = m11;
return out;
}
/**
* Transpose the values of a mat2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
function transpose(out, a) {
// If we are transposing ourselves we can skip a few steps but have to cache
// some values
if (out === a) {
var a1 = a[1];
out[1] = a[2];
out[2] = a1;
} else {
out[0] = a[0];
out[1] = a[2];
out[2] = a[1];
out[3] = a[3];
}
return out;
}
/**
* Inverts a mat2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
function invert(out, a) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
// Calculate the determinant
var det = a0 * a3 - a2 * a1;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = a3 * det;
out[1] = -a1 * det;
out[2] = -a2 * det;
out[3] = a0 * det;
return out;
}
/**
* Calculates the adjugate of a mat2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the source matrix
* @returns {mat2} out
*/
function adjoint(out, a) {
// Caching this value is nessecary if out == a
var a0 = a[0];
out[0] = a[3];
out[1] = -a[1];
out[2] = -a[2];
out[3] = a0;
return out;
}
/**
* Calculates the determinant of a mat2
*
* @param {mat2} a the source matrix
* @returns {Number} determinant of a
*/
function determinant(a) {
return a[0] * a[3] - a[2] * a[1];
}
/**
* Multiplies two mat2's
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the first operand
* @param {mat2} b the second operand
* @returns {mat2} out
*/
function multiply(out, a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
out[0] = a0 * b0 + a2 * b1;
out[1] = a1 * b0 + a3 * b1;
out[2] = a0 * b2 + a2 * b3;
out[3] = a1 * b2 + a3 * b3;
return out;
}
/**
* Rotates a mat2 by the given angle
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat2} out
*/
function rotate(out, a, rad) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
var s = Math.sin(rad);
var c = Math.cos(rad);
out[0] = a0 * c + a2 * s;
out[1] = a1 * c + a3 * s;
out[2] = a0 * -s + a2 * c;
out[3] = a1 * -s + a3 * c;
return out;
}
/**
* Scales the mat2 by the dimensions in the given vec2
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the matrix to rotate
* @param {vec2} v the vec2 to scale the matrix by
* @returns {mat2} out
**/
function scale(out, a, v) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
var v0 = v[0], v1 = v[1];
out[0] = a0 * v0;
out[1] = a1 * v0;
out[2] = a2 * v1;
out[3] = a3 * v1;
return out;
}
/**
* Creates a matrix from a given angle
* This is equivalent to (but much faster than):
*
* mat2.identity(dest);
* mat2.rotate(dest, dest, rad);
*
* @param {mat2} out mat2 receiving operation result
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat2} out
*/
function fromRotation(out, rad) {
var s = Math.sin(rad);
var c = Math.cos(rad);
out[0] = c;
out[1] = s;
out[2] = -s;
out[3] = c;
return out;
}
/**
* Creates a matrix from a vector scaling
* This is equivalent to (but much faster than):
*
* mat2.identity(dest);
* mat2.scale(dest, dest, vec);
*
* @param {mat2} out mat2 receiving operation result
* @param {vec2} v Scaling vector
* @returns {mat2} out
*/
function fromScaling(out, v) {
out[0] = v[0];
out[1] = 0;
out[2] = 0;
out[3] = v[1];
return out;
}
/**
* Returns a string representation of a mat2
*
* @param {mat2} a matrix to represent as a string
* @returns {String} string representation of the matrix
*/
function str(a) {
return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
}
/**
* Returns Frobenius norm of a mat2
*
* @param {mat2} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
function frob(a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2)))
}
/**
* Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
* @param {mat2} L the lower triangular matrix
* @param {mat2} D the diagonal matrix
* @param {mat2} U the upper triangular matrix
* @param {mat2} a the input matrix to factorize
*/
function LDU(L, D, U, a) {
L[2] = a[2]/a[0];
U[0] = a[0];
U[1] = a[1];
U[3] = a[3] - L[2] * U[1];
return [L, D, U];
}
/**
* Adds two mat2's
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the first operand
* @param {mat2} b the second operand
* @returns {mat2} out
*/
function add(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
out[3] = a[3] + b[3];
return out;
}
/**
* Subtracts matrix b from matrix a
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the first operand
* @param {mat2} b the second operand
* @returns {mat2} out
*/
function subtract(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
out[3] = a[3] - b[3];
return out;
}
/**
* Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
*
* @param {mat2} a The first matrix.
* @param {mat2} b The second matrix.
* @returns {Boolean} True if the matrices are equal, false otherwise.
*/
function exactEquals(a, b) {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
}
/**
* Returns whether or not the matrices have approximately the same elements in the same position.
*
* @param {mat2} a The first matrix.
* @param {mat2} b The second matrix.
* @returns {Boolean} True if the matrices are equal, false otherwise.
*/
function equals$1(a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
return (Math.abs(a0 - b0) <= EPSILON*Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
Math.abs(a1 - b1) <= EPSILON*Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
Math.abs(a2 - b2) <= EPSILON*Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
Math.abs(a3 - b3) <= EPSILON*Math.max(1.0, Math.abs(a3), Math.abs(b3)));
}
/**
* Multiply each element of the matrix by a scalar.
*
* @param {mat2} out the receiving matrix
* @param {mat2} a the matrix to scale
* @param {Number} b amount to scale the matrix's elements by
* @returns {mat2} out
*/
function multiplyScalar(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
out[3] = a[3] * b;
return out;
}
/**
* Adds two mat2's after multiplying each element of the second operand by a scalar value.
*
* @param {mat2} out the receiving vector
* @param {mat2} a the first operand
* @param {mat2} b the second operand
* @param {Number} scale the amount to scale b's elements by before adding
* @returns {mat2} out
*/
function multiplyScalarAndAdd(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
out[2] = a[2] + (b[2] * scale);
out[3] = a[3] + (b[3] * scale);
return out;
}
/**
* Alias for {@link mat2.multiply}
* @function
*/
var mul = multiply;
/**
* Alias for {@link mat2.subtract}
* @function
*/
var sub = subtract;
/**
* 2x3 Matrix
* @module mat2d
*
* @description
* A mat2d contains six elements defined as:
* <pre>
* [a, c, tx,
* b, d, ty]
* </pre>
* This is a short form for the 3x3 matrix:
* <pre>
* [a, c, tx,
* b, d, ty,
* 0, 0, 1]
* </pre>
* The last row is ignored so the array is shorter and operations are faster.
*/
/**
* Creates a new identity mat2d
*
* @returns {mat2d} a new 2x3 matrix
*/
function create$1() {
var out = new ARRAY_TYPE(6);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
out[4] = 0;
out[5] = 0;
return out;
}
/**
* Creates a new mat2d initialized with values from an existing matrix
*
* @param {mat2d} a matrix to clone
* @returns {mat2d} a new 2x3 matrix
*/
function clone$2(a) {
var out = new ARRAY_TYPE(6);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
return out;
}
/**
* Copy the values from one mat2d to another
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the source matrix
* @returns {mat2d} out
*/
function copy$1(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
return out;
}
/**
* Set a mat2d to the identity matrix
*
* @param {mat2d} out the receiving matrix
* @returns {mat2d} out
*/
function identity$1(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
out[4] = 0;
out[5] = 0;
return out;
}
/**
* Create a new mat2d with the given values
*
* @param {Number} a Component A (index 0)
* @param {Number} b Component B (index 1)
* @param {Number} c Component C (index 2)
* @param {Number} d Component D (index 3)
* @param {Number} tx Component TX (index 4)
* @param {Number} ty Component TY (index 5)
* @returns {mat2d} A new mat2d
*/
function fromValues$1(a, b, c, d, tx, ty) {
var out = new ARRAY_TYPE(6);
out[0] = a;
out[1] = b;
out[2] = c;
out[3] = d;
out[4] = tx;
out[5] = ty;
return out;
}
/**
* Set the components of a mat2d to the given values
*
* @param {mat2d} out the receiving matrix
* @param {Number} a Component A (index 0)
* @param {Number} b Component B (index 1)
* @param {Number} c Component C (index 2)
* @param {Number} d Component D (index 3)
* @param {Number} tx Component TX (index 4)
* @param {Number} ty Component TY (index 5)
* @returns {mat2d} out
*/
function set$1(out, a, b, c, d, tx, ty) {
out[0] = a;
out[1] = b;
out[2] = c;
out[3] = d;
out[4] = tx;
out[5] = ty;
return out;
}
/**
* Inverts a mat2d
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the source matrix
* @returns {mat2d} out
*/
function invert$1(out, a) {
var aa = a[0], ab = a[1], ac = a[2], ad = a[3];
var atx = a[4], aty = a[5];
var det = aa * ad - ab * ac;
if(!det){
return null;
}
det = 1.0 / det;
out[0] = ad * det;
out[1] = -ab * det;
out[2] = -ac * det;
out[3] = aa * det;
out[4] = (ac * aty - ad * atx) * det;
out[5] = (ab * atx - aa * aty) * det;
return out;
}
/**
* Calculates the determinant of a mat2d
*
* @param {mat2d} a the source matrix
* @returns {Number} determinant of a
*/
function determinant$1(a) {
return a[0] * a[3] - a[1] * a[2];
}
/**
* Multiplies two mat2d's
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the first operand
* @param {mat2d} b the second operand
* @returns {mat2d} out
*/
function multiply$1(out, a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5];
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];
out[0] = a0 * b0 + a2 * b1;
out[1] = a1 * b0 + a3 * b1;
out[2] = a0 * b2 + a2 * b3;
out[3] = a1 * b2 + a3 * b3;
out[4] = a0 * b4 + a2 * b5 + a4;
out[5] = a1 * b4 + a3 * b5 + a5;
return out;
}
/**
* Rotates a mat2d by the given angle
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat2d} out
*/
function rotate$1(out, a, rad) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5];
var s = Math.sin(rad);
var c = Math.cos(rad);
out[0] = a0 * c + a2 * s;
out[1] = a1 * c + a3 * s;
out[2] = a0 * -s + a2 * c;
out[3] = a1 * -s + a3 * c;
out[4] = a4;
out[5] = a5;
return out;
}
/**
* Scales the mat2d by the dimensions in the given vec2
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the matrix to translate
* @param {vec2} v the vec2 to scale the matrix by
* @returns {mat2d} out
**/
function scale$1(out, a, v) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5];
var v0 = v[0], v1 = v[1];
out[0] = a0 * v0;
out[1] = a1 * v0;
out[2] = a2 * v1;
out[3] = a3 * v1;
out[4] = a4;
out[5] = a5;
return out;
}
/**
* Translates the mat2d by the dimensions in the given vec2
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the matrix to translate
* @param {vec2} v the vec2 to translate the matrix by
* @returns {mat2d} out
**/
function translate$1(out, a, v) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5];
var v0 = v[0], v1 = v[1];
out[0] = a0;
out[1] = a1;
out[2] = a2;
out[3] = a3;
out[4] = a0 * v0 + a2 * v1 + a4;
out[5] = a1 * v0 + a3 * v1 + a5;
return out;
}
/**
* Creates a matrix from a given angle
* This is equivalent to (but much faster than):
*
* mat2d.identity(dest);
* mat2d.rotate(dest, dest, rad);
*
* @param {mat2d} out mat2d receiving operation result
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat2d} out
*/
function fromRotation$1(out, rad) {
var s = Math.sin(rad), c = Math.cos(rad);
out[0] = c;
out[1] = s;
out[2] = -s;
out[3] = c;
out[4] = 0;
out[5] = 0;
return out;
}
/**
* Creates a matrix from a vector scaling
* This is equivalent to (but much faster than):
*
* mat2d.identity(dest);
* mat2d.scale(dest, dest, vec);
*
* @param {mat2d} out mat2d receiving operation result
* @param {vec2} v Scaling vector
* @returns {mat2d} out
*/
function fromScaling$1(out, v) {
out[0] = v[0];
out[1] = 0;
out[2] = 0;
out[3] = v[1];
out[4] = 0;
out[5] = 0;
return out;
}
/**
* Creates a matrix from a vector translation
* This is equivalent to (but much faster than):
*
* mat2d.identity(dest);
* mat2d.translate(dest, dest, vec);
*
* @param {mat2d} out mat2d receiving operation result
* @param {vec2} v Translation vector
* @returns {mat2d} out
*/
function fromTranslation(out, v) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 1;
out[4] = v[0];
out[5] = v[1];
return out;
}
/**
* Returns a string representation of a mat2d
*
* @param {mat2d} a matrix to represent as a string
* @returns {String} string representation of the matrix
*/
function str$1(a) {
return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
a[3] + ', ' + a[4] + ', ' + a[5] + ')';
}
/**
* Returns Frobenius norm of a mat2d
*
* @param {mat2d} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
function frob$1(a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1))
}
/**
* Adds two mat2d's
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the first operand
* @param {mat2d} b the second operand
* @returns {mat2d} out
*/
function add$1(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
out[3] = a[3] + b[3];
out[4] = a[4] + b[4];
out[5] = a[5] + b[5];
return out;
}
/**
* Subtracts matrix b from matrix a
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the first operand
* @param {mat2d} b the second operand
* @returns {mat2d} out
*/
function subtract$1(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
out[3] = a[3] - b[3];
out[4] = a[4] - b[4];
out[5] = a[5] - b[5];
return out;
}
/**
* Multiply each element of the matrix by a scalar.
*
* @param {mat2d} out the receiving matrix
* @param {mat2d} a the matrix to scale
* @param {Number} b amount to scale the matrix's elements by
* @returns {mat2d} out
*/
function multiplyScalar$1(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
out[3] = a[3] * b;
out[4] = a[4] * b;
out[5] = a[5] * b;
return out;
}
/**
* Adds two mat2d's after multiplying each element of the second operand by a scalar value.
*
* @param {mat2d} out the receiving vector
* @param {mat2d} a the first operand
* @param {mat2d} b the second operand
* @param {Number} scale the amount to scale b's elements by before adding
* @returns {mat2d} out
*/
function multiplyScalarAndAdd$1(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
out[2] = a[2] + (b[2] * scale);
out[3] = a[3] + (b[3] * scale);
out[4] = a[4] + (b[4] * scale);
out[5] = a[5] + (b[5] * scale);
return out;
}
/**
* Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
*
* @param {mat2d} a The first matrix.
* @param {mat2d} b The second matrix.
* @returns {Boolean} True if the matrices are equal, false otherwise.
*/
function exactEquals$1(a, b) {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5];
}
/**
* Returns whether or not the matrices have approximately the same elements in the same position.
*
* @param {mat2d} a The first matrix.
* @param {mat2d} b The second matrix.
* @returns {Boolean} True if the matrices are equal, false otherwise.
*/
function equals$2(a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5];
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];
return (Math.abs(a0 - b0) <= EPSILON*Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
Math.abs(a1 - b1) <= EPSILON*Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
Math.abs(a2 - b2) <= EPSILON*Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
Math.abs(a3 - b3) <= EPSILON*Math.max(1.0, Math.abs(a3), Math.abs(b3)) &&
Math.abs(a4 - b4) <= EPSILON*Math.max(1.0, Math.abs(a4), Math.abs(b4)) &&
Math.abs(a5 - b5) <= EPSILON*Math.max(1.0, Math.abs(a5), Math.abs(b5)));
}
/**
* Alias for {@link mat2d.multiply}
* @function
*/
var mul$1 = multiply$1;
/**
* Alias for {@link mat2d.subtract}
* @function
*/
var sub$1 = subtract$1;
/**
* 3x3 Matrix
* @module mat3
*/
/**
* Creates a new identity mat3
*
* @returns {mat3} a new 3x3 matrix
*/
function create$2() {
var out = new ARRAY_TYPE(9);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 1;
out[5] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 1;
return out;
}
/**
* Copies the upper-left 3x3 values into the given mat3.
*
* @param {mat3} out the receiving 3x3 matrix
* @param {mat4} a the source 4x4 matrix
* @returns {mat3} out
*/
function fromMat4(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[4];
out[4] = a[5];
out[5] = a[6];
out[6] = a[8];
out[7] = a[9];
out[8] = a[10];
return out;
}
/**
* Creates a new mat3 initialized with values from an existing matrix
*
* @param {mat3} a matrix to clone
* @returns {mat3} a new 3x3 matrix
*/
function clone$3(a) {
var out = new ARRAY_TYPE(9);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
return out;
}
/**
* Copy the values from one mat3 to another
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
function copy$2(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
return out;
}
/**
* Create a new mat3 with the given values
*
* @param {Number} m00 Component in column 0, row 0 position (index 0)
* @param {Number} m01 Component in column 0, row 1 position (index 1)
* @param {Number} m02 Component in column 0, row 2 position (index 2)
* @param {Number} m10 Component in column 1, row 0 position (index 3)
* @param {Number} m11 Component in column 1, row 1 position (index 4)
* @param {Number} m12 Component in column 1, row 2 position (index 5)
* @param {Number} m20 Component in column 2, row 0 position (index 6)
* @param {Number} m21 Component in column 2, row 1 position (index 7)
* @param {Number} m22 Component in column 2, row 2 position (index 8)
* @returns {mat3} A new mat3
*/
function fromValues$2(m00, m01, m02, m10, m11, m12, m20, m21, m22) {
var out = new ARRAY_TYPE(9);
out[0] = m00;
out[1] = m01;
out[2] = m02;
out[3] = m10;
out[4] = m11;
out[5] = m12;
out[6] = m20;
out[7] = m21;
out[8] = m22;
return out;
}
/**
* Set the components of a mat3 to the given values
*
* @param {mat3} out the receiving matrix
* @param {Number} m00 Component in column 0, row 0 position (index 0)
* @param {Number} m01 Component in column 0, row 1 position (index 1)
* @param {Number} m02 Component in column 0, row 2 position (index 2)
* @param {Number} m10 Component in column 1, row 0 position (index 3)
* @param {Number} m11 Component in column 1, row 1 position (index 4)
* @param {Number} m12 Component in column 1, row 2 position (index 5)
* @param {Number} m20 Component in column 2, row 0 position (index 6)
* @param {Number} m21 Component in column 2, row 1 position (index 7)
* @param {Number} m22 Component in column 2, row 2 position (index 8)
* @returns {mat3} out
*/
function set$2(out, m00, m01, m02, m10, m11, m12, m20, m21, m22) {
out[0] = m00;
out[1] = m01;
out[2] = m02;
out[3] = m10;
out[4] = m11;
out[5] = m12;
out[6] = m20;
out[7] = m21;
out[8] = m22;
return out;
}
/**
* Set a mat3 to the identity matrix
*
* @param {mat3} out the receiving matrix
* @returns {mat3} out
*/
function identity$2(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 1;
out[5] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 1;
return out;
}
/**
* Transpose the values of a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
function transpose$1(out, a) {
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (out === a) {
var a01 = a[1], a02 = a[2], a12 = a[5];
out[1] = a[3];
out[2] = a[6];
out[3] = a01;
out[5] = a[7];
out[6] = a02;
out[7] = a12;
} else {
out[0] = a[0];
out[1] = a[3];
out[2] = a[6];
out[3] = a[1];
out[4] = a[4];
out[5] = a[7];
out[6] = a[2];
out[7] = a[5];
out[8] = a[8];
}
return out;
}
/**
* Inverts a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
function invert$2(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2];
var a10 = a[3], a11 = a[4], a12 = a[5];
var a20 = a[6], a21 = a[7], a22 = a[8];
var b01 = a22 * a11 - a12 * a21;
var b11 = -a22 * a10 + a12 * a20;
var b21 = a21 * a10 - a11 * a20;
// Calculate the determinant
var det = a00 * b01 + a01 * b11 + a02 * b21;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = b01 * det;
out[1] = (-a22 * a01 + a02 * a21) * det;
out[2] = (a12 * a01 - a02 * a11) * det;
out[3] = b11 * det;
out[4] = (a22 * a00 - a02 * a20) * det;
out[5] = (-a12 * a00 + a02 * a10) * det;
out[6] = b21 * det;
out[7] = (-a21 * a00 + a01 * a20) * det;
out[8] = (a11 * a00 - a01 * a10) * det;
return out;
}
/**
* Calculates the adjugate of a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the source matrix
* @returns {mat3} out
*/
function adjoint$1(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2];
var a10 = a[3], a11 = a[4], a12 = a[5];
var a20 = a[6], a21 = a[7], a22 = a[8];
out[0] = (a11 * a22 - a12 * a21);
out[1] = (a02 * a21 - a01 * a22);
out[2] = (a01 * a12 - a02 * a11);
out[3] = (a12 * a20 - a10 * a22);
out[4] = (a00 * a22 - a02 * a20);
out[5] = (a02 * a10 - a00 * a12);
out[6] = (a10 * a21 - a11 * a20);
out[7] = (a01 * a20 - a00 * a21);
out[8] = (a00 * a11 - a01 * a10);
return out;
}
/**
* Calculates the determinant of a mat3
*
* @param {mat3} a the source matrix
* @returns {Number} determinant of a
*/
function determinant$2(a) {
var a00 = a[0], a01 = a[1], a02 = a[2];
var a10 = a[3], a11 = a[4], a12 = a[5];
var a20 = a[6], a21 = a[7], a22 = a[8];
return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
}
/**
* Multiplies two mat3's
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the first operand
* @param {mat3} b the second operand
* @returns {mat3} out
*/
function multiply$2(out, a, b) {
var a00 = a[0], a01 = a[1], a02 = a[2];
var a10 = a[3], a11 = a[4], a12 = a[5];
var a20 = a[6], a21 = a[7], a22 = a[8];
var b00 = b[0], b01 = b[1], b02 = b[2];
var b10 = b[3], b11 = b[4], b12 = b[5];
var b20 = b[6], b21 = b[7], b22 = b[8];
out[0] = b00 * a00 + b01 * a10 + b02 * a20;
out[1] = b00 * a01 + b01 * a11 + b02 * a21;
out[2] = b00 * a02 + b01 * a12 + b02 * a22;
out[3] = b10 * a00 + b11 * a10 + b12 * a20;
out[4] = b10 * a01 + b11 * a11 + b12 * a21;
out[5] = b10 * a02 + b11 * a12 + b12 * a22;
out[6] = b20 * a00 + b21 * a10 + b22 * a20;
out[7] = b20 * a01 + b21 * a11 + b22 * a21;
out[8] = b20 * a02 + b21 * a12 + b22 * a22;
return out;
}
/**
* Translate a mat3 by the given vector
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the matrix to translate
* @param {vec2} v vector to translate by
* @returns {mat3} out
*/
function translate$2(out, a, v) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8],
x = v[0], y = v[1];
out[0] = a00;
out[1] = a01;
out[2] = a02;
out[3] = a10;
out[4] = a11;
out[5] = a12;
out[6] = x * a00 + y * a10 + a20;
out[7] = x * a01 + y * a11 + a21;
out[8] = x * a02 + y * a12 + a22;
return out;
}
/**
* Rotates a mat3 by the given angle
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat3} out
*/
function rotate$2(out, a, rad) {
var a00 = a[0], a01 = a[1], a02 = a[2],
a10 = a[3], a11 = a[4], a12 = a[5],
a20 = a[6], a21 = a[7], a22 = a[8],
s = Math.sin(rad),
c = Math.cos(rad);
out[0] = c * a00 + s * a10;
out[1] = c * a01 + s * a11;
out[2] = c * a02 + s * a12;
out[3] = c * a10 - s * a00;
out[4] = c * a11 - s * a01;
out[5] = c * a12 - s * a02;
out[6] = a20;
out[7] = a21;
out[8] = a22;
return out;
}
/**
* Scales the mat3 by the dimensions in the given vec2
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the matrix to rotate
* @param {vec2} v the vec2 to scale the matrix by
* @returns {mat3} out
**/
function scale$2(out, a, v) {
var x = v[0], y = v[1];
out[0] = x * a[0];
out[1] = x * a[1];
out[2] = x * a[2];
out[3] = y * a[3];
out[4] = y * a[4];
out[5] = y * a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
return out;
}
/**
* Creates a matrix from a vector translation
* This is equivalent to (but much faster than):
*
* mat3.identity(dest);
* mat3.translate(dest, dest, vec);
*
* @param {mat3} out mat3 receiving operation result
* @param {vec2} v Translation vector
* @returns {mat3} out
*/
function fromTranslation$1(out, v) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 1;
out[5] = 0;
out[6] = v[0];
out[7] = v[1];
out[8] = 1;
return out;
}
/**
* Creates a matrix from a given angle
* This is equivalent to (but much faster than):
*
* mat3.identity(dest);
* mat3.rotate(dest, dest, rad);
*
* @param {mat3} out mat3 receiving operation result
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat3} out
*/
function fromRotation$2(out, rad) {
var s = Math.sin(rad), c = Math.cos(rad);
out[0] = c;
out[1] = s;
out[2] = 0;
out[3] = -s;
out[4] = c;
out[5] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 1;
return out;
}
/**
* Creates a matrix from a vector scaling
* This is equivalent to (but much faster than):
*
* mat3.identity(dest);
* mat3.scale(dest, dest, vec);
*
* @param {mat3} out mat3 receiving operation result
* @param {vec2} v Scaling vector
* @returns {mat3} out
*/
function fromScaling$2(out, v) {
out[0] = v[0];
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = v[1];
out[5] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 1;
return out;
}
/**
* Copies the values from a mat2d into a mat3
*
* @param {mat3} out the receiving matrix
* @param {mat2d} a the matrix to copy
* @returns {mat3} out
**/
function fromMat2d(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = 0;
out[3] = a[2];
out[4] = a[3];
out[5] = 0;
out[6] = a[4];
out[7] = a[5];
out[8] = 1;
return out;
}
/**
* Calculates a 3x3 matrix from the given quaternion
*
* @param {mat3} out mat3 receiving operation result
* @param {quat} q Quaternion to create matrix from
*
* @returns {mat3} out
*/
function fromQuat(out, q) {
var x = q[0], y = q[1], z = q[2], w = q[3];
var x2 = x + x;
var y2 = y + y;
var z2 = z + z;
var xx = x * x2;
var yx = y * x2;
var yy = y * y2;
var zx = z * x2;
var zy = z * y2;
var zz = z * z2;
var wx = w * x2;
var wy = w * y2;
var wz = w * z2;
out[0] = 1 - yy - zz;
out[3] = yx - wz;
out[6] = zx + wy;
out[1] = yx + wz;
out[4] = 1 - xx - zz;
out[7] = zy - wx;
out[2] = zx - wy;
out[5] = zy + wx;
out[8] = 1 - xx - yy;
return out;
}
/**
* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
*
* @param {mat3} out mat3 receiving operation result
* @param {mat4} a Mat4 to derive the normal matrix from
*
* @returns {mat3} out
*/
function normalFromMat4(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
var b00 = a00 * a11 - a01 * a10;
var b01 = a00 * a12 - a02 * a10;
var b02 = a00 * a13 - a03 * a10;
var b03 = a01 * a12 - a02 * a11;
var b04 = a01 * a13 - a03 * a11;
var b05 = a02 * a13 - a03 * a12;
var b06 = a20 * a31 - a21 * a30;
var b07 = a20 * a32 - a22 * a30;
var b08 = a20 * a33 - a23 * a30;
var b09 = a21 * a32 - a22 * a31;
var b10 = a21 * a33 - a23 * a31;
var b11 = a22 * a33 - a23 * a32;
// Calculate the determinant
var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
return out;
}
/**
* Generates a 2D projection matrix with the given bounds
*
* @param {mat3} out mat3 frustum matrix will be written into
* @param {number} width Width of your gl context
* @param {number} height Height of gl context
* @returns {mat3} out
*/
function projection(out, width, height) {
out[0] = 2 / width;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = -2 / height;
out[5] = 0;
out[6] = -1;
out[7] = 1;
out[8] = 1;
return out;
}
/**
* Returns a string representation of a mat3
*
* @param {mat3} a matrix to represent as a string
* @returns {String} string representation of the matrix
*/
function str$2(a) {
return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
a[3] + ', ' + a[4] + ', ' + a[5] + ', ' +
a[6] + ', ' + a[7] + ', ' + a[8] + ')';
}
/**
* Returns Frobenius norm of a mat3
*
* @param {mat3} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
function frob$2(a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2)))
}
/**
* Adds two mat3's
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the first operand
* @param {mat3} b the second operand
* @returns {mat3} out
*/
function add$2(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
out[3] = a[3] + b[3];
out[4] = a[4] + b[4];
out[5] = a[5] + b[5];
out[6] = a[6] + b[6];
out[7] = a[7] + b[7];
out[8] = a[8] + b[8];
return out;
}
/**
* Subtracts matrix b from matrix a
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the first operand
* @param {mat3} b the second operand
* @returns {mat3} out
*/
function subtract$2(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
out[3] = a[3] - b[3];
out[4] = a[4] - b[4];
out[5] = a[5] - b[5];
out[6] = a[6] - b[6];
out[7] = a[7] - b[7];
out[8] = a[8] - b[8];
return out;
}
/**
* Multiply each element of the matrix by a scalar.
*
* @param {mat3} out the receiving matrix
* @param {mat3} a the matrix to scale
* @param {Number} b amount to scale the matrix's elements by
* @returns {mat3} out
*/
function multiplyScalar$2(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
out[3] = a[3] * b;
out[4] = a[4] * b;
out[5] = a[5] * b;
out[6] = a[6] * b;
out[7] = a[7] * b;
out[8] = a[8] * b;
return out;
}
/**
* Adds two mat3's after multiplying each element of the second operand by a scalar value.
*
* @param {mat3} out the receiving vector
* @param {mat3} a the first operand
* @param {mat3} b the second operand
* @param {Number} scale the amount to scale b's elements by before adding
* @returns {mat3} out
*/
function multiplyScalarAndAdd$2(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
out[2] = a[2] + (b[2] * scale);
out[3] = a[3] + (b[3] * scale);
out[4] = a[4] + (b[4] * scale);
out[5] = a[5] + (b[5] * scale);
out[6] = a[6] + (b[6] * scale);
out[7] = a[7] + (b[7] * scale);
out[8] = a[8] + (b[8] * scale);
return out;
}
/**
* Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
*
* @param {mat3} a The first matrix.
* @param {mat3} b The second matrix.
* @returns {Boolean} True if the matrices are equal, false otherwise.
*/
function exactEquals$2(a, b) {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] &&
a[3] === b[3] && a[4] === b[4] && a[5] === b[5] &&
a[6] === b[6] && a[7] === b[7] && a[8] === b[8];
}
/**
* Returns whether or not the matrices have approximately the same elements in the same position.
*
* @param {mat3} a The first matrix.
* @param {mat3} b The second matrix.
* @returns {Boolean} True if the matrices are equal, false otherwise.
*/
function equals$3(a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], a6 = a[6], a7 = a[7], a8 = a[8];
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5], b6 = b[6], b7 = b[7], b8 = b[8];
return (Math.abs(a0 - b0) <= EPSILON*Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
Math.abs(a1 - b1) <= EPSILON*Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
Math.abs(a2 - b2) <= EPSILON*Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
Math.abs(a3 - b3) <= EPSILON*Math.max(1.0, Math.abs(a3), Math.abs(b3)) &&
Math.abs(a4 - b4) <= EPSILON*Math.max(1.0, Math.abs(a4), Math.abs(b4)) &&
Math.abs(a5 - b5) <= EPSILON*Math.max(1.0, Math.abs(a5), Math.abs(b5)) &&
Math.abs(a6 - b6) <= EPSILON*Math.max(1.0, Math.abs(a6), Math.abs(b6)) &&
Math.abs(a7 - b7) <= EPSILON*Math.max(1.0, Math.abs(a7), Math.abs(b7)) &&
Math.abs(a8 - b8) <= EPSILON*Math.max(1.0, Math.abs(a8), Math.abs(b8)));
}
/**
* Alias for {@link mat3.multiply}
* @function
*/
var mul$2 = multiply$2;
/**
* Alias for {@link mat3.subtract}
* @function
*/
var sub$2 = subtract$2;
/**
* 4x4 Matrix<br>Format: column-major, when typed out it looks like row-major<br>The matrices are being post multiplied.
* @module mat4
*/
/**
* Creates a new identity mat4
*
* @returns {mat4} a new 4x4 matrix
*/
function create$3() {
var out = new ARRAY_TYPE(16);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
}
/**
* Creates a new mat4 initialized with values from an existing matrix
*
* @param {mat4} a matrix to clone
* @returns {mat4} a new 4x4 matrix
*/
function clone$4(a) {
var out = new ARRAY_TYPE(16);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
return out;
}
/**
* Copy the values from one mat4 to another
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
function copy$3(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
return out;
}
/**
* Create a new mat4 with the given values
*
* @param {Number} m00 Component in column 0, row 0 position (index 0)
* @param {Number} m01 Component in column 0, row 1 position (index 1)
* @param {Number} m02 Component in column 0, row 2 position (index 2)
* @param {Number} m03 Component in column 0, row 3 position (index 3)
* @param {Number} m10 Component in column 1, row 0 position (index 4)
* @param {Number} m11 Component in column 1, row 1 position (index 5)
* @param {Number} m12 Component in column 1, row 2 position (index 6)
* @param {Number} m13 Component in column 1, row 3 position (index 7)
* @param {Number} m20 Component in column 2, row 0 position (index 8)
* @param {Number} m21 Component in column 2, row 1 position (index 9)
* @param {Number} m22 Component in column 2, row 2 position (index 10)
* @param {Number} m23 Component in column 2, row 3 position (index 11)
* @param {Number} m30 Component in column 3, row 0 position (index 12)
* @param {Number} m31 Component in column 3, row 1 position (index 13)
* @param {Number} m32 Component in column 3, row 2 position (index 14)
* @param {Number} m33 Component in column 3, row 3 position (index 15)
* @returns {mat4} A new mat4
*/
function fromValues$3(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
var out = new ARRAY_TYPE(16);
out[0] = m00;
out[1] = m01;
out[2] = m02;
out[3] = m03;
out[4] = m10;
out[5] = m11;
out[6] = m12;
out[7] = m13;
out[8] = m20;
out[9] = m21;
out[10] = m22;
out[11] = m23;
out[12] = m30;
out[13] = m31;
out[14] = m32;
out[15] = m33;
return out;
}
/**
* Set the components of a mat4 to the given values
*
* @param {mat4} out the receiving matrix
* @param {Number} m00 Component in column 0, row 0 position (index 0)
* @param {Number} m01 Component in column 0, row 1 position (index 1)
* @param {Number} m02 Component in column 0, row 2 position (index 2)
* @param {Number} m03 Component in column 0, row 3 position (index 3)
* @param {Number} m10 Component in column 1, row 0 position (index 4)
* @param {Number} m11 Component in column 1, row 1 position (index 5)
* @param {Number} m12 Component in column 1, row 2 position (index 6)
* @param {Number} m13 Component in column 1, row 3 position (index 7)
* @param {Number} m20 Component in column 2, row 0 position (index 8)
* @param {Number} m21 Component in column 2, row 1 position (index 9)
* @param {Number} m22 Component in column 2, row 2 position (index 10)
* @param {Number} m23 Component in column 2, row 3 position (index 11)
* @param {Number} m30 Component in column 3, row 0 position (index 12)
* @param {Number} m31 Component in column 3, row 1 position (index 13)
* @param {Number} m32 Component in column 3, row 2 position (index 14)
* @param {Number} m33 Component in column 3, row 3 position (index 15)
* @returns {mat4} out
*/
function set$3(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
out[0] = m00;
out[1] = m01;
out[2] = m02;
out[3] = m03;
out[4] = m10;
out[5] = m11;
out[6] = m12;
out[7] = m13;
out[8] = m20;
out[9] = m21;
out[10] = m22;
out[11] = m23;
out[12] = m30;
out[13] = m31;
out[14] = m32;
out[15] = m33;
return out;
}
/**
* Set a mat4 to the identity matrix
*
* @param {mat4} out the receiving matrix
* @returns {mat4} out
*/
function identity$3(out) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
}
/**
* Transpose the values of a mat4
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
function transpose$2(out, a) {
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (out === a) {
var a01 = a[1], a02 = a[2], a03 = a[3];
var a12 = a[6], a13 = a[7];
var a23 = a[11];
out[1] = a[4];
out[2] = a[8];
out[3] = a[12];
out[4] = a01;
out[6] = a[9];
out[7] = a[13];
out[8] = a02;
out[9] = a12;
out[11] = a[14];
out[12] = a03;
out[13] = a13;
out[14] = a23;
} else {
out[0] = a[0];
out[1] = a[4];
out[2] = a[8];
out[3] = a[12];
out[4] = a[1];
out[5] = a[5];
out[6] = a[9];
out[7] = a[13];
out[8] = a[2];
out[9] = a[6];
out[10] = a[10];
out[11] = a[14];
out[12] = a[3];
out[13] = a[7];
out[14] = a[11];
out[15] = a[15];
}
return out;
}
/**
* Inverts a mat4
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
function invert$3(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
var b00 = a00 * a11 - a01 * a10;
var b01 = a00 * a12 - a02 * a10;
var b02 = a00 * a13 - a03 * a10;
var b03 = a01 * a12 - a02 * a11;
var b04 = a01 * a13 - a03 * a11;
var b05 = a02 * a13 - a03 * a12;
var b06 = a20 * a31 - a21 * a30;
var b07 = a20 * a32 - a22 * a30;
var b08 = a20 * a33 - a23 * a30;
var b09 = a21 * a32 - a22 * a31;
var b10 = a21 * a33 - a23 * a31;
var b11 = a22 * a33 - a23 * a32;
// Calculate the determinant
var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
return out;
}
/**
* Calculates the adjugate of a mat4
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the source matrix
* @returns {mat4} out
*/
function adjoint$2(out, a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
return out;
}
/**
* Calculates the determinant of a mat4
*
* @param {mat4} a the source matrix
* @returns {Number} determinant of a
*/
function determinant$3(a) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
var b00 = a00 * a11 - a01 * a10;
var b01 = a00 * a12 - a02 * a10;
var b02 = a00 * a13 - a03 * a10;
var b03 = a01 * a12 - a02 * a11;
var b04 = a01 * a13 - a03 * a11;
var b05 = a02 * a13 - a03 * a12;
var b06 = a20 * a31 - a21 * a30;
var b07 = a20 * a32 - a22 * a30;
var b08 = a20 * a33 - a23 * a30;
var b09 = a21 * a32 - a22 * a31;
var b10 = a21 * a33 - a23 * a31;
var b11 = a22 * a33 - a23 * a32;
// Calculate the determinant
return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
}
/**
* Multiplies two mat4s
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the first operand
* @param {mat4} b the second operand
* @returns {mat4} out
*/
function multiply$3(out, a, b) {
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
// Cache only the current line of the second matrix
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
return out;
}
/**
* Translate a mat4 by the given vector
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to translate
* @param {vec3} v vector to translate by
* @returns {mat4} out
*/
function translate$3(out, a, v) {
var x = v[0], y = v[1], z = v[2];
var a00, a01, a02, a03;
var a10, a11, a12, a13;
var a20, a21, a22, a23;
if (a === out) {
out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
} else {
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
out[12] = a00 * x + a10 * y + a20 * z + a[12];
out[13] = a01 * x + a11 * y + a21 * z + a[13];
out[14] = a02 * x + a12 * y + a22 * z + a[14];
out[15] = a03 * x + a13 * y + a23 * z + a[15];
}
return out;
}
/**
* Scales the mat4 by the dimensions in the given vec3 not using vectorization
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to scale
* @param {vec3} v the vec3 to scale the matrix by
* @returns {mat4} out
**/
function scale$3(out, a, v) {
var x = v[0], y = v[1], z = v[2];
out[0] = a[0] * x;
out[1] = a[1] * x;
out[2] = a[2] * x;
out[3] = a[3] * x;
out[4] = a[4] * y;
out[5] = a[5] * y;
out[6] = a[6] * y;
out[7] = a[7] * y;
out[8] = a[8] * z;
out[9] = a[9] * z;
out[10] = a[10] * z;
out[11] = a[11] * z;
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
return out;
}
/**
* Rotates a mat4 by the given angle around the given axis
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @param {vec3} axis the axis to rotate around
* @returns {mat4} out
*/
function rotate$3(out, a, rad, axis) {
var x = axis[0], y = axis[1], z = axis[2];
var len = Math.sqrt(x * x + y * y + z * z);
var s, c, t;
var a00, a01, a02, a03;
var a10, a11, a12, a13;
var a20, a21, a22, a23;
var b00, b01, b02;
var b10, b11, b12;
var b20, b21, b22;
if (len < EPSILON) { return null; }
len = 1 / len;
x *= len;
y *= len;
z *= len;
s = Math.sin(rad);
c = Math.cos(rad);
t = 1 - c;
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
// Construct the elements of the rotation matrix
b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
// Perform rotation-specific matrix multiplication
out[0] = a00 * b00 + a10 * b01 + a20 * b02;
out[1] = a01 * b00 + a11 * b01 + a21 * b02;
out[2] = a02 * b00 + a12 * b01 + a22 * b02;
out[3] = a03 * b00 + a13 * b01 + a23 * b02;
out[4] = a00 * b10 + a10 * b11 + a20 * b12;
out[5] = a01 * b10 + a11 * b11 + a21 * b12;
out[6] = a02 * b10 + a12 * b11 + a22 * b12;
out[7] = a03 * b10 + a13 * b11 + a23 * b12;
out[8] = a00 * b20 + a10 * b21 + a20 * b22;
out[9] = a01 * b20 + a11 * b21 + a21 * b22;
out[10] = a02 * b20 + a12 * b21 + a22 * b22;
out[11] = a03 * b20 + a13 * b21 + a23 * b22;
if (a !== out) { // If the source and destination differ, copy the unchanged last row
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
return out;
}
/**
* Rotates a matrix by the given angle around the X axis
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
function rotateX(out, a, rad) {
var s = Math.sin(rad);
var c = Math.cos(rad);
var a10 = a[4];
var a11 = a[5];
var a12 = a[6];
var a13 = a[7];
var a20 = a[8];
var a21 = a[9];
var a22 = a[10];
var a23 = a[11];
if (a !== out) { // If the source and destination differ, copy the unchanged rows
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
// Perform axis-specific matrix multiplication
out[4] = a10 * c + a20 * s;
out[5] = a11 * c + a21 * s;
out[6] = a12 * c + a22 * s;
out[7] = a13 * c + a23 * s;
out[8] = a20 * c - a10 * s;
out[9] = a21 * c - a11 * s;
out[10] = a22 * c - a12 * s;
out[11] = a23 * c - a13 * s;
return out;
}
/**
* Rotates a matrix by the given angle around the Y axis
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
function rotateY(out, a, rad) {
var s = Math.sin(rad);
var c = Math.cos(rad);
var a00 = a[0];
var a01 = a[1];
var a02 = a[2];
var a03 = a[3];
var a20 = a[8];
var a21 = a[9];
var a22 = a[10];
var a23 = a[11];
if (a !== out) { // If the source and destination differ, copy the unchanged rows
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
// Perform axis-specific matrix multiplication
out[0] = a00 * c - a20 * s;
out[1] = a01 * c - a21 * s;
out[2] = a02 * c - a22 * s;
out[3] = a03 * c - a23 * s;
out[8] = a00 * s + a20 * c;
out[9] = a01 * s + a21 * c;
out[10] = a02 * s + a22 * c;
out[11] = a03 * s + a23 * c;
return out;
}
/**
* Rotates a matrix by the given angle around the Z axis
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to rotate
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
function rotateZ(out, a, rad) {
var s = Math.sin(rad);
var c = Math.cos(rad);
var a00 = a[0];
var a01 = a[1];
var a02 = a[2];
var a03 = a[3];
var a10 = a[4];
var a11 = a[5];
var a12 = a[6];
var a13 = a[7];
if (a !== out) { // If the source and destination differ, copy the unchanged last row
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
// Perform axis-specific matrix multiplication
out[0] = a00 * c + a10 * s;
out[1] = a01 * c + a11 * s;
out[2] = a02 * c + a12 * s;
out[3] = a03 * c + a13 * s;
out[4] = a10 * c - a00 * s;
out[5] = a11 * c - a01 * s;
out[6] = a12 * c - a02 * s;
out[7] = a13 * c - a03 * s;
return out;
}
/**
* Creates a matrix from a vector translation
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.translate(dest, dest, vec);
*
* @param {mat4} out mat4 receiving operation result
* @param {vec3} v Translation vector
* @returns {mat4} out
*/
function fromTranslation$2(out, v) {
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = v[0];
out[13] = v[1];
out[14] = v[2];
out[15] = 1;
return out;
}
/**
* Creates a matrix from a vector scaling
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.scale(dest, dest, vec);
*
* @param {mat4} out mat4 receiving operation result
* @param {vec3} v Scaling vector
* @returns {mat4} out
*/
function fromScaling$3(out, v) {
out[0] = v[0];
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = v[1];
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = v[2];
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
}
/**
* Creates a matrix from a given angle around a given axis
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.rotate(dest, dest, rad, axis);
*
* @param {mat4} out mat4 receiving operation result
* @param {Number} rad the angle to rotate the matrix by
* @param {vec3} axis the axis to rotate around
* @returns {mat4} out
*/
function fromRotation$3(out, rad, axis) {
var x = axis[0], y = axis[1], z = axis[2];
var len = Math.sqrt(x * x + y * y + z * z);
var s, c, t;
if (len < EPSILON) { return null; }
len = 1 / len;
x *= len;
y *= len;
z *= len;
s = Math.sin(rad);
c = Math.cos(rad);
t = 1 - c;
// Perform rotation-specific matrix multiplication
out[0] = x * x * t + c;
out[1] = y * x * t + z * s;
out[2] = z * x * t - y * s;
out[3] = 0;
out[4] = x * y * t - z * s;
out[5] = y * y * t + c;
out[6] = z * y * t + x * s;
out[7] = 0;
out[8] = x * z * t + y * s;
out[9] = y * z * t - x * s;
out[10] = z * z * t + c;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
}
/**
* Creates a matrix from the given angle around the X axis
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.rotateX(dest, dest, rad);
*
* @param {mat4} out mat4 receiving operation result
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
function fromXRotation(out, rad) {
var s = Math.sin(rad);
var c = Math.cos(rad);
// Perform axis-specific matrix multiplication
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = c;
out[6] = s;
out[7] = 0;
out[8] = 0;
out[9] = -s;
out[10] = c;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
}
/**
* Creates a matrix from the given angle around the Y axis
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.rotateY(dest, dest, rad);
*
* @param {mat4} out mat4 receiving operation result
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
function fromYRotation(out, rad) {
var s = Math.sin(rad);
var c = Math.cos(rad);
// Perform axis-specific matrix multiplication
out[0] = c;
out[1] = 0;
out[2] = -s;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = s;
out[9] = 0;
out[10] = c;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
}
/**
* Creates a matrix from the given angle around the Z axis
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.rotateZ(dest, dest, rad);
*
* @param {mat4} out mat4 receiving operation result
* @param {Number} rad the angle to rotate the matrix by
* @returns {mat4} out
*/
function fromZRotation(out, rad) {
var s = Math.sin(rad);
var c = Math.cos(rad);
// Perform axis-specific matrix multiplication
out[0] = c;
out[1] = s;
out[2] = 0;
out[3] = 0;
out[4] = -s;
out[5] = c;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
}
/**
* Creates a matrix from a quaternion rotation and vector translation
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.translate(dest, vec);
* let quatMat = mat4.create();
* quat4.toMat4(quat, quatMat);
* mat4.multiply(dest, quatMat);
*
* @param {mat4} out mat4 receiving operation result
* @param {quat4} q Rotation quaternion
* @param {vec3} v Translation vector
* @returns {mat4} out
*/
function fromRotationTranslation(out, q, v) {
// Quaternion math
var x = q[0], y = q[1], z = q[2], w = q[3];
var x2 = x + x;
var y2 = y + y;
var z2 = z + z;
var xx = x * x2;
var xy = x * y2;
var xz = x * z2;
var yy = y * y2;
var yz = y * z2;
var zz = z * z2;
var wx = w * x2;
var wy = w * y2;
var wz = w * z2;
out[0] = 1 - (yy + zz);
out[1] = xy + wz;
out[2] = xz - wy;
out[3] = 0;
out[4] = xy - wz;
out[5] = 1 - (xx + zz);
out[6] = yz + wx;
out[7] = 0;
out[8] = xz + wy;
out[9] = yz - wx;
out[10] = 1 - (xx + yy);
out[11] = 0;
out[12] = v[0];
out[13] = v[1];
out[14] = v[2];
out[15] = 1;
return out;
}
/**
* Creates a new mat4 from a dual quat.
*
* @param {mat4} out Matrix
* @param {quat2} a Dual Quaternion
* @returns {mat4} mat4 receiving operation result
*/
function fromQuat2(out, a) {
var translation = new ARRAY_TYPE(3);
var bx = -a[0], by = -a[1], bz = -a[2], bw = a[3],
ax = a[4], ay = a[5], az = a[6], aw = a[7];
var magnitude = bx * bx + by * by + bz * bz + bw * bw;
//Only scale if it makes sense
if (magnitude > 0) {
translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;
translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;
translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;
} else {
translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
}
fromRotationTranslation(out, a, translation);
return out;
}
/**
* Returns the translation vector component of a transformation
* matrix. If a matrix is built with fromRotationTranslation,
* the returned vector will be the same as the translation vector
* originally supplied.
* @param {vec3} out Vector to receive translation component
* @param {mat4} mat Matrix to be decomposed (input)
* @return {vec3} out
*/
function getTranslation(out, mat) {
out[0] = mat[12];
out[1] = mat[13];
out[2] = mat[14];
return out;
}
/**
* Returns the scaling factor component of a transformation
* matrix. If a matrix is built with fromRotationTranslationScale
* with a normalized Quaternion paramter, the returned vector will be
* the same as the scaling vector
* originally supplied.
* @param {vec3} out Vector to receive scaling factor component
* @param {mat4} mat Matrix to be decomposed (input)
* @return {vec3} out
*/
function getScaling(out, mat) {
var m11 = mat[0];
var m12 = mat[1];
var m13 = mat[2];
var m21 = mat[4];
var m22 = mat[5];
var m23 = mat[6];
var m31 = mat[8];
var m32 = mat[9];
var m33 = mat[10];
out[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);
out[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);
out[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);
return out;
}
/**
* Returns a quaternion representing the rotational component
* of a transformation matrix. If a matrix is built with
* fromRotationTranslation, the returned quaternion will be the
* same as the quaternion originally supplied.
* @param {quat} out Quaternion to receive the rotation component
* @param {mat4} mat Matrix to be decomposed (input)
* @return {quat} out
*/
function getRotation(out, mat) {
// Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
var trace = mat[0] + mat[5] + mat[10];
var S = 0;
if (trace > 0) {
S = Math.sqrt(trace + 1.0) * 2;
out[3] = 0.25 * S;
out[0] = (mat[6] - mat[9]) / S;
out[1] = (mat[8] - mat[2]) / S;
out[2] = (mat[1] - mat[4]) / S;
} else if ((mat[0] > mat[5]) && (mat[0] > mat[10])) {
S = Math.sqrt(1.0 + mat[0] - mat[5] - mat[10]) * 2;
out[3] = (mat[6] - mat[9]) / S;
out[0] = 0.25 * S;
out[1] = (mat[1] + mat[4]) / S;
out[2] = (mat[8] + mat[2]) / S;
} else if (mat[5] > mat[10]) {
S = Math.sqrt(1.0 + mat[5] - mat[0] - mat[10]) * 2;
out[3] = (mat[8] - mat[2]) / S;
out[0] = (mat[1] + mat[4]) / S;
out[1] = 0.25 * S;
out[2] = (mat[6] + mat[9]) / S;
} else {
S = Math.sqrt(1.0 + mat[10] - mat[0] - mat[5]) * 2;
out[3] = (mat[1] - mat[4]) / S;
out[0] = (mat[8] + mat[2]) / S;
out[1] = (mat[6] + mat[9]) / S;
out[2] = 0.25 * S;
}
return out;
}
/**
* Creates a matrix from a quaternion rotation, vector translation and vector scale
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.translate(dest, vec);
* let quatMat = mat4.create();
* quat4.toMat4(quat, quatMat);
* mat4.multiply(dest, quatMat);
* mat4.scale(dest, scale)
*
* @param {mat4} out mat4 receiving operation result
* @param {quat4} q Rotation quaternion
* @param {vec3} v Translation vector
* @param {vec3} s Scaling vector
* @returns {mat4} out
*/
function fromRotationTranslationScale(out, q, v, s) {
// Quaternion math
var x = q[0], y = q[1], z = q[2], w = q[3];
var x2 = x + x;
var y2 = y + y;
var z2 = z + z;
var xx = x * x2;
var xy = x * y2;
var xz = x * z2;
var yy = y * y2;
var yz = y * z2;
var zz = z * z2;
var wx = w * x2;
var wy = w * y2;
var wz = w * z2;
var sx = s[0];
var sy = s[1];
var sz = s[2];
out[0] = (1 - (yy + zz)) * sx;
out[1] = (xy + wz) * sx;
out[2] = (xz - wy) * sx;
out[3] = 0;
out[4] = (xy - wz) * sy;
out[5] = (1 - (xx + zz)) * sy;
out[6] = (yz + wx) * sy;
out[7] = 0;
out[8] = (xz + wy) * sz;
out[9] = (yz - wx) * sz;
out[10] = (1 - (xx + yy)) * sz;
out[11] = 0;
out[12] = v[0];
out[13] = v[1];
out[14] = v[2];
out[15] = 1;
return out;
}
/**
* Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
* This is equivalent to (but much faster than):
*
* mat4.identity(dest);
* mat4.translate(dest, vec);
* mat4.translate(dest, origin);
* let quatMat = mat4.create();
* quat4.toMat4(quat, quatMat);
* mat4.multiply(dest, quatMat);
* mat4.scale(dest, scale)
* mat4.translate(dest, negativeOrigin);
*
* @param {mat4} out mat4 receiving operation result
* @param {quat4} q Rotation quaternion
* @param {vec3} v Translation vector
* @param {vec3} s Scaling vector
* @param {vec3} o The origin vector around which to scale and rotate
* @returns {mat4} out
*/
function fromRotationTranslationScaleOrigin(out, q, v, s, o) {
// Quaternion math
var x = q[0], y = q[1], z = q[2], w = q[3];
var x2 = x + x;
var y2 = y + y;
var z2 = z + z;
var xx = x * x2;
var xy = x * y2;
var xz = x * z2;
var yy = y * y2;
var yz = y * z2;
var zz = z * z2;
var wx = w * x2;
var wy = w * y2;
var wz = w * z2;
var sx = s[0];
var sy = s[1];
var sz = s[2];
var ox = o[0];
var oy = o[1];
var oz = o[2];
var out0 = (1 - (yy + zz)) * sx;
var out1 = (xy + wz) * sx;
var out2 = (xz - wy) * sx;
var out4 = (xy - wz) * sy;
var out5 = (1 - (xx + zz)) * sy;
var out6 = (yz + wx) * sy;
var out8 = (xz + wy) * sz;
var out9 = (yz - wx) * sz;
var out10 = (1 - (xx + yy)) * sz;
out[0] = out0;
out[1] = out1;
out[2] = out2;
out[3] = 0;
out[4] = out4;
out[5] = out5;
out[6] = out6;
out[7] = 0;
out[8] = out8;
out[9] = out9;
out[10] = out10;
out[11] = 0;
out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);
out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);
out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);
out[15] = 1;
return out;
}
/**
* Calculates a 4x4 matrix from the given quaternion
*
* @param {mat4} out mat4 receiving operation result
* @param {quat} q Quaternion to create matrix from
*
* @returns {mat4} out
*/
function fromQuat$1(out, q) {
var x = q[0], y = q[1], z = q[2], w = q[3];
var x2 = x + x;
var y2 = y + y;
var z2 = z + z;
var xx = x * x2;
var yx = y * x2;
var yy = y * y2;
var zx = z * x2;
var zy = z * y2;
var zz = z * z2;
var wx = w * x2;
var wy = w * y2;
var wz = w * z2;
out[0] = 1 - yy - zz;
out[1] = yx + wz;
out[2] = zx - wy;
out[3] = 0;
out[4] = yx - wz;
out[5] = 1 - xx - zz;
out[6] = zy + wx;
out[7] = 0;
out[8] = zx + wy;
out[9] = zy - wx;
out[10] = 1 - xx - yy;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
return out;
}
/**
* Generates a frustum matrix with the given bounds
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {Number} left Left bound of the frustum
* @param {Number} right Right bound of the frustum
* @param {Number} bottom Bottom bound of the frustum
* @param {Number} top Top bound of the frustum
* @param {Number} near Near bound of the frustum
* @param {Number} far Far bound of the frustum
* @returns {mat4} out
*/
function frustum(out, left, right, bottom, top, near, far) {
var rl = 1 / (right - left);
var tb = 1 / (top - bottom);
var nf = 1 / (near - far);
out[0] = (near * 2) * rl;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = (near * 2) * tb;
out[6] = 0;
out[7] = 0;
out[8] = (right + left) * rl;
out[9] = (top + bottom) * tb;
out[10] = (far + near) * nf;
out[11] = -1;
out[12] = 0;
out[13] = 0;
out[14] = (far * near * 2) * nf;
out[15] = 0;
return out;
}
/**
* Generates a perspective projection matrix with the given bounds
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {number} fovy Vertical field of view in radians
* @param {number} aspect Aspect ratio. typically viewport width/height
* @param {number} near Near bound of the frustum
* @param {number} far Far bound of the frustum
* @returns {mat4} out
*/
function perspective(out, fovy, aspect, near, far) {
var f = 1.0 / Math.tan(fovy / 2);
var nf = 1 / (near - far);
out[0] = f / aspect;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = f;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = (far + near) * nf;
out[11] = -1;
out[12] = 0;
out[13] = 0;
out[14] = (2 * far * near) * nf;
out[15] = 0;
return out;
}
/**
* Generates a perspective projection matrix with the given field of view.
* This is primarily useful for generating projection matrices to be used
* with the still experiemental WebVR API.
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
* @param {number} near Near bound of the frustum
* @param {number} far Far bound of the frustum
* @returns {mat4} out
*/
function perspectiveFromFieldOfView(out, fov, near, far) {
var upTan = Math.tan(fov.upDegrees * Math.PI/180.0);
var downTan = Math.tan(fov.downDegrees * Math.PI/180.0);
var leftTan = Math.tan(fov.leftDegrees * Math.PI/180.0);
var rightTan = Math.tan(fov.rightDegrees * Math.PI/180.0);
var xScale = 2.0 / (leftTan + rightTan);
var yScale = 2.0 / (upTan + downTan);
out[0] = xScale;
out[1] = 0.0;
out[2] = 0.0;
out[3] = 0.0;
out[4] = 0.0;
out[5] = yScale;
out[6] = 0.0;
out[7] = 0.0;
out[8] = -((leftTan - rightTan) * xScale * 0.5);
out[9] = ((upTan - downTan) * yScale * 0.5);
out[10] = far / (near - far);
out[11] = -1.0;
out[12] = 0.0;
out[13] = 0.0;
out[14] = (far * near) / (near - far);
out[15] = 0.0;
return out;
}
/**
* Generates a orthogonal projection matrix with the given bounds
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {number} left Left bound of the frustum
* @param {number} right Right bound of the frustum
* @param {number} bottom Bottom bound of the frustum
* @param {number} top Top bound of the frustum
* @param {number} near Near bound of the frustum
* @param {number} far Far bound of the frustum
* @returns {mat4} out
*/
function ortho(out, left, right, bottom, top, near, far) {
var lr = 1 / (left - right);
var bt = 1 / (bottom - top);
var nf = 1 / (near - far);
out[0] = -2 * lr;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = -2 * bt;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 2 * nf;
out[11] = 0;
out[12] = (left + right) * lr;
out[13] = (top + bottom) * bt;
out[14] = (far + near) * nf;
out[15] = 1;
return out;
}
/**
* Generates a look-at matrix with the given eye position, focal point, and up axis.
* If you want a matrix that actually makes an object look at another object, you should use targetTo instead.
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {vec3} eye Position of the viewer
* @param {vec3} center Point the viewer is looking at
* @param {vec3} up vec3 pointing up
* @returns {mat4} out
*/
function lookAt(out, eye, center, up) {
var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
var eyex = eye[0];
var eyey = eye[1];
var eyez = eye[2];
var upx = up[0];
var upy = up[1];
var upz = up[2];
var centerx = center[0];
var centery = center[1];
var centerz = center[2];
if (Math.abs(eyex - centerx) < EPSILON &&
Math.abs(eyey - centery) < EPSILON &&
Math.abs(eyez - centerz) < EPSILON) {
return identity$3(out);
}
z0 = eyex - centerx;
z1 = eyey - centery;
z2 = eyez - centerz;
len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
z0 *= len;
z1 *= len;
z2 *= len;
x0 = upy * z2 - upz * z1;
x1 = upz * z0 - upx * z2;
x2 = upx * z1 - upy * z0;
len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
if (!len) {
x0 = 0;
x1 = 0;
x2 = 0;
} else {
len = 1 / len;
x0 *= len;
x1 *= len;
x2 *= len;
}
y0 = z1 * x2 - z2 * x1;
y1 = z2 * x0 - z0 * x2;
y2 = z0 * x1 - z1 * x0;
len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
if (!len) {
y0 = 0;
y1 = 0;
y2 = 0;
} else {
len = 1 / len;
y0 *= len;
y1 *= len;
y2 *= len;
}
out[0] = x0;
out[1] = y0;
out[2] = z0;
out[3] = 0;
out[4] = x1;
out[5] = y1;
out[6] = z1;
out[7] = 0;
out[8] = x2;
out[9] = y2;
out[10] = z2;
out[11] = 0;
out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
out[15] = 1;
return out;
}
/**
* Generates a matrix that makes something look at something else.
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {vec3} eye Position of the viewer
* @param {vec3} center Point the viewer is looking at
* @param {vec3} up vec3 pointing up
* @returns {mat4} out
*/
function targetTo(out, eye, target, up) {
var eyex = eye[0],
eyey = eye[1],
eyez = eye[2],
upx = up[0],
upy = up[1],
upz = up[2];
var z0 = eyex - target[0],
z1 = eyey - target[1],
z2 = eyez - target[2];
var len = z0*z0 + z1*z1 + z2*z2;
if (len > 0) {
len = 1 / Math.sqrt(len);
z0 *= len;
z1 *= len;
z2 *= len;
}
var x0 = upy * z2 - upz * z1,
x1 = upz * z0 - upx * z2,
x2 = upx * z1 - upy * z0;
len = x0*x0 + x1*x1 + x2*x2;
if (len > 0) {
len = 1 / Math.sqrt(len);
x0 *= len;
x1 *= len;
x2 *= len;
}
out[0] = x0;
out[1] = x1;
out[2] = x2;
out[3] = 0;
out[4] = z1 * x2 - z2 * x1;
out[5] = z2 * x0 - z0 * x2;
out[6] = z0 * x1 - z1 * x0;
out[7] = 0;
out[8] = z0;
out[9] = z1;
out[10] = z2;
out[11] = 0;
out[12] = eyex;
out[13] = eyey;
out[14] = eyez;
out[15] = 1;
return out;
}
/**
* Returns a string representation of a mat4
*
* @param {mat4} a matrix to represent as a string
* @returns {String} string representation of the matrix
*/
function str$3(a) {
return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' +
a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
}
/**
* Returns Frobenius norm of a mat4
*
* @param {mat4} a the matrix to calculate Frobenius norm of
* @returns {Number} Frobenius norm
*/
function frob$3(a) {
return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) ))
}
/**
* Adds two mat4's
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the first operand
* @param {mat4} b the second operand
* @returns {mat4} out
*/
function add$3(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
out[3] = a[3] + b[3];
out[4] = a[4] + b[4];
out[5] = a[5] + b[5];
out[6] = a[6] + b[6];
out[7] = a[7] + b[7];
out[8] = a[8] + b[8];
out[9] = a[9] + b[9];
out[10] = a[10] + b[10];
out[11] = a[11] + b[11];
out[12] = a[12] + b[12];
out[13] = a[13] + b[13];
out[14] = a[14] + b[14];
out[15] = a[15] + b[15];
return out;
}
/**
* Subtracts matrix b from matrix a
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the first operand
* @param {mat4} b the second operand
* @returns {mat4} out
*/
function subtract$3(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
out[3] = a[3] - b[3];
out[4] = a[4] - b[4];
out[5] = a[5] - b[5];
out[6] = a[6] - b[6];
out[7] = a[7] - b[7];
out[8] = a[8] - b[8];
out[9] = a[9] - b[9];
out[10] = a[10] - b[10];
out[11] = a[11] - b[11];
out[12] = a[12] - b[12];
out[13] = a[13] - b[13];
out[14] = a[14] - b[14];
out[15] = a[15] - b[15];
return out;
}
/**
* Multiply each element of the matrix by a scalar.
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to scale
* @param {Number} b amount to scale the matrix's elements by
* @returns {mat4} out
*/
function multiplyScalar$3(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
out[3] = a[3] * b;
out[4] = a[4] * b;
out[5] = a[5] * b;
out[6] = a[6] * b;
out[7] = a[7] * b;
out[8] = a[8] * b;
out[9] = a[9] * b;
out[10] = a[10] * b;
out[11] = a[11] * b;
out[12] = a[12] * b;
out[13] = a[13] * b;
out[14] = a[14] * b;
out[15] = a[15] * b;
return out;
}
/**
* Adds two mat4's after multiplying each element of the second operand by a scalar value.
*
* @param {mat4} out the receiving vector
* @param {mat4} a the first operand
* @param {mat4} b the second operand
* @param {Number} scale the amount to scale b's elements by before adding
* @returns {mat4} out
*/
function multiplyScalarAndAdd$3(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
out[2] = a[2] + (b[2] * scale);
out[3] = a[3] + (b[3] * scale);
out[4] = a[4] + (b[4] * scale);
out[5] = a[5] + (b[5] * scale);
out[6] = a[6] + (b[6] * scale);
out[7] = a[7] + (b[7] * scale);
out[8] = a[8] + (b[8] * scale);
out[9] = a[9] + (b[9] * scale);
out[10] = a[10] + (b[10] * scale);
out[11] = a[11] + (b[11] * scale);
out[12] = a[12] + (b[12] * scale);
out[13] = a[13] + (b[13] * scale);
out[14] = a[14] + (b[14] * scale);
out[15] = a[15] + (b[15] * scale);
return out;
}
/**
* Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
*
* @param {mat4} a The first matrix.
* @param {mat4} b The second matrix.
* @returns {Boolean} True if the matrices are equal, false otherwise.
*/
function exactEquals$3(a, b) {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] &&
a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] &&
a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] &&
a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];
}
/**
* Returns whether or not the matrices have approximately the same elements in the same position.
*
* @param {mat4} a The first matrix.
* @param {mat4} b The second matrix.
* @returns {Boolean} True if the matrices are equal, false otherwise.
*/
function equals$4(a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
var a4 = a[4], a5 = a[5], a6 = a[6], a7 = a[7];
var a8 = a[8], a9 = a[9], a10 = a[10], a11 = a[11];
var a12 = a[12], a13 = a[13], a14 = a[14], a15 = a[15];
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
var b4 = b[4], b5 = b[5], b6 = b[6], b7 = b[7];
var b8 = b[8], b9 = b[9], b10 = b[10], b11 = b[11];
var b12 = b[12], b13 = b[13], b14 = b[14], b15 = b[15];
return (Math.abs(a0 - b0) <= EPSILON*Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
Math.abs(a1 - b1) <= EPSILON*Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
Math.abs(a2 - b2) <= EPSILON*Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
Math.abs(a3 - b3) <= EPSILON*Math.max(1.0, Math.abs(a3), Math.abs(b3)) &&
Math.abs(a4 - b4) <= EPSILON*Math.max(1.0, Math.abs(a4), Math.abs(b4)) &&
Math.abs(a5 - b5) <= EPSILON*Math.max(1.0, Math.abs(a5), Math.abs(b5)) &&
Math.abs(a6 - b6) <= EPSILON*Math.max(1.0, Math.abs(a6), Math.abs(b6)) &&
Math.abs(a7 - b7) <= EPSILON*Math.max(1.0, Math.abs(a7), Math.abs(b7)) &&
Math.abs(a8 - b8) <= EPSILON*Math.max(1.0, Math.abs(a8), Math.abs(b8)) &&
Math.abs(a9 - b9) <= EPSILON*Math.max(1.0, Math.abs(a9), Math.abs(b9)) &&
Math.abs(a10 - b10) <= EPSILON*Math.max(1.0, Math.abs(a10), Math.abs(b10)) &&
Math.abs(a11 - b11) <= EPSILON*Math.max(1.0, Math.abs(a11), Math.abs(b11)) &&
Math.abs(a12 - b12) <= EPSILON*Math.max(1.0, Math.abs(a12), Math.abs(b12)) &&
Math.abs(a13 - b13) <= EPSILON*Math.max(1.0, Math.abs(a13), Math.abs(b13)) &&
Math.abs(a14 - b14) <= EPSILON*Math.max(1.0, Math.abs(a14), Math.abs(b14)) &&
Math.abs(a15 - b15) <= EPSILON*Math.max(1.0, Math.abs(a15), Math.abs(b15)));
}
/**
* Alias for {@link mat4.multiply}
* @function
*/
var mul$3 = multiply$3;
/**
* Alias for {@link mat4.subtract}
* @function
*/
var sub$3 = subtract$3;
/**
* 3 Dimensional Vector
* @module vec3
*/
/**
* Creates a new, empty vec3
*
* @returns {vec3} a new 3D vector
*/
function create$4() {
var out = new ARRAY_TYPE(3);
out[0] = 0;
out[1] = 0;
out[2] = 0;
return out;
}
/**
* Creates a new vec3 initialized with values from an existing vector
*
* @param {vec3} a vector to clone
* @returns {vec3} a new 3D vector
*/
function clone$5(a) {
var out = new ARRAY_TYPE(3);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
return out;
}
/**
* Calculates the length of a vec3
*
* @param {vec3} a vector to calculate length of
* @returns {Number} length of a
*/
function length(a) {
var x = a[0];
var y = a[1];
var z = a[2];
return Math.sqrt(x*x + y*y + z*z);
}
/**
* Creates a new vec3 initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @returns {vec3} a new 3D vector
*/
function fromValues$4(x, y, z) {
var out = new ARRAY_TYPE(3);
out[0] = x;
out[1] = y;
out[2] = z;
return out;
}
/**
* Copy the values from one vec3 to another
*
* @param {vec3} out the receiving vector
* @param {vec3} a the source vector
* @returns {vec3} out
*/
function copy$4(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
return out;
}
/**
* Set the components of a vec3 to the given values
*
* @param {vec3} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @returns {vec3} out
*/
function set$4(out, x, y, z) {
out[0] = x;
out[1] = y;
out[2] = z;
return out;
}
/**
* Adds two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function add$4(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
return out;
}
/**
* Subtracts vector b from vector a
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function subtract$4(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
return out;
}
/**
* Multiplies two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function multiply$4(out, a, b) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
out[2] = a[2] * b[2];
return out;
}
/**
* Divides two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function divide(out, a, b) {
out[0] = a[0] / b[0];
out[1] = a[1] / b[1];
out[2] = a[2] / b[2];
return out;
}
/**
* Math.ceil the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to ceil
* @returns {vec3} out
*/
function ceil(out, a) {
out[0] = Math.ceil(a[0]);
out[1] = Math.ceil(a[1]);
out[2] = Math.ceil(a[2]);
return out;
}
/**
* Math.floor the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to floor
* @returns {vec3} out
*/
function floor(out, a) {
out[0] = Math.floor(a[0]);
out[1] = Math.floor(a[1]);
out[2] = Math.floor(a[2]);
return out;
}
/**
* Returns the minimum of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function min(out, a, b) {
out[0] = Math.min(a[0], b[0]);
out[1] = Math.min(a[1], b[1]);
out[2] = Math.min(a[2], b[2]);
return out;
}
/**
* Returns the maximum of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function max(out, a, b) {
out[0] = Math.max(a[0], b[0]);
out[1] = Math.max(a[1], b[1]);
out[2] = Math.max(a[2], b[2]);
return out;
}
/**
* Math.round the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to round
* @returns {vec3} out
*/
function round(out, a) {
out[0] = Math.round(a[0]);
out[1] = Math.round(a[1]);
out[2] = Math.round(a[2]);
return out;
}
/**
* Scales a vec3 by a scalar number
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {vec3} out
*/
function scale$4(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
return out;
}
/**
* Adds two vec3's after scaling the second operand by a scalar value
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @param {Number} scale the amount to scale b by before adding
* @returns {vec3} out
*/
function scaleAndAdd(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
out[2] = a[2] + (b[2] * scale);
return out;
}
/**
* Calculates the euclidian distance between two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} distance between a and b
*/
function distance(a, b) {
var x = b[0] - a[0];
var y = b[1] - a[1];
var z = b[2] - a[2];
return Math.sqrt(x*x + y*y + z*z);
}
/**
* Calculates the squared euclidian distance between two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} squared distance between a and b
*/
function squaredDistance(a, b) {
var x = b[0] - a[0];
var y = b[1] - a[1];
var z = b[2] - a[2];
return x*x + y*y + z*z;
}
/**
* Calculates the squared length of a vec3
*
* @param {vec3} a vector to calculate squared length of
* @returns {Number} squared length of a
*/
function squaredLength(a) {
var x = a[0];
var y = a[1];
var z = a[2];
return x*x + y*y + z*z;
}
/**
* Negates the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to negate
* @returns {vec3} out
*/
function negate(out, a) {
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
return out;
}
/**
* Returns the inverse of the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to invert
* @returns {vec3} out
*/
function inverse(out, a) {
out[0] = 1.0 / a[0];
out[1] = 1.0 / a[1];
out[2] = 1.0 / a[2];
return out;
}
/**
* Normalize a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to normalize
* @returns {vec3} out
*/
function normalize(out, a) {
var x = a[0];
var y = a[1];
var z = a[2];
var len = x*x + y*y + z*z;
if (len > 0) {
//TODO: evaluate use of glm_invsqrt here?
len = 1 / Math.sqrt(len);
out[0] = a[0] * len;
out[1] = a[1] * len;
out[2] = a[2] * len;
}
return out;
}
/**
* Calculates the dot product of two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} dot product of a and b
*/
function dot(a, b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
/**
* Computes the cross product of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function cross(out, a, b) {
var ax = a[0], ay = a[1], az = a[2];
var bx = b[0], by = b[1], bz = b[2];
out[0] = ay * bz - az * by;
out[1] = az * bx - ax * bz;
out[2] = ax * by - ay * bx;
return out;
}
/**
* Performs a linear interpolation between two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @param {Number} t interpolation amount, in the range [0-1], between the two inputs
* @returns {vec3} out
*/
function lerp(out, a, b, t) {
var ax = a[0];
var ay = a[1];
var az = a[2];
out[0] = ax + t * (b[0] - ax);
out[1] = ay + t * (b[1] - ay);
out[2] = az + t * (b[2] - az);
return out;
}
/**
* Performs a hermite interpolation with two control points
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @param {vec3} c the third operand
* @param {vec3} d the fourth operand
* @param {Number} t interpolation amount, in the range [0-1], between the two inputs
* @returns {vec3} out
*/
function hermite(out, a, b, c, d, t) {
var factorTimes2 = t * t;
var factor1 = factorTimes2 * (2 * t - 3) + 1;
var factor2 = factorTimes2 * (t - 2) + t;
var factor3 = factorTimes2 * (t - 1);
var factor4 = factorTimes2 * (3 - 2 * t);
out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
return out;
}
/**
* Performs a bezier interpolation with two control points
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @param {vec3} c the third operand
* @param {vec3} d the fourth operand
* @param {Number} t interpolation amount, in the range [0-1], between the two inputs
* @returns {vec3} out
*/
function bezier$1(out, a, b, c, d, t) {
var inverseFactor = 1 - t;
var inverseFactorTimesTwo = inverseFactor * inverseFactor;
var factorTimes2 = t * t;
var factor1 = inverseFactorTimesTwo * inverseFactor;
var factor2 = 3 * t * inverseFactorTimesTwo;
var factor3 = 3 * factorTimes2 * inverseFactor;
var factor4 = factorTimes2 * t;
out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
return out;
}
/**
* Generates a random vector with the given scale
*
* @param {vec3} out the receiving vector
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
* @returns {vec3} out
*/
function random(out, scale) {
scale = scale || 1.0;
var r = RANDOM() * 2.0 * Math.PI;
var z = (RANDOM() * 2.0) - 1.0;
var zScale = Math.sqrt(1.0-z*z) * scale;
out[0] = Math.cos(r) * zScale;
out[1] = Math.sin(r) * zScale;
out[2] = z * scale;
return out;
}
/**
* Transforms the vec3 with a mat4.
* 4th vector component is implicitly '1'
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {mat4} m matrix to transform with
* @returns {vec3} out
*/
function transformMat4(out, a, m) {
var x = a[0], y = a[1], z = a[2];
var w = m[3] * x + m[7] * y + m[11] * z + m[15];
w = w || 1.0;
out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
return out;
}
/**
* Transforms the vec3 with a mat3.
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {mat3} m the 3x3 matrix to transform with
* @returns {vec3} out
*/
function transformMat3(out, a, m) {
var x = a[0], y = a[1], z = a[2];
out[0] = x * m[0] + y * m[3] + z * m[6];
out[1] = x * m[1] + y * m[4] + z * m[7];
out[2] = x * m[2] + y * m[5] + z * m[8];
return out;
}
/**
* Transforms the vec3 with a quat
* Can also be used for dual quaternions. (Multiply it with the real part)
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {quat} q quaternion to transform with
* @returns {vec3} out
*/
function transformQuat(out, a, q) {
// benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed
var qx = q[0], qy = q[1], qz = q[2], qw = q[3];
var x = a[0], y = a[1], z = a[2];
// var qvec = [qx, qy, qz];
// var uv = vec3.cross([], qvec, a);
var uvx = qy * z - qz * y,
uvy = qz * x - qx * z,
uvz = qx * y - qy * x;
// var uuv = vec3.cross([], qvec, uv);
var uuvx = qy * uvz - qz * uvy,
uuvy = qz * uvx - qx * uvz,
uuvz = qx * uvy - qy * uvx;
// vec3.scale(uv, uv, 2 * w);
var w2 = qw * 2;
uvx *= w2;
uvy *= w2;
uvz *= w2;
// vec3.scale(uuv, uuv, 2);
uuvx *= 2;
uuvy *= 2;
uuvz *= 2;
// return vec3.add(out, a, vec3.add(out, uv, uuv));
out[0] = x + uvx + uuvx;
out[1] = y + uvy + uuvy;
out[2] = z + uvz + uuvz;
return out;
}
/**
* Rotate a 3D vector around the x-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
function rotateX$1(out, a, b, c){
var p = [], r=[];
//Translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];
//perform rotation
r[0] = p[0];
r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c);
r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c);
//translate to correct position
out[0] = r[0] + b[0];
out[1] = r[1] + b[1];
out[2] = r[2] + b[2];
return out;
}
/**
* Rotate a 3D vector around the y-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
function rotateY$1(out, a, b, c){
var p = [], r=[];
//Translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];
//perform rotation
r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c);
r[1] = p[1];
r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c);
//translate to correct position
out[0] = r[0] + b[0];
out[1] = r[1] + b[1];
out[2] = r[2] + b[2];
return out;
}
/**
* Rotate a 3D vector around the z-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
function rotateZ$1(out, a, b, c){
var p = [], r=[];
//Translate point to the origin
p[0] = a[0] - b[0];
p[1] = a[1] - b[1];
p[2] = a[2] - b[2];
//perform rotation
r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c);
r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c);
r[2] = p[2];
//translate to correct position
out[0] = r[0] + b[0];
out[1] = r[1] + b[1];
out[2] = r[2] + b[2];
return out;
}
/**
* Get the angle between two 3D vectors
* @param {vec3} a The first operand
* @param {vec3} b The second operand
* @returns {Number} The angle in radians
*/
function angle(a, b) {
var tempA = fromValues$4(a[0], a[1], a[2]);
var tempB = fromValues$4(b[0], b[1], b[2]);
normalize(tempA, tempA);
normalize(tempB, tempB);
var cosine = dot(tempA, tempB);
if(cosine > 1.0) {
return 0;
}
else if(cosine < -1.0) {
return Math.PI;
} else {
return Math.acos(cosine);
}
}
/**
* Returns a string representation of a vector
*
* @param {vec3} a vector to represent as a string
* @returns {String} string representation of the vector
*/
function str$4(a) {
return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
}
/**
* Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)
*
* @param {vec3} a The first vector.
* @param {vec3} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
function exactEquals$4(a, b) {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
}
/**
* Returns whether or not the vectors have approximately the same elements in the same position.
*
* @param {vec3} a The first vector.
* @param {vec3} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
function equals$5(a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2];
var b0 = b[0], b1 = b[1], b2 = b[2];
return (Math.abs(a0 - b0) <= EPSILON*Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
Math.abs(a1 - b1) <= EPSILON*Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
Math.abs(a2 - b2) <= EPSILON*Math.max(1.0, Math.abs(a2), Math.abs(b2)));
}
/**
* Alias for {@link vec3.subtract}
* @function
*/
var sub$4 = subtract$4;
/**
* Alias for {@link vec3.multiply}
* @function
*/
var mul$4 = multiply$4;
/**
* Alias for {@link vec3.divide}
* @function
*/
var div = divide;
/**
* Alias for {@link vec3.distance}
* @function
*/
var dist = distance;
/**
* Alias for {@link vec3.squaredDistance}
* @function
*/
var sqrDist = squaredDistance;
/**
* Alias for {@link vec3.length}
* @function
*/
var len = length;
/**
* Alias for {@link vec3.squaredLength}
* @function
*/
var sqrLen = squaredLength;
/**
* Perform some operation over an array of vec3s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
var forEach = (function() {
var vec = create$4();
return function(a, stride, offset, count, fn, arg) {
var i, l;
if(!stride) {
stride = 3;
}
if(!offset) {
offset = 0;
}
if(count) {
l = Math.min((count * stride) + offset, a.length);
} else {
l = a.length;
}
for(i = offset; i < l; i += stride) {
vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2];
fn(vec, vec, arg);
a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2];
}
return a;
};
})();
/**
* 4 Dimensional Vector
* @module vec4
*/
/**
* Creates a new, empty vec4
*
* @returns {vec4} a new 4D vector
*/
function create$5() {
var out = new ARRAY_TYPE(4);
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 0;
return out;
}
/**
* Creates a new vec4 initialized with values from an existing vector
*
* @param {vec4} a vector to clone
* @returns {vec4} a new 4D vector
*/
function clone$6(a) {
var out = new ARRAY_TYPE(4);
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
}
/**
* Creates a new vec4 initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {vec4} a new 4D vector
*/
function fromValues$5(x, y, z, w) {
var out = new ARRAY_TYPE(4);
out[0] = x;
out[1] = y;
out[2] = z;
out[3] = w;
return out;
}
/**
* Copy the values from one vec4 to another
*
* @param {vec4} out the receiving vector
* @param {vec4} a the source vector
* @returns {vec4} out
*/
function copy$5(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
return out;
}
/**
* Set the components of a vec4 to the given values
*
* @param {vec4} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {vec4} out
*/
function set$5(out, x, y, z, w) {
out[0] = x;
out[1] = y;
out[2] = z;
out[3] = w;
return out;
}
/**
* Adds two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
function add$5(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
out[3] = a[3] + b[3];
return out;
}
/**
* Subtracts vector b from vector a
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
function subtract$5(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
out[3] = a[3] - b[3];
return out;
}
/**
* Multiplies two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
function multiply$5(out, a, b) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
out[2] = a[2] * b[2];
out[3] = a[3] * b[3];
return out;
}
/**
* Divides two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
function divide$1(out, a, b) {
out[0] = a[0] / b[0];
out[1] = a[1] / b[1];
out[2] = a[2] / b[2];
out[3] = a[3] / b[3];
return out;
}
/**
* Math.ceil the components of a vec4
*
* @param {vec4} out the receiving vector
* @param {vec4} a vector to ceil
* @returns {vec4} out
*/
function ceil$1(out, a) {
out[0] = Math.ceil(a[0]);
out[1] = Math.ceil(a[1]);
out[2] = Math.ceil(a[2]);
out[3] = Math.ceil(a[3]);
return out;
}
/**
* Math.floor the components of a vec4
*
* @param {vec4} out the receiving vector
* @param {vec4} a vector to floor
* @returns {vec4} out
*/
function floor$1(out, a) {
out[0] = Math.floor(a[0]);
out[1] = Math.floor(a[1]);
out[2] = Math.floor(a[2]);
out[3] = Math.floor(a[3]);
return out;
}
/**
* Returns the minimum of two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
function min$1(out, a, b) {
out[0] = Math.min(a[0], b[0]);
out[1] = Math.min(a[1], b[1]);
out[2] = Math.min(a[2], b[2]);
out[3] = Math.min(a[3], b[3]);
return out;
}
/**
* Returns the maximum of two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {vec4} out
*/
function max$1(out, a, b) {
out[0] = Math.max(a[0], b[0]);
out[1] = Math.max(a[1], b[1]);
out[2] = Math.max(a[2], b[2]);
out[3] = Math.max(a[3], b[3]);
return out;
}
/**
* Math.round the components of a vec4
*
* @param {vec4} out the receiving vector
* @param {vec4} a vector to round
* @returns {vec4} out
*/
function round$1(out, a) {
out[0] = Math.round(a[0]);
out[1] = Math.round(a[1]);
out[2] = Math.round(a[2]);
out[3] = Math.round(a[3]);
return out;
}
/**
* Scales a vec4 by a scalar number
*
* @param {vec4} out the receiving vector
* @param {vec4} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {vec4} out
*/
function scale$5(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
out[3] = a[3] * b;
return out;
}
/**
* Adds two vec4's after scaling the second operand by a scalar value
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @param {Number} scale the amount to scale b by before adding
* @returns {vec4} out
*/
function scaleAndAdd$1(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
out[2] = a[2] + (b[2] * scale);
out[3] = a[3] + (b[3] * scale);
return out;
}
/**
* Calculates the euclidian distance between two vec4's
*
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {Number} distance between a and b
*/
function distance$1(a, b) {
var x = b[0] - a[0];
var y = b[1] - a[1];
var z = b[2] - a[2];
var w = b[3] - a[3];
return Math.sqrt(x*x + y*y + z*z + w*w);
}
/**
* Calculates the squared euclidian distance between two vec4's
*
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {Number} squared distance between a and b
*/
function squaredDistance$1(a, b) {
var x = b[0] - a[0];
var y = b[1] - a[1];
var z = b[2] - a[2];
var w = b[3] - a[3];
return x*x + y*y + z*z + w*w;
}
/**
* Calculates the length of a vec4
*
* @param {vec4} a vector to calculate length of
* @returns {Number} length of a
*/
function length$1(a) {
var x = a[0];
var y = a[1];
var z = a[2];
var w = a[3];
return Math.sqrt(x*x + y*y + z*z + w*w);
}
/**
* Calculates the squared length of a vec4
*
* @param {vec4} a vector to calculate squared length of
* @returns {Number} squared length of a
*/
function squaredLength$1(a) {
var x = a[0];
var y = a[1];
var z = a[2];
var w = a[3];
return x*x + y*y + z*z + w*w;
}
/**
* Negates the components of a vec4
*
* @param {vec4} out the receiving vector
* @param {vec4} a vector to negate
* @returns {vec4} out
*/
function negate$1(out, a) {
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
out[3] = -a[3];
return out;
}
/**
* Returns the inverse of the components of a vec4
*
* @param {vec4} out the receiving vector
* @param {vec4} a vector to invert
* @returns {vec4} out
*/
function inverse$1(out, a) {
out[0] = 1.0 / a[0];
out[1] = 1.0 / a[1];
out[2] = 1.0 / a[2];
out[3] = 1.0 / a[3];
return out;
}
/**
* Normalize a vec4
*
* @param {vec4} out the receiving vector
* @param {vec4} a vector to normalize
* @returns {vec4} out
*/
function normalize$1(out, a) {
var x = a[0];
var y = a[1];
var z = a[2];
var w = a[3];
var len = x*x + y*y + z*z + w*w;
if (len > 0) {
len = 1 / Math.sqrt(len);
out[0] = x * len;
out[1] = y * len;
out[2] = z * len;
out[3] = w * len;
}
return out;
}
/**
* Calculates the dot product of two vec4's
*
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @returns {Number} dot product of a and b
*/
function dot$1(a, b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
}
/**
* Performs a linear interpolation between two vec4's
*
* @param {vec4} out the receiving vector
* @param {vec4} a the first operand
* @param {vec4} b the second operand
* @param {Number} t interpolation amount, in the range [0-1], between the two inputs
* @returns {vec4} out
*/
function lerp$1(out, a, b, t) {
var ax = a[0];
var ay = a[1];
var az = a[2];
var aw = a[3];
out[0] = ax + t * (b[0] - ax);
out[1] = ay + t * (b[1] - ay);
out[2] = az + t * (b[2] - az);
out[3] = aw + t * (b[3] - aw);
return out;
}
/**
* Generates a random vector with the given scale
*
* @param {vec4} out the receiving vector
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
* @returns {vec4} out
*/
function random$1(out, vectorScale) {
vectorScale = vectorScale || 1.0;
// Marsaglia, George. Choosing a Point from the Surface of a
// Sphere. Ann. Math. Statist. 43 (1972), no. 2, 645--646.
// http://projecteuclid.org/euclid.aoms/1177692644;
var v1, v2, v3, v4;
var s1, s2;
do {
v1 = RANDOM() * 2 - 1;
v2 = RANDOM() * 2 - 1;
s1 = v1 * v1 + v2 * v2;
} while (s1 >= 1);
do {
v3 = RANDOM() * 2 - 1;
v4 = RANDOM() * 2 - 1;
s2 = v3 * v3 + v4 * v4;
} while (s2 >= 1);
var d = Math.sqrt((1 - s1) / s2);
out[0] = scale$5 * v1;
out[1] = scale$5 * v2;
out[2] = scale$5 * v3 * d;
out[3] = scale$5 * v4 * d;
return out;
}
/**
* Transforms the vec4 with a mat4.
*
* @param {vec4} out the receiving vector
* @param {vec4} a the vector to transform
* @param {mat4} m matrix to transform with
* @returns {vec4} out
*/
function transformMat4$1(out, a, m) {
var x = a[0], y = a[1], z = a[2], w = a[3];
out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
return out;
}
/**
* Transforms the vec4 with a quat
*
* @param {vec4} out the receiving vector
* @param {vec4} a the vector to transform
* @param {quat} q quaternion to transform with
* @returns {vec4} out
*/
function transformQuat$1(out, a, q) {
var x = a[0], y = a[1], z = a[2];
var qx = q[0], qy = q[1], qz = q[2], qw = q[3];
// calculate quat * vec
var ix = qw * x + qy * z - qz * y;
var iy = qw * y + qz * x - qx * z;
var iz = qw * z + qx * y - qy * x;
var iw = -qx * x - qy * y - qz * z;
// calculate result * inverse quat
out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
out[3] = a[3];
return out;
}
/**
* Returns a string representation of a vector
*
* @param {vec4} a vector to represent as a string
* @returns {String} string representation of the vector
*/
function str$5(a) {
return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
}
/**
* Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)
*
* @param {vec4} a The first vector.
* @param {vec4} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
function exactEquals$5(a, b) {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
}
/**
* Returns whether or not the vectors have approximately the same elements in the same position.
*
* @param {vec4} a The first vector.
* @param {vec4} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
function equals$6(a, b) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
return (Math.abs(a0 - b0) <= EPSILON*Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
Math.abs(a1 - b1) <= EPSILON*Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
Math.abs(a2 - b2) <= EPSILON*Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
Math.abs(a3 - b3) <= EPSILON*Math.max(1.0, Math.abs(a3), Math.abs(b3)));
}
/**
* Alias for {@link vec4.subtract}
* @function
*/
var sub$5 = subtract$5;
/**
* Alias for {@link vec4.multiply}
* @function
*/
var mul$5 = multiply$5;
/**
* Alias for {@link vec4.divide}
* @function
*/
var div$1 = divide$1;
/**
* Alias for {@link vec4.distance}
* @function
*/
var dist$1 = distance$1;
/**
* Alias for {@link vec4.squaredDistance}
* @function
*/
var sqrDist$1 = squaredDistance$1;
/**
* Alias for {@link vec4.length}
* @function
*/
var len$1 = length$1;
/**
* Alias for {@link vec4.squaredLength}
* @function
*/
var sqrLen$1 = squaredLength$1;
/**
* Perform some operation over an array of vec4s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
var forEach$1 = (function() {
var vec = create$5();
return function(a, stride, offset, count, fn, arg) {
var i, l;
if(!stride) {
stride = 4;
}
if(!offset) {
offset = 0;
}
if(count) {
l = Math.min((count * stride) + offset, a.length);
} else {
l = a.length;
}
for(i = offset; i < l; i += stride) {
vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3];
fn(vec, vec, arg);
a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3];
}
return a;
};
})();
/**
* Quaternion
* @module quat
*/
/**
* Creates a new identity quat
*
* @returns {quat} a new quaternion
*/
function create$6() {
var out = new ARRAY_TYPE(4);
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
}
/**
* Set a quat to the identity quaternion
*
* @param {quat} out the receiving quaternion
* @returns {quat} out
*/
function identity$4(out) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
}
/**
* Sets a quat from the given angle and rotation axis,
* then returns it.
*
* @param {quat} out the receiving quaternion
* @param {vec3} axis the axis around which to rotate
* @param {Number} rad the angle in radians
* @returns {quat} out
**/
function setAxisAngle(out, axis, rad) {
rad = rad * 0.5;
var s = Math.sin(rad);
out[0] = s * axis[0];
out[1] = s * axis[1];
out[2] = s * axis[2];
out[3] = Math.cos(rad);
return out;
}
/**
* Gets the rotation axis and angle for a given
* quaternion. If a quaternion is created with
* setAxisAngle, this method will return the same
* values as providied in the original parameter list
* OR functionally equivalent values.
* Example: The quaternion formed by axis [0, 0, 1] and
* angle -90 is the same as the quaternion formed by
* [0, 0, 1] and 270. This method favors the latter.
* @param {vec3} out_axis Vector receiving the axis of rotation
* @param {quat} q Quaternion to be decomposed
* @return {Number} Angle, in radians, of the rotation
*/
function getAxisAngle(out_axis, q) {
var rad = Math.acos(q[3]) * 2.0;
var s = Math.sin(rad / 2.0);
if (s != 0.0) {
out_axis[0] = q[0] / s;
out_axis[1] = q[1] / s;
out_axis[2] = q[2] / s;
} else {
// If s is zero, return any axis (no rotation - axis does not matter)
out_axis[0] = 1;
out_axis[1] = 0;
out_axis[2] = 0;
}
return rad;
}
/**
* Multiplies two quat's
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @returns {quat} out
*/
function multiply$6(out, a, b) {
var ax = a[0], ay = a[1], az = a[2], aw = a[3];
var bx = b[0], by = b[1], bz = b[2], bw = b[3];
out[0] = ax * bw + aw * bx + ay * bz - az * by;
out[1] = ay * bw + aw * by + az * bx - ax * bz;
out[2] = az * bw + aw * bz + ax * by - ay * bx;
out[3] = aw * bw - ax * bx - ay * by - az * bz;
return out;
}
/**
* Rotates a quaternion by the given angle about the X axis
*
* @param {quat} out quat receiving operation result
* @param {quat} a quat to rotate
* @param {number} rad angle (in radians) to rotate
* @returns {quat} out
*/
function rotateX$2(out, a, rad) {
rad *= 0.5;
var ax = a[0], ay = a[1], az = a[2], aw = a[3];
var bx = Math.sin(rad), bw = Math.cos(rad);
out[0] = ax * bw + aw * bx;
out[1] = ay * bw + az * bx;
out[2] = az * bw - ay * bx;
out[3] = aw * bw - ax * bx;
return out;
}
/**
* Rotates a quaternion by the given angle about the Y axis
*
* @param {quat} out quat receiving operation result
* @param {quat} a quat to rotate
* @param {number} rad angle (in radians) to rotate
* @returns {quat} out
*/
function rotateY$2(out, a, rad) {
rad *= 0.5;
var ax = a[0], ay = a[1], az = a[2], aw = a[3];
var by = Math.sin(rad), bw = Math.cos(rad);
out[0] = ax * bw - az * by;
out[1] = ay * bw + aw * by;
out[2] = az * bw + ax * by;
out[3] = aw * bw - ay * by;
return out;
}
/**
* Rotates a quaternion by the given angle about the Z axis
*
* @param {quat} out quat receiving operation result
* @param {quat} a quat to rotate
* @param {number} rad angle (in radians) to rotate
* @returns {quat} out
*/
function rotateZ$2(out, a, rad) {
rad *= 0.5;
var ax = a[0], ay = a[1], az = a[2], aw = a[3];
var bz = Math.sin(rad), bw = Math.cos(rad);
out[0] = ax * bw + ay * bz;
out[1] = ay * bw - ax * bz;
out[2] = az * bw + aw * bz;
out[3] = aw * bw - az * bz;
return out;
}
/**
* Calculates the W component of a quat from the X, Y, and Z components.
* Assumes that quaternion is 1 unit in length.
* Any existing W component will be ignored.
*
* @param {quat} out the receiving quaternion
* @param {quat} a quat to calculate W component of
* @returns {quat} out
*/
function calculateW(out, a) {
var x = a[0], y = a[1], z = a[2];
out[0] = x;
out[1] = y;
out[2] = z;
out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
return out;
}
/**
* Performs a spherical linear interpolation between two quat
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @param {Number} t interpolation amount, in the range [0-1], between the two inputs
* @returns {quat} out
*/
function slerp(out, a, b, t) {
// benchmarks:
// http://jsperf.com/quaternion-slerp-implementations
var ax = a[0], ay = a[1], az = a[2], aw = a[3];
var bx = b[0], by = b[1], bz = b[2], bw = b[3];
var omega, cosom, sinom, scale0, scale1;
// calc cosine
cosom = ax * bx + ay * by + az * bz + aw * bw;
// adjust signs (if necessary)
if ( cosom < 0.0 ) {
cosom = -cosom;
bx = - bx;
by = - by;
bz = - bz;
bw = - bw;
}
// calculate coefficients
if ( (1.0 - cosom) > 0.000001 ) {
// standard case (slerp)
omega = Math.acos(cosom);
sinom = Math.sin(omega);
scale0 = Math.sin((1.0 - t) * omega) / sinom;
scale1 = Math.sin(t * omega) / sinom;
} else {
// "from" and "to" quaternions are very close
// ... so we can do a linear interpolation
scale0 = 1.0 - t;
scale1 = t;
}
// calculate final values
out[0] = scale0 * ax + scale1 * bx;
out[1] = scale0 * ay + scale1 * by;
out[2] = scale0 * az + scale1 * bz;
out[3] = scale0 * aw + scale1 * bw;
return out;
}
/**
* Calculates the inverse of a quat
*
* @param {quat} out the receiving quaternion
* @param {quat} a quat to calculate inverse of
* @returns {quat} out
*/
function invert$4(out, a) {
var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
var dot$$1 = a0*a0 + a1*a1 + a2*a2 + a3*a3;
var invDot = dot$$1 ? 1.0/dot$$1 : 0;
// TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
out[0] = -a0*invDot;
out[1] = -a1*invDot;
out[2] = -a2*invDot;
out[3] = a3*invDot;
return out;
}
/**
* Calculates the conjugate of a quat
* If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
*
* @param {quat} out the receiving quaternion
* @param {quat} a quat to calculate conjugate of
* @returns {quat} out
*/
function conjugate(out, a) {
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
out[3] = a[3];
return out;
}
/**
* Creates a quaternion from the given 3x3 rotation matrix.
*
* NOTE: The resultant quaternion is not normalized, so you should be sure
* to renormalize the quaternion yourself where necessary.
*
* @param {quat} out the receiving quaternion
* @param {mat3} m rotation matrix
* @returns {quat} out
* @function
*/
function fromMat3(out, m) {
// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
// article "Quaternion Calculus and Fast Animation".
var fTrace = m[0] + m[4] + m[8];
var fRoot;
if ( fTrace > 0.0 ) {
// |w| > 1/2, may as well choose w > 1/2
fRoot = Math.sqrt(fTrace + 1.0); // 2w
out[3] = 0.5 * fRoot;
fRoot = 0.5/fRoot; // 1/(4w)
out[0] = (m[5]-m[7])*fRoot;
out[1] = (m[6]-m[2])*fRoot;
out[2] = (m[1]-m[3])*fRoot;
} else {
// |w| <= 1/2
var i = 0;
if ( m[4] > m[0] )
{ i = 1; }
if ( m[8] > m[i*3+i] )
{ i = 2; }
var j = (i+1)%3;
var k = (i+2)%3;
fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0);
out[i] = 0.5 * fRoot;
fRoot = 0.5 / fRoot;
out[3] = (m[j*3+k] - m[k*3+j]) * fRoot;
out[j] = (m[j*3+i] + m[i*3+j]) * fRoot;
out[k] = (m[k*3+i] + m[i*3+k]) * fRoot;
}
return out;
}
/**
* Creates a quaternion from the given euler angle x, y, z.
*
* @param {quat} out the receiving quaternion
* @param {x} Angle to rotate around X axis in degrees.
* @param {y} Angle to rotate around Y axis in degrees.
* @param {z} Angle to rotate around Z axis in degrees.
* @returns {quat} out
* @function
*/
function fromEuler(out, x, y, z) {
var halfToRad = 0.5 * Math.PI / 180.0;
x *= halfToRad;
y *= halfToRad;
z *= halfToRad;
var sx = Math.sin(x);
var cx = Math.cos(x);
var sy = Math.sin(y);
var cy = Math.cos(y);
var sz = Math.sin(z);
var cz = Math.cos(z);
out[0] = sx * cy * cz - cx * sy * sz;
out[1] = cx * sy * cz + sx * cy * sz;
out[2] = cx * cy * sz - sx * sy * cz;
out[3] = cx * cy * cz + sx * sy * sz;
return out;
}
/**
* Returns a string representation of a quatenion
*
* @param {quat} a vector to represent as a string
* @returns {String} string representation of the vector
*/
function str$6(a) {
return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
}
/**
* Creates a new quat initialized with values from an existing quaternion
*
* @param {quat} a quaternion to clone
* @returns {quat} a new quaternion
* @function
*/
var clone$7 = clone$6;
/**
* Creates a new quat initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {quat} a new quaternion
* @function
*/
var fromValues$6 = fromValues$5;
/**
* Copy the values from one quat to another
*
* @param {quat} out the receiving quaternion
* @param {quat} a the source quaternion
* @returns {quat} out
* @function
*/
var copy$6 = copy$5;
/**
* Set the components of a quat to the given values
*
* @param {quat} out the receiving quaternion
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @param {Number} w W component
* @returns {quat} out
* @function
*/
var set$6 = set$5;
/**
* Adds two quat's
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @returns {quat} out
* @function
*/
var add$6 = add$5;
/**
* Alias for {@link quat.multiply}
* @function
*/
var mul$6 = multiply$6;
/**
* Scales a quat by a scalar number
*
* @param {quat} out the receiving vector
* @param {quat} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {quat} out
* @function
*/
var scale$6 = scale$5;
/**
* Calculates the dot product of two quat's
*
* @param {quat} a the first operand
* @param {quat} b the second operand
* @returns {Number} dot product of a and b
* @function
*/
var dot$2 = dot$1;
/**
* Performs a linear interpolation between two quat's
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @param {Number} t interpolation amount, in the range [0-1], between the two inputs
* @returns {quat} out
* @function
*/
var lerp$2 = lerp$1;
/**
* Calculates the length of a quat
*
* @param {quat} a vector to calculate length of
* @returns {Number} length of a
*/
var length$2 = length$1;
/**
* Alias for {@link quat.length}
* @function
*/
var len$2 = length$2;
/**
* Calculates the squared length of a quat
*
* @param {quat} a vector to calculate squared length of
* @returns {Number} squared length of a
* @function
*/
var squaredLength$2 = squaredLength$1;
/**
* Alias for {@link quat.squaredLength}
* @function
*/
var sqrLen$2 = squaredLength$2;
/**
* Normalize a quat
*
* @param {quat} out the receiving quaternion
* @param {quat} a quaternion to normalize
* @returns {quat} out
* @function
*/
var normalize$2 = normalize$1;
/**
* Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)
*
* @param {quat} a The first quaternion.
* @param {quat} b The second quaternion.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
var exactEquals$6 = exactEquals$5;
/**
* Returns whether or not the quaternions have approximately the same elements in the same position.
*
* @param {quat} a The first vector.
* @param {quat} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
var equals$7 = equals$6;
/**
* Sets a quaternion to represent the shortest rotation from one
* vector to another.
*
* Both vectors are assumed to be unit length.
*
* @param {quat} out the receiving quaternion.
* @param {vec3} a the initial vector
* @param {vec3} b the destination vector
* @returns {quat} out
*/
var rotationTo = (function() {
var tmpvec3 = create$4();
var xUnitVec3 = fromValues$4(1,0,0);
var yUnitVec3 = fromValues$4(0,1,0);
return function(out, a, b) {
var dot$$1 = dot(a, b);
if (dot$$1 < -0.999999) {
cross(tmpvec3, xUnitVec3, a);
if (len(tmpvec3) < 0.000001)
{ cross(tmpvec3, yUnitVec3, a); }
normalize(tmpvec3, tmpvec3);
setAxisAngle(out, tmpvec3, Math.PI);
return out;
} else if (dot$$1 > 0.999999) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
return out;
} else {
cross(tmpvec3, a, b);
out[0] = tmpvec3[0];
out[1] = tmpvec3[1];
out[2] = tmpvec3[2];
out[3] = 1 + dot$$1;
return normalize$2(out, out);
}
};
})();
/**
* Performs a spherical linear interpolation with two control points
*
* @param {quat} out the receiving quaternion
* @param {quat} a the first operand
* @param {quat} b the second operand
* @param {quat} c the third operand
* @param {quat} d the fourth operand
* @param {Number} t interpolation amount, in the range [0-1], between the two inputs
* @returns {quat} out
*/
var sqlerp = (function () {
var temp1 = create$6();
var temp2 = create$6();
return function (out, a, b, c, d, t) {
slerp(temp1, a, d, t);
slerp(temp2, b, c, t);
slerp(out, temp1, temp2, 2 * t * (1 - t));
return out;
};
}());
/**
* Sets the specified quaternion with values corresponding to the given
* axes. Each axis is a vec3 and is expected to be unit length and
* perpendicular to all other specified axes.
*
* @param {vec3} view the vector representing the viewing direction
* @param {vec3} right the vector representing the local "right" direction
* @param {vec3} up the vector representing the local "up" direction
* @returns {quat} out
*/
var setAxes = (function() {
var matr = create$2();
return function(out, view, right, up) {
matr[0] = right[0];
matr[3] = right[1];
matr[6] = right[2];
matr[1] = up[0];
matr[4] = up[1];
matr[7] = up[2];
matr[2] = -view[0];
matr[5] = -view[1];
matr[8] = -view[2];
return normalize$2(out, fromMat3(out, matr));
};
})();
/**
* Dual Quaternion<br>
* Format: [real, dual]<br>
* Quaternion format: XYZW<br>
* Make sure to have normalized dual quaternions, otherwise the functions may not work as intended.<br>
* @module quat2
*/
/**
* Creates a new identity dual quat
*
* @returns {quat2} a new dual quaternion [real -> rotation, dual -> translation]
*/
function create$7() {
var dq = new ARRAY_TYPE(8);
dq[0] = 0;
dq[1] = 0;
dq[2] = 0;
dq[3] = 1;
dq[4] = 0;
dq[5] = 0;
dq[6] = 0;
dq[7] = 0;
return dq;
}
/**
* Creates a new quat initialized with values from an existing quaternion
*
* @param {quat2} a dual quaternion to clone
* @returns {quat2} new dual quaternion
* @function
*/
function clone$8(a) {
var dq = new ARRAY_TYPE(8);
dq[0] = a[0];
dq[1] = a[1];
dq[2] = a[2];
dq[3] = a[3];
dq[4] = a[4];
dq[5] = a[5];
dq[6] = a[6];
dq[7] = a[7];
return dq;
}
/**
* Creates a new dual quat initialized with the given values
*
* @param {Number} x1 X component
* @param {Number} y1 Y component
* @param {Number} z1 Z component
* @param {Number} w1 W component
* @param {Number} x2 X component
* @param {Number} y2 Y component
* @param {Number} z2 Z component
* @param {Number} w2 W component
* @returns {quat2} new dual quaternion
* @function
*/
function fromValues$7(x1, y1, z1, w1, x2, y2, z2, w2) {
var dq = new ARRAY_TYPE(8);
dq[0] = x1;
dq[1] = y1;
dq[2] = z1;
dq[3] = w1;
dq[4] = x2;
dq[5] = y2;
dq[6] = z2;
dq[7] = w2;
return dq;
}
/**
* Creates a new dual quat from the given values (quat and translation)
*
* @param {Number} x1 X component
* @param {Number} y1 Y component
* @param {Number} z1 Z component
* @param {Number} w1 W component
* @param {Number} x2 X component (translation)
* @param {Number} y2 Y component (translation)
* @param {Number} z2 Z component (translation)
* @returns {quat2} new dual quaternion
* @function
*/
function fromRotationTranslationValues(x1, y1, z1, w1, x2, y2, z2) {
var dq = new ARRAY_TYPE(8);
dq[0] = x1;
dq[1] = y1;
dq[2] = z1;
dq[3] = w1;
var ax = x2 * 0.5,
ay = y2 * 0.5,
az = z2 * 0.5;
dq[4] = ax * w1 + ay * z1 - az * y1;
dq[5] = ay * w1 + az * x1 - ax * z1;
dq[6] = az * w1 + ax * y1 - ay * x1;
dq[7] = -ax * x1 - ay * y1 - az * z1;
return dq;
}
/**
* Creates a dual quat from a quaternion and a translation
*
* @param {quat2} dual quaternion receiving operation result
* @param {quat} q quaternion
* @param {vec3} t tranlation vector
* @returns {quat2} dual quaternion receiving operation result
* @function
*/
function fromRotationTranslation$1(out, q, t) {
var ax = t[0] * 0.5,
ay = t[1] * 0.5,
az = t[2] * 0.5,
bx = q[0],
by = q[1],
bz = q[2],
bw = q[3];
out[0] = bx;
out[1] = by;
out[2] = bz;
out[3] = bw;
out[4] = ax * bw + ay * bz - az * by;
out[5] = ay * bw + az * bx - ax * bz;
out[6] = az * bw + ax * by - ay * bx;
out[7] = -ax * bx - ay * by - az * bz;
return out;
}
/**
* Creates a dual quat from a translation
*
* @param {quat2} dual quaternion receiving operation result
* @param {vec3} t translation vector
* @returns {quat2} dual quaternion receiving operation result
* @function
*/
function fromTranslation$3(out, t) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
out[4] = t[0] * 0.5;
out[5] = t[1] * 0.5;
out[6] = t[2] * 0.5;
out[7] = 0;
return out;
}
/**
* Creates a dual quat from a quaternion
*
* @param {quat2} dual quaternion receiving operation result
* @param {quat} q the quaternion
* @returns {quat2} dual quaternion receiving operation result
* @function
*/
function fromRotation$4(out, q) {
out[0] = q[0];
out[1] = q[1];
out[2] = q[2];
out[3] = q[3];
out[4] = 0;
out[5] = 0;
out[6] = 0;
out[7] = 0;
return out;
}
/**
* Creates a new dual quat from a matrix (4x4)
*
* @param {quat2} out the dual quaternion
* @param {mat4} a the matrix
* @returns {quat2} dual quat receiving operation result
* @function
*/
function fromMat4$1(out, a) {
//TODO Optimize this
var outer = create$6();
getRotation(outer, a);
var t = new ARRAY_TYPE(3);
getTranslation(t, a);
fromRotationTranslation$1(out, outer, t);
return out;
}
/**
* Copy the values from one dual quat to another
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a the source dual quaternion
* @returns {quat2} out
* @function
*/
function copy$7(out, a) {
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
return out;
}
/**
* Set a dual quat to the identity dual quaternion
*
* @param {quat2} out the receiving quaternion
* @returns {quat2} out
*/
function identity$5(out) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 1;
out[4] = 0;
out[5] = 0;
out[6] = 0;
out[7] = 0;
return out;
}
/**
* Set the components of a dual quat to the given values
*
* @param {quat2} out the receiving quaternion
* @param {Number} x1 X component
* @param {Number} y1 Y component
* @param {Number} z1 Z component
* @param {Number} w1 W component
* @param {Number} x2 X component
* @param {Number} y2 Y component
* @param {Number} z2 Z component
* @param {Number} w2 W component
* @returns {quat2} out
* @function
*/
function set$7(out, x1, y1, z1, w1, x2, y2, z2, w2) {
out[0] = x1;
out[1] = y1;
out[2] = z1;
out[3] = w1;
out[4] = x2;
out[5] = y2;
out[6] = z2;
out[7] = w2;
return out;
}
/**
* Gets the real part of a dual quat
* @param {quat} out real part
* @param {quat2} a Dual Quaternion
* @return {quat} real part
*/
var getReal = copy$6;
/**
* Gets the dual part of a dual quat
* @param {quat} out dual part
* @param {quat2} a Dual Quaternion
* @return {quat} dual part
*/
function getDual(out, a) {
out[0] = a[4];
out[1] = a[5];
out[2] = a[6];
out[3] = a[7];
return out;
}
/**
* Set the real component of a dual quat to the given quaternion
*
* @param {quat2} out the receiving quaternion
* @param {quat} q a quaternion representing the real part
* @returns {quat2} out
* @function
*/
var setReal = copy$6;
/**
* Set the dual component of a dual quat to the given quaternion
*
* @param {quat2} out the receiving quaternion
* @param {quat} q a quaternion representing the dual part
* @returns {quat2} out
* @function
*/
function setDual(out, q) {
out[4] = q[0];
out[5] = q[1];
out[6] = q[2];
out[7] = q[3];
return out;
}
/**
* Gets the translation of a normalized dual quat
* @param {vec3} out translation
* @param {quat2} a Dual Quaternion to be decomposed
* @return {vec3} translation
*/
function getTranslation$1(out, a) {
var ax = a[4],
ay = a[5],
az = a[6],
aw = a[7],
bx = -a[0],
by = -a[1],
bz = -a[2],
bw = a[3];
out[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
out[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
out[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
return out;
}
/**
* Translates a dual quat by the given vector
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a the dual quaternion to translate
* @param {vec3} v vector to translate by
* @returns {quat2} out
*/
function translate$4(out, a, v) {
var ax1 = a[0],
ay1 = a[1],
az1 = a[2],
aw1 = a[3],
bx1 = v[0] * 0.5,
by1 = v[1] * 0.5,
bz1 = v[2] * 0.5,
ax2 = a[4],
ay2 = a[5],
az2 = a[6],
aw2 = a[7];
out[0] = ax1;
out[1] = ay1;
out[2] = az1;
out[3] = aw1;
out[4] = aw1 * bx1 + ay1 * bz1 - az1 * by1 + ax2;
out[5] = aw1 * by1 + az1 * bx1 - ax1 * bz1 + ay2;
out[6] = aw1 * bz1 + ax1 * by1 - ay1 * bx1 + az2;
out[7] = -ax1 * bx1 - ay1 * by1 - az1 * bz1 + aw2;
return out;
}
/**
* Rotates a dual quat around the X axis
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a the dual quaternion to rotate
* @param {number} rad how far should the rotation be
* @returns {quat2} out
*/
function rotateX$3(out, a, rad) {
var bx = -a[0],
by = -a[1],
bz = -a[2],
bw = a[3],
ax = a[4],
ay = a[5],
az = a[6],
aw = a[7],
ax1 = ax * bw + aw * bx + ay * bz - az * by,
ay1 = ay * bw + aw * by + az * bx - ax * bz,
az1 = az * bw + aw * bz + ax * by - ay * bx,
aw1 = aw * bw - ax * bx - ay * by - az * bz;
rotateX$2(out, a, rad);
bx = out[0];
by = out[1];
bz = out[2];
bw = out[3];
out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
return out;
}
/**
* Rotates a dual quat around the Y axis
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a the dual quaternion to rotate
* @param {number} rad how far should the rotation be
* @returns {quat2} out
*/
function rotateY$3(out, a, rad) {
var bx = -a[0],
by = -a[1],
bz = -a[2],
bw = a[3],
ax = a[4],
ay = a[5],
az = a[6],
aw = a[7],
ax1 = ax * bw + aw * bx + ay * bz - az * by,
ay1 = ay * bw + aw * by + az * bx - ax * bz,
az1 = az * bw + aw * bz + ax * by - ay * bx,
aw1 = aw * bw - ax * bx - ay * by - az * bz;
rotateY$2(out, a, rad);
bx = out[0];
by = out[1];
bz = out[2];
bw = out[3];
out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
return out;
}
/**
* Rotates a dual quat around the Z axis
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a the dual quaternion to rotate
* @param {number} rad how far should the rotation be
* @returns {quat2} out
*/
function rotateZ$3(out, a, rad) {
var bx = -a[0],
by = -a[1],
bz = -a[2],
bw = a[3],
ax = a[4],
ay = a[5],
az = a[6],
aw = a[7],
ax1 = ax * bw + aw * bx + ay * bz - az * by,
ay1 = ay * bw + aw * by + az * bx - ax * bz,
az1 = az * bw + aw * bz + ax * by - ay * bx,
aw1 = aw * bw - ax * bx - ay * by - az * bz;
rotateZ$2(out, a, rad);
bx = out[0];
by = out[1];
bz = out[2];
bw = out[3];
out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
return out;
}
/**
* Rotates a dual quat by a given quaternion (a * q)
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a the dual quaternion to rotate
* @param {quat} q quaternion to rotate by
* @returns {quat2} out
*/
function rotateByQuatAppend(out, a, q) {
var qx = q[0],
qy = q[1],
qz = q[2],
qw = q[3],
ax = a[0],
ay = a[1],
az = a[2],
aw = a[3];
out[0] = ax * qw + aw * qx + ay * qz - az * qy;
out[1] = ay * qw + aw * qy + az * qx - ax * qz;
out[2] = az * qw + aw * qz + ax * qy - ay * qx;
out[3] = aw * qw - ax * qx - ay * qy - az * qz;
ax = a[4];
ay = a[5];
az = a[6];
aw = a[7];
out[4] = ax * qw + aw * qx + ay * qz - az * qy;
out[5] = ay * qw + aw * qy + az * qx - ax * qz;
out[6] = az * qw + aw * qz + ax * qy - ay * qx;
out[7] = aw * qw - ax * qx - ay * qy - az * qz;
return out;
}
/**
* Rotates a dual quat by a given quaternion (q * a)
*
* @param {quat2} out the receiving dual quaternion
* @param {quat} q quaternion to rotate by
* @param {quat2} a the dual quaternion to rotate
* @returns {quat2} out
*/
function rotateByQuatPrepend(out, q, a) {
var qx = q[0],
qy = q[1],
qz = q[2],
qw = q[3],
bx = a[0],
by = a[1],
bz = a[2],
bw = a[3];
out[0] = qx * bw + qw * bx + qy * bz - qz * by;
out[1] = qy * bw + qw * by + qz * bx - qx * bz;
out[2] = qz * bw + qw * bz + qx * by - qy * bx;
out[3] = qw * bw - qx * bx - qy * by - qz * bz;
bx = a[4];
by = a[5];
bz = a[6];
bw = a[7];
out[4] = qx * bw + qw * bx + qy * bz - qz * by;
out[5] = qy * bw + qw * by + qz * bx - qx * bz;
out[6] = qz * bw + qw * bz + qx * by - qy * bx;
out[7] = qw * bw - qx * bx - qy * by - qz * bz;
return out;
}
/**
* Rotates a dual quat around a given axis. Does the normalisation automatically
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a the dual quaternion to rotate
* @param {vec3} axis the axis to rotate around
* @param {Number} rad how far the rotation should be
* @returns {quat2} out
*/
function rotateAroundAxis(out, a, axis, rad) {
//Special case for rad = 0
if (Math.abs(rad) < EPSILON) {
return copy$7(out, a);
}
var axisLength = Math.sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
rad = rad * 0.5;
var s = Math.sin(rad);
var bx = s * axis[0] / axisLength;
var by = s * axis[1] / axisLength;
var bz = s * axis[2] / axisLength;
var bw = Math.cos(rad);
var ax1 = a[0],
ay1 = a[1],
az1 = a[2],
aw1 = a[3];
out[0] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
out[1] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
out[2] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
out[3] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
var ax = a[4],
ay = a[5],
az = a[6],
aw = a[7];
out[4] = ax * bw + aw * bx + ay * bz - az * by;
out[5] = ay * bw + aw * by + az * bx - ax * bz;
out[6] = az * bw + aw * bz + ax * by - ay * bx;
out[7] = aw * bw - ax * bx - ay * by - az * bz;
return out;
}
/**
* Adds two dual quat's
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a the first operand
* @param {quat2} b the second operand
* @returns {quat2} out
* @function
*/
function add$7(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
out[2] = a[2] + b[2];
out[3] = a[3] + b[3];
out[4] = a[4] + b[4];
out[5] = a[5] + b[5];
out[6] = a[6] + b[6];
out[7] = a[7] + b[7];
return out;
}
/**
* Multiplies two dual quat's
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a the first operand
* @param {quat2} b the second operand
* @returns {quat2} out
*/
function multiply$7(out, a, b) {
var ax0 = a[0],
ay0 = a[1],
az0 = a[2],
aw0 = a[3],
bx1 = b[4],
by1 = b[5],
bz1 = b[6],
bw1 = b[7],
ax1 = a[4],
ay1 = a[5],
az1 = a[6],
aw1 = a[7],
bx0 = b[0],
by0 = b[1],
bz0 = b[2],
bw0 = b[3];
out[0] = ax0 * bw0 + aw0 * bx0 + ay0 * bz0 - az0 * by0;
out[1] = ay0 * bw0 + aw0 * by0 + az0 * bx0 - ax0 * bz0;
out[2] = az0 * bw0 + aw0 * bz0 + ax0 * by0 - ay0 * bx0;
out[3] = aw0 * bw0 - ax0 * bx0 - ay0 * by0 - az0 * bz0;
out[4] = ax0 * bw1 + aw0 * bx1 + ay0 * bz1 - az0 * by1 + ax1 * bw0 + aw1 * bx0 + ay1 * bz0 - az1 * by0;
out[5] = ay0 * bw1 + aw0 * by1 + az0 * bx1 - ax0 * bz1 + ay1 * bw0 + aw1 * by0 + az1 * bx0 - ax1 * bz0;
out[6] = az0 * bw1 + aw0 * bz1 + ax0 * by1 - ay0 * bx1 + az1 * bw0 + aw1 * bz0 + ax1 * by0 - ay1 * bx0;
out[7] = aw0 * bw1 - ax0 * bx1 - ay0 * by1 - az0 * bz1 + aw1 * bw0 - ax1 * bx0 - ay1 * by0 - az1 * bz0;
return out;
}
/**
* Alias for {@link quat2.multiply}
* @function
*/
var mul$7 = multiply$7;
/**
* Scales a dual quat by a scalar number
*
* @param {quat2} out the receiving dual quat
* @param {quat2} a the dual quat to scale
* @param {Number} b amount to scale the dual quat by
* @returns {quat2} out
* @function
*/
function scale$7(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
out[2] = a[2] * b;
out[3] = a[3] * b;
out[4] = a[4] * b;
out[5] = a[5] * b;
out[6] = a[6] * b;
out[7] = a[7] * b;
return out;
}
/**
* Calculates the dot product of two dual quat's (The dot product of the real parts)
*
* @param {quat2} a the first operand
* @param {quat2} b the second operand
* @returns {Number} dot product of a and b
* @function
*/
var dot$3 = dot$2;
/**
* Performs a linear interpolation between two dual quats's
* NOTE: The resulting dual quaternions won't always be normalized (The error is most noticeable when t = 0.5)
*
* @param {quat2} out the receiving dual quat
* @param {quat2} a the first operand
* @param {quat2} b the second operand
* @param {Number} t interpolation amount, in the range [0-1], between the two inputs
* @returns {quat2} out
*/
function lerp$3(out, a, b, t) {
var mt = 1 - t;
if (dot$3(a, b) < 0) { t = -t; }
out[0] = a[0] * mt + b[0] * t;
out[1] = a[1] * mt + b[1] * t;
out[2] = a[2] * mt + b[2] * t;
out[3] = a[3] * mt + b[3] * t;
out[4] = a[4] * mt + b[4] * t;
out[5] = a[5] * mt + b[5] * t;
out[6] = a[6] * mt + b[6] * t;
out[7] = a[7] * mt + b[7] * t;
return out;
}
/**
* Calculates the inverse of a dual quat. If they are normalized, conjugate is cheaper
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a dual quat to calculate inverse of
* @returns {quat2} out
*/
function invert$5(out, a) {
var sqlen = squaredLength$3(a);
out[0] = -a[0] / sqlen;
out[1] = -a[1] / sqlen;
out[2] = -a[2] / sqlen;
out[3] = a[3] / sqlen;
out[4] = -a[4] / sqlen;
out[5] = -a[5] / sqlen;
out[6] = -a[6] / sqlen;
out[7] = a[7] / sqlen;
return out;
}
/**
* Calculates the conjugate of a dual quat
* If the dual quaternion is normalized, this function is faster than quat2.inverse and produces the same result.
*
* @param {quat2} out the receiving quaternion
* @param {quat2} a quat to calculate conjugate of
* @returns {quat2} out
*/
function conjugate$1(out, a) {
out[0] = -a[0];
out[1] = -a[1];
out[2] = -a[2];
out[3] = a[3];
out[4] = -a[4];
out[5] = -a[5];
out[6] = -a[6];
out[7] = a[7];
return out;
}
/**
* Calculates the length of a dual quat
*
* @param {quat2} a dual quat to calculate length of
* @returns {Number} length of a
* @function
*/
var length$3 = length$2;
/**
* Alias for {@link quat2.length}
* @function
*/
var len$3 = length$3;
/**
* Calculates the squared length of a dual quat
*
* @param {quat2} a dual quat to calculate squared length of
* @returns {Number} squared length of a
* @function
*/
var squaredLength$3 = squaredLength$2;
/**
* Alias for {@link quat2.squaredLength}
* @function
*/
var sqrLen$3 = squaredLength$3;
/**
* Normalize a dual quat
*
* @param {quat2} out the receiving dual quaternion
* @param {quat2} a dual quaternion to normalize
* @returns {quat2} out
* @function
*/
function normalize$3(out, a) {
var magnitude = squaredLength$3(a);
if (magnitude > 0) {
magnitude = Math.sqrt(magnitude);
out[0] = a[0] / magnitude;
out[1] = a[1] / magnitude;
out[2] = a[2] / magnitude;
out[3] = a[3] / magnitude;
out[4] = a[4] / magnitude;
out[5] = a[5] / magnitude;
out[6] = a[6] / magnitude;
out[7] = a[7] / magnitude;
}
return out;
}
/**
* Returns a string representation of a dual quatenion
*
* @param {quat2} a dual quaternion to represent as a string
* @returns {String} string representation of the dual quat
*/
function str$7(a) {
return 'quat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ')';
}
/**
* Returns whether or not the dual quaternions have exactly the same elements in the same position (when compared with ===)
*
* @param {quat2} a the first dual quaternion.
* @param {quat2} b the second dual quaternion.
* @returns {Boolean} true if the dual quaternions are equal, false otherwise.
*/
function exactEquals$7(a, b) {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] &&
a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7];
}
/**
* Returns whether or not the dual quaternions have approximately the same elements in the same position.
*
* @param {quat2} a the first dual quat.
* @param {quat2} b the second dual quat.
* @returns {Boolean} true if the dual quats are equal, false otherwise.
*/
function equals$8(a, b) {
var a0 = a[0],
a1 = a[1],
a2 = a[2],
a3 = a[3],
a4 = a[4],
a5 = a[5],
a6 = a[6],
a7 = a[7];
var b0 = b[0],
b1 = b[1],
b2 = b[2],
b3 = b[3],
b4 = b[4],
b5 = b[5],
b6 = b[6],
b7 = b[7];
return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) &&
Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) &&
Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) &&
Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) &&
Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)));
}
/**
* 2 Dimensional Vector
* @module vec2
*/
/**
* Creates a new, empty vec2
*
* @returns {vec2} a new 2D vector
*/
function create$8() {
var out = new ARRAY_TYPE(2);
out[0] = 0;
out[1] = 0;
return out;
}
/**
* Creates a new vec2 initialized with values from an existing vector
*
* @param {vec2} a vector to clone
* @returns {vec2} a new 2D vector
*/
function clone$9(a) {
var out = new ARRAY_TYPE(2);
out[0] = a[0];
out[1] = a[1];
return out;
}
/**
* Creates a new vec2 initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @returns {vec2} a new 2D vector
*/
function fromValues$8(x, y) {
var out = new ARRAY_TYPE(2);
out[0] = x;
out[1] = y;
return out;
}
/**
* Copy the values from one vec2 to another
*
* @param {vec2} out the receiving vector
* @param {vec2} a the source vector
* @returns {vec2} out
*/
function copy$8(out, a) {
out[0] = a[0];
out[1] = a[1];
return out;
}
/**
* Set the components of a vec2 to the given values
*
* @param {vec2} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @returns {vec2} out
*/
function set$8(out, x, y) {
out[0] = x;
out[1] = y;
return out;
}
/**
* Adds two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
function add$8(out, a, b) {
out[0] = a[0] + b[0];
out[1] = a[1] + b[1];
return out;
}
/**
* Subtracts vector b from vector a
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
function subtract$6(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
return out;
}
/**
* Multiplies two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
function multiply$8(out, a, b) {
out[0] = a[0] * b[0];
out[1] = a[1] * b[1];
return out;
}
/**
* Divides two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
function divide$2(out, a, b) {
out[0] = a[0] / b[0];
out[1] = a[1] / b[1];
return out;
}
/**
* Math.ceil the components of a vec2
*
* @param {vec2} out the receiving vector
* @param {vec2} a vector to ceil
* @returns {vec2} out
*/
function ceil$2(out, a) {
out[0] = Math.ceil(a[0]);
out[1] = Math.ceil(a[1]);
return out;
}
/**
* Math.floor the components of a vec2
*
* @param {vec2} out the receiving vector
* @param {vec2} a vector to floor
* @returns {vec2} out
*/
function floor$2(out, a) {
out[0] = Math.floor(a[0]);
out[1] = Math.floor(a[1]);
return out;
}
/**
* Returns the minimum of two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
function min$2(out, a, b) {
out[0] = Math.min(a[0], b[0]);
out[1] = Math.min(a[1], b[1]);
return out;
}
/**
* Returns the maximum of two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec2} out
*/
function max$2(out, a, b) {
out[0] = Math.max(a[0], b[0]);
out[1] = Math.max(a[1], b[1]);
return out;
}
/**
* Math.round the components of a vec2
*
* @param {vec2} out the receiving vector
* @param {vec2} a vector to round
* @returns {vec2} out
*/
function round$2 (out, a) {
out[0] = Math.round(a[0]);
out[1] = Math.round(a[1]);
return out;
}
/**
* Scales a vec2 by a scalar number
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {vec2} out
*/
function scale$8(out, a, b) {
out[0] = a[0] * b;
out[1] = a[1] * b;
return out;
}
/**
* Adds two vec2's after scaling the second operand by a scalar value
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @param {Number} scale the amount to scale b by before adding
* @returns {vec2} out
*/
function scaleAndAdd$2(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale);
out[1] = a[1] + (b[1] * scale);
return out;
}
/**
* Calculates the euclidian distance between two vec2's
*
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {Number} distance between a and b
*/
function distance$2(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1];
return Math.sqrt(x*x + y*y);
}
/**
* Calculates the squared euclidian distance between two vec2's
*
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {Number} squared distance between a and b
*/
function squaredDistance$2(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1];
return x*x + y*y;
}
/**
* Calculates the length of a vec2
*
* @param {vec2} a vector to calculate length of
* @returns {Number} length of a
*/
function length$4(a) {
var x = a[0],
y = a[1];
return Math.sqrt(x*x + y*y);
}
/**
* Calculates the squared length of a vec2
*
* @param {vec2} a vector to calculate squared length of
* @returns {Number} squared length of a
*/
function squaredLength$4 (a) {
var x = a[0],
y = a[1];
return x*x + y*y;
}
/**
* Negates the components of a vec2
*
* @param {vec2} out the receiving vector
* @param {vec2} a vector to negate
* @returns {vec2} out
*/
function negate$2(out, a) {
out[0] = -a[0];
out[1] = -a[1];
return out;
}
/**
* Returns the inverse of the components of a vec2
*
* @param {vec2} out the receiving vector
* @param {vec2} a vector to invert
* @returns {vec2} out
*/
function inverse$2(out, a) {
out[0] = 1.0 / a[0];
out[1] = 1.0 / a[1];
return out;
}
/**
* Normalize a vec2
*
* @param {vec2} out the receiving vector
* @param {vec2} a vector to normalize
* @returns {vec2} out
*/
function normalize$4(out, a) {
var x = a[0],
y = a[1];
var len = x*x + y*y;
if (len > 0) {
//TODO: evaluate use of glm_invsqrt here?
len = 1 / Math.sqrt(len);
out[0] = a[0] * len;
out[1] = a[1] * len;
}
return out;
}
/**
* Calculates the dot product of two vec2's
*
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {Number} dot product of a and b
*/
function dot$4(a, b) {
return a[0] * b[0] + a[1] * b[1];
}
/**
* Computes the cross product of two vec2's
* Note that the cross product must by definition produce a 3D vector
*
* @param {vec3} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @returns {vec3} out
*/
function cross$1(out, a, b) {
var z = a[0] * b[1] - a[1] * b[0];
out[0] = out[1] = 0;
out[2] = z;
return out;
}
/**
* Performs a linear interpolation between two vec2's
*
* @param {vec2} out the receiving vector
* @param {vec2} a the first operand
* @param {vec2} b the second operand
* @param {Number} t interpolation amount, in the range [0-1], between the two inputs
* @returns {vec2} out
*/
function lerp$4(out, a, b, t) {
var ax = a[0],
ay = a[1];
out[0] = ax + t * (b[0] - ax);
out[1] = ay + t * (b[1] - ay);
return out;
}
/**
* Generates a random vector with the given scale
*
* @param {vec2} out the receiving vector
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
* @returns {vec2} out
*/
function random$2(out, scale) {
scale = scale || 1.0;
var r = RANDOM() * 2.0 * Math.PI;
out[0] = Math.cos(r) * scale;
out[1] = Math.sin(r) * scale;
return out;
}
/**
* Transforms the vec2 with a mat2
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat2} m matrix to transform with
* @returns {vec2} out
*/
function transformMat2(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[2] * y;
out[1] = m[1] * x + m[3] * y;
return out;
}
/**
* Transforms the vec2 with a mat2d
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat2d} m matrix to transform with
* @returns {vec2} out
*/
function transformMat2d(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[2] * y + m[4];
out[1] = m[1] * x + m[3] * y + m[5];
return out;
}
/**
* Transforms the vec2 with a mat3
* 3rd vector component is implicitly '1'
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat3} m matrix to transform with
* @returns {vec2} out
*/
function transformMat3$1(out, a, m) {
var x = a[0],
y = a[1];
out[0] = m[0] * x + m[3] * y + m[6];
out[1] = m[1] * x + m[4] * y + m[7];
return out;
}
/**
* Transforms the vec2 with a mat4
* 3rd vector component is implicitly '0'
* 4th vector component is implicitly '1'
*
* @param {vec2} out the receiving vector
* @param {vec2} a the vector to transform
* @param {mat4} m matrix to transform with
* @returns {vec2} out
*/
function transformMat4$2(out, a, m) {
var x = a[0];
var y = a[1];
out[0] = m[0] * x + m[4] * y + m[12];
out[1] = m[1] * x + m[5] * y + m[13];
return out;
}
/**
* Rotate a 2D vector
* @param {vec2} out The receiving vec2
* @param {vec2} a The vec2 point to rotate
* @param {vec2} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec2} out
*/
function rotate$4(out, a, b, c) {
//Translate point to the origin
var p0 = a[0] - b[0],
p1 = a[1] - b[1],
sinC = Math.sin(c),
cosC = Math.cos(c);
//perform rotation and translate to correct position
out[0] = p0*cosC - p1*sinC + b[0];
out[1] = p0*sinC + p1*cosC + b[1];
return out;
}
/**
* Get the angle between two 2D vectors
* @param {vec2} a The first operand
* @param {vec2} b The second operand
* @returns {Number} The angle in radians
*/
function angle$1(a, b) {
var x1 = a[0],
y1 = a[1],
x2 = b[0],
y2 = b[1];
var len1 = x1*x1 + y1*y1;
if (len1 > 0) {
//TODO: evaluate use of glm_invsqrt here?
len1 = 1 / Math.sqrt(len1);
}
var len2 = x2*x2 + y2*y2;
if (len2 > 0) {
//TODO: evaluate use of glm_invsqrt here?
len2 = 1 / Math.sqrt(len2);
}
var cosine = (x1 * x2 + y1 * y2) * len1 * len2;
if(cosine > 1.0) {
return 0;
}
else if(cosine < -1.0) {
return Math.PI;
} else {
return Math.acos(cosine);
}
}
/**
* Returns a string representation of a vector
*
* @param {vec2} a vector to represent as a string
* @returns {String} string representation of the vector
*/
function str$8(a) {
return 'vec2(' + a[0] + ', ' + a[1] + ')';
}
/**
* Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
*
* @param {vec2} a The first vector.
* @param {vec2} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
function exactEquals$8(a, b) {
return a[0] === b[0] && a[1] === b[1];
}
/**
* Returns whether or not the vectors have approximately the same elements in the same position.
*
* @param {vec2} a The first vector.
* @param {vec2} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
function equals$9(a, b) {
var a0 = a[0], a1 = a[1];
var b0 = b[0], b1 = b[1];
return (Math.abs(a0 - b0) <= EPSILON*Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
Math.abs(a1 - b1) <= EPSILON*Math.max(1.0, Math.abs(a1), Math.abs(b1)));
}
/**
* Alias for {@link vec2.length}
* @function
*/
var len$4 = length$4;
/**
* Alias for {@link vec2.subtract}
* @function
*/
var sub$6 = subtract$6;
/**
* Alias for {@link vec2.multiply}
* @function
*/
var mul$8 = multiply$8;
/**
* Alias for {@link vec2.divide}
* @function
*/
var div$2 = divide$2;
/**
* Alias for {@link vec2.distance}
* @function
*/
var dist$2 = distance$2;
/**
* Alias for {@link vec2.squaredDistance}
* @function
*/
var sqrDist$2 = squaredDistance$2;
/**
* Alias for {@link vec2.squaredLength}
* @function
*/
var sqrLen$4 = squaredLength$4;
/**
* Perform some operation over an array of vec2s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
var forEach$2 = (function() {
var vec = create$8();
return function(a, stride, offset, count, fn, arg) {
var i, l;
if(!stride) {
stride = 2;
}
if(!offset) {
offset = 0;
}
if(count) {
l = Math.min((count * stride) + offset, a.length);
} else {
l = a.length;
}
for(i = offset; i < l; i += stride) {
vec[0] = a[i]; vec[1] = a[i+1];
fn(vec, vec, arg);
a[i] = vec[0]; a[i+1] = vec[1];
}
return a;
};
})();
//
var CircleStyleLayer = (function (StyleLayer$$1) {
function CircleStyleLayer(layer ) {
StyleLayer$$1.call(this, layer, properties);
}
if ( StyleLayer$$1 ) CircleStyleLayer.__proto__ = StyleLayer$$1;
CircleStyleLayer.prototype = Object.create( StyleLayer$$1 && StyleLayer$$1.prototype );
CircleStyleLayer.prototype.constructor = CircleStyleLayer;
CircleStyleLayer.prototype.createBucket = function createBucket (parameters ) {
return new CircleBucket(parameters);
};
CircleStyleLayer.prototype.queryRadius = function queryRadius (bucket ) {
var circleBucket = (bucket );
return getMaximumPaintValue('circle-radius', this, circleBucket) +
getMaximumPaintValue('circle-stroke-width', this, circleBucket) +
translateDistance(this.paint.get('circle-translate'));
};
CircleStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature (queryGeometry ,
feature ,
featureState ,
geometry ,
zoom ,
transform ,
pixelsToTileUnits ,
posMatrix ) {
var this$1 = this;
var translatedPolygon = translate(queryGeometry,
this.paint.get('circle-translate'),
this.paint.get('circle-translate-anchor'),
transform.angle, pixelsToTileUnits);
var radius = this.paint.get('circle-radius').evaluate(feature, featureState);
var stroke = this.paint.get('circle-stroke-width').evaluate(feature, featureState);
var size = radius + stroke;
// For pitch-alignment: map, compare feature geometry to query geometry in the plane of the tile
// // Otherwise, compare geometry in the plane of the viewport
// // A circle with fixed scaling relative to the viewport gets larger in tile space as it moves into the distance
// // A circle with fixed scaling relative to the map gets smaller in viewport space as it moves into the distance
var alignWithMap = this.paint.get('circle-pitch-alignment') === 'map';
var transformedPolygon = alignWithMap ? translatedPolygon : projectQueryGeometry(translatedPolygon, posMatrix, transform);
var transformedSize = alignWithMap ? size * pixelsToTileUnits : size;
for (var i$1 = 0, list$1 = geometry; i$1 < list$1.length; i$1 += 1) {
var ring = list$1[i$1];
for (var i = 0, list = ring; i < list.length; i += 1) {
var point = list[i];
var transformedPoint = alignWithMap ? point : projectPoint(point, posMatrix, transform);
var adjustedSize = transformedSize;
var projectedCenter = transformMat4$1([], [point.x, point.y, 0, 1], posMatrix);
if (this$1.paint.get('circle-pitch-scale') === 'viewport' && this$1.paint.get('circle-pitch-alignment') === 'map') {
adjustedSize *= projectedCenter[3] / transform.cameraToCenterDistance;
} else if (this$1.paint.get('circle-pitch-scale') === 'map' && this$1.paint.get('circle-pitch-alignment') === 'viewport') {
adjustedSize *= transform.cameraToCenterDistance / projectedCenter[3];
}
if (multiPolygonIntersectsBufferedPoint(transformedPolygon, transformedPoint, adjustedSize)) { return true; }
}
}
return false;
};
return CircleStyleLayer;
}(StyleLayer));
function projectPoint(p , posMatrix , transform ) {
var point = transformMat4$1([], [p.x, p.y, 0, 1], posMatrix);
return new pointGeometry(
(point[0] / point[3] + 1) * transform.width * 0.5,
(point[1] / point[3] + 1) * transform.height * 0.5);
}
function projectQueryGeometry(queryGeometry , posMatrix , transform ) {
return queryGeometry.map(function (r) {
return r.map(function (p) {
return projectPoint(p, posMatrix, transform);
});
});
}
//
var HeatmapBucket = (function (CircleBucket$$1) {
function HeatmapBucket () {
CircleBucket$$1.apply(this, arguments);
}if ( CircleBucket$$1 ) HeatmapBucket.__proto__ = CircleBucket$$1;
HeatmapBucket.prototype = Object.create( CircleBucket$$1 && CircleBucket$$1.prototype );
HeatmapBucket.prototype.constructor = HeatmapBucket;
return HeatmapBucket;
}(CircleBucket));
register('HeatmapBucket', HeatmapBucket, {omit: ['layers']});
//
function createImage(image , ref , channels , data ) {
var width = ref.width;
var height = ref.height;
if (!data) {
data = new Uint8Array(width * height * channels);
} else if (data.length !== width * height * channels) {
throw new RangeError('mismatched image size');
}
image.width = width;
image.height = height;
image.data = data;
return image;
}
function resizeImage(image , ref , channels ) {
var width = ref.width;
var height = ref.height;
if (width === image.width && height === image.height) {
return;
}
var newImage = createImage({}, {width: width, height: height}, channels);
copyImage(image, newImage, {x: 0, y: 0}, {x: 0, y: 0}, {
width: Math.min(image.width, width),
height: Math.min(image.height, height)
}, channels);
image.width = width;
image.height = height;
image.data = newImage.data;
}
function copyImage(srcImg , dstImg , srcPt , dstPt , size , channels ) {
if (size.width === 0 || size.height === 0) {
return dstImg;
}
if (size.width > srcImg.width ||
size.height > srcImg.height ||
srcPt.x > srcImg.width - size.width ||
srcPt.y > srcImg.height - size.height) {
throw new RangeError('out of range source coordinates for image copy');
}
if (size.width > dstImg.width ||
size.height > dstImg.height ||
dstPt.x > dstImg.width - size.width ||
dstPt.y > dstImg.height - size.height) {
throw new RangeError('out of range destination coordinates for image copy');
}
var srcData = srcImg.data;
var dstData = dstImg.data;
assert_1(srcData !== dstData);
for (var y = 0; y < size.height; y++) {
var srcOffset = ((srcPt.y + y) * srcImg.width + srcPt.x) * channels;
var dstOffset = ((dstPt.y + y) * dstImg.width + dstPt.x) * channels;
for (var i = 0; i < size.width * channels; i++) {
dstData[dstOffset + i] = srcData[srcOffset + i];
}
}
return dstImg;
}
var AlphaImage = function AlphaImage(size , data ) {
createImage(this, size, 1, data);
};
AlphaImage.prototype.resize = function resize (size ) {
resizeImage(this, size, 1);
};
AlphaImage.prototype.clone = function clone () {
return new AlphaImage({width: this.width, height: this.height}, new Uint8Array(this.data));
};
AlphaImage.copy = function copy (srcImg , dstImg , srcPt , dstPt , size ) {
copyImage(srcImg, dstImg, srcPt, dstPt, size, 1);
};
// Not premultiplied, because ImageData is not premultiplied.
// UNPACK_PREMULTIPLY_ALPHA_WEBGL must be used when uploading to a texture.
var RGBAImage = function RGBAImage(size , data ) {
createImage(this, size, 4, data);
};
RGBAImage.prototype.resize = function resize (size ) {
resizeImage(this, size, 4);
};
RGBAImage.prototype.clone = function clone () {
return new RGBAImage({width: this.width, height: this.height}, new Uint8Array(this.data));
};
RGBAImage.copy = function copy (srcImg , dstImg , srcPt , dstPt , size ) {
copyImage(srcImg, dstImg, srcPt, dstPt, size, 4);
};
register('AlphaImage', AlphaImage);
register('RGBAImage', RGBAImage);
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
var paint$2 = new Properties({
"heatmap-radius": new DataDrivenProperty(styleSpec["paint_heatmap"]["heatmap-radius"]),
"heatmap-weight": new DataDrivenProperty(styleSpec["paint_heatmap"]["heatmap-weight"]),
"heatmap-intensity": new DataConstantProperty(styleSpec["paint_heatmap"]["heatmap-intensity"]),
"heatmap-color": new ColorRampProperty(styleSpec["paint_heatmap"]["heatmap-color"]),
"heatmap-opacity": new DataConstantProperty(styleSpec["paint_heatmap"]["heatmap-opacity"]),
});
// Note: without adding the explicit type annotation, Flow infers weaker types
// for these objects from their use in the constructor to StyleLayer, as
// {layout?: Properties<...>, paint: Properties<...>}
var properties$1 = ({ paint: paint$2 }
);
//
/**
* Given an expression that should evaluate to a color ramp, return
* a 256x1 px RGBA image representing that ramp expression.
*
* @private
*/
function renderColorRamp(expression , colorRampEvaluationParameter ) {
var colorRampData = new Uint8Array(256 * 4);
var evaluationGlobals = {};
for (var i = 0, j = 0; i < 256; i++, j += 4) {
evaluationGlobals[colorRampEvaluationParameter] = i / 255;
var pxColor = expression.evaluate((evaluationGlobals ));
// the colors are being unpremultiplied because Color uses
// premultiplied values, and the Texture class expects unpremultiplied ones
colorRampData[j + 0] = Math.floor(pxColor.r * 255 / pxColor.a);
colorRampData[j + 1] = Math.floor(pxColor.g * 255 / pxColor.a);
colorRampData[j + 2] = Math.floor(pxColor.b * 255 / pxColor.a);
colorRampData[j + 3] = Math.floor(pxColor.a * 255);
}
return new RGBAImage({width: 256, height: 1}, colorRampData);
}
//
var HeatmapStyleLayer = (function (StyleLayer$$1) {
function HeatmapStyleLayer(layer ) {
StyleLayer$$1.call(this, layer, properties$1);
// make sure color ramp texture is generated for default heatmap color too
this._updateColorRamp();
}
if ( StyleLayer$$1 ) HeatmapStyleLayer.__proto__ = StyleLayer$$1;
HeatmapStyleLayer.prototype = Object.create( StyleLayer$$1 && StyleLayer$$1.prototype );
HeatmapStyleLayer.prototype.constructor = HeatmapStyleLayer;
HeatmapStyleLayer.prototype.createBucket = function createBucket (options ) {
return new HeatmapBucket(options);
};
HeatmapStyleLayer.prototype._handleSpecialPaintPropertyUpdate = function _handleSpecialPaintPropertyUpdate (name ) {
if (name === 'heatmap-color') {
this._updateColorRamp();
}
};
HeatmapStyleLayer.prototype._updateColorRamp = function _updateColorRamp () {
var expression = this._transitionablePaint._values['heatmap-color'].value.expression;
this.colorRamp = renderColorRamp(expression, 'heatmapDensity');
this.colorRampTexture = null;
};
HeatmapStyleLayer.prototype.resize = function resize () {
if (this.heatmapFbo) {
this.heatmapFbo.destroy();
this.heatmapFbo = null;
}
};
HeatmapStyleLayer.prototype.queryRadius = function queryRadius () {
return 0;
};
HeatmapStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature () {
return false;
};
HeatmapStyleLayer.prototype.hasOffscreenPass = function hasOffscreenPass () {
return this.paint.get('heatmap-opacity') !== 0 && this.visibility !== 'none';
};
return HeatmapStyleLayer;
}(StyleLayer));
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
var paint$3 = new Properties({
"hillshade-illumination-direction": new DataConstantProperty(styleSpec["paint_hillshade"]["hillshade-illumination-direction"]),
"hillshade-illumination-anchor": new DataConstantProperty(styleSpec["paint_hillshade"]["hillshade-illumination-anchor"]),
"hillshade-exaggeration": new DataConstantProperty(styleSpec["paint_hillshade"]["hillshade-exaggeration"]),
"hillshade-shadow-color": new DataConstantProperty(styleSpec["paint_hillshade"]["hillshade-shadow-color"]),
"hillshade-highlight-color": new DataConstantProperty(styleSpec["paint_hillshade"]["hillshade-highlight-color"]),
"hillshade-accent-color": new DataConstantProperty(styleSpec["paint_hillshade"]["hillshade-accent-color"]),
});
// Note: without adding the explicit type annotation, Flow infers weaker types
// for these objects from their use in the constructor to StyleLayer, as
// {layout?: Properties<...>, paint: Properties<...>}
var properties$2 = ({ paint: paint$3 }
);
//
var HillshadeStyleLayer = (function (StyleLayer$$1) {
function HillshadeStyleLayer(layer ) {
StyleLayer$$1.call(this, layer, properties$2);
}
if ( StyleLayer$$1 ) HillshadeStyleLayer.__proto__ = StyleLayer$$1;
HillshadeStyleLayer.prototype = Object.create( StyleLayer$$1 && StyleLayer$$1.prototype );
HillshadeStyleLayer.prototype.constructor = HillshadeStyleLayer;
HillshadeStyleLayer.prototype.hasOffscreenPass = function hasOffscreenPass () {
return this.paint.get('hillshade-exaggeration') !== 0 && this.visibility !== 'none';
};
return HillshadeStyleLayer;
}(StyleLayer));
//
var layout$2 = createLayout([
{name: 'a_pos', components: 2, type: 'Int16'}
], 4);
var members$1 = layout$2.members;
var size$1 = layout$2.size;
var alignment$1 = layout$2.alignment;
'use strict';
var earcut_1 = earcut;
var default_1 = earcut;
function earcut(data, holeIndices, dim) {
dim = dim || 2;
var hasHoles = holeIndices && holeIndices.length,
outerLen = hasHoles ? holeIndices[0] * dim : data.length,
outerNode = linkedList(data, 0, outerLen, dim, true),
triangles = [];
if (!outerNode) { return triangles; }
var minX, minY, maxX, maxY, x, y, invSize;
if (hasHoles) { outerNode = eliminateHoles(data, holeIndices, outerNode, dim); }
// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
if (data.length > 80 * dim) {
minX = maxX = data[0];
minY = maxY = data[1];
for (var i = dim; i < outerLen; i += dim) {
x = data[i];
y = data[i + 1];
if (x < minX) { minX = x; }
if (y < minY) { minY = y; }
if (x > maxX) { maxX = x; }
if (y > maxY) { maxY = y; }
}
// minX, minY and invSize are later used to transform coords into integers for z-order calculation
invSize = Math.max(maxX - minX, maxY - minY);
invSize = invSize !== 0 ? 1 / invSize : 0;
}
earcutLinked(outerNode, triangles, dim, minX, minY, invSize);
return triangles;
}
// create a circular doubly linked list from polygon points in the specified winding order
function linkedList(data, start, end, dim, clockwise) {
var i, last;
if (clockwise === (signedArea(data, start, end, dim) > 0)) {
for (i = start; i < end; i += dim) { last = insertNode(i, data[i], data[i + 1], last); }
} else {
for (i = end - dim; i >= start; i -= dim) { last = insertNode(i, data[i], data[i + 1], last); }
}
if (last && equals$a(last, last.next)) {
removeNode(last);
last = last.next;
}
return last;
}
// eliminate colinear or duplicate points
function filterPoints(start, end) {
if (!start) { return start; }
if (!end) { end = start; }
var p = start,
again;
do {
again = false;
if (!p.steiner && (equals$a(p, p.next) || area(p.prev, p, p.next) === 0)) {
removeNode(p);
p = end = p.prev;
if (p === p.next) { break; }
again = true;
} else {
p = p.next;
}
} while (again || p !== end);
return end;
}
// main ear slicing loop which triangulates a polygon (given as a linked list)
function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
if (!ear) { return; }
// interlink polygon nodes in z-order
if (!pass && invSize) { indexCurve(ear, minX, minY, invSize); }
var stop = ear,
prev, next;
// iterate through ears, slicing them one by one
while (ear.prev !== ear.next) {
prev = ear.prev;
next = ear.next;
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
// cut off the triangle
triangles.push(prev.i / dim);
triangles.push(ear.i / dim);
triangles.push(next.i / dim);
removeNode(ear);
// skipping the next vertice leads to less sliver triangles
ear = next.next;
stop = next.next;
continue;
}
ear = next;
// if we looped through the whole remaining polygon and can't find any more ears
if (ear === stop) {
// try filtering points and slicing again
if (!pass) {
earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
// if this didn't work, try curing all small self-intersections locally
} else if (pass === 1) {
ear = cureLocalIntersections(ear, triangles, dim);
earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
// as a last resort, try splitting the remaining polygon into two
} else if (pass === 2) {
splitEarcut(ear, triangles, dim, minX, minY, invSize);
}
break;
}
}
}
// check whether a polygon node forms a valid ear with adjacent nodes
function isEar(ear) {
var a = ear.prev,
b = ear,
c = ear.next;
if (area(a, b, c) >= 0) { return false; } // reflex, can't be an ear
// now make sure we don't have other points inside the potential ear
var p = ear.next.next;
while (p !== ear.prev) {
if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
area(p.prev, p, p.next) >= 0) { return false; }
p = p.next;
}
return true;
}
function isEarHashed(ear, minX, minY, invSize) {
var a = ear.prev,
b = ear,
c = ear.next;
if (area(a, b, c) >= 0) { return false; } // reflex, can't be an ear
// triangle bbox; min & max are calculated like this for speed
var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x),
minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y),
maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x),
maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y);
// z-order range for the current triangle bbox;
var minZ = zOrder(minTX, minTY, minX, minY, invSize),
maxZ = zOrder(maxTX, maxTY, minX, minY, invSize);
var p = ear.prevZ,
n = ear.nextZ;
// look for points inside the triangle in both directions
while (p && p.z >= minZ && n && n.z <= maxZ) {
if (p !== ear.prev && p !== ear.next &&
pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
area(p.prev, p, p.next) >= 0) { return false; }
p = p.prevZ;
if (n !== ear.prev && n !== ear.next &&
pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) &&
area(n.prev, n, n.next) >= 0) { return false; }
n = n.nextZ;
}
// look for remaining points in decreasing z-order
while (p && p.z >= minZ) {
if (p !== ear.prev && p !== ear.next &&
pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&
area(p.prev, p, p.next) >= 0) { return false; }
p = p.prevZ;
}
// look for remaining points in increasing z-order
while (n && n.z <= maxZ) {
if (n !== ear.prev && n !== ear.next &&
pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) &&
area(n.prev, n, n.next) >= 0) { return false; }
n = n.nextZ;
}
return true;
}
// go through all polygon nodes and cure small local self-intersections
function cureLocalIntersections(start, triangles, dim) {
var p = start;
do {
var a = p.prev,
b = p.next.next;
if (!equals$a(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
triangles.push(a.i / dim);
triangles.push(p.i / dim);
triangles.push(b.i / dim);
// remove two nodes involved
removeNode(p);
removeNode(p.next);
p = start = b;
}
p = p.next;
} while (p !== start);
return p;
}
// try splitting polygon into two and triangulate them independently
function splitEarcut(start, triangles, dim, minX, minY, invSize) {
// look for a valid diagonal that divides the polygon into two
var a = start;
do {
var b = a.next.next;
while (b !== a.prev) {
if (a.i !== b.i && isValidDiagonal(a, b)) {
// split the polygon in two by the diagonal
var c = splitPolygon(a, b);
// filter colinear points around the cuts
a = filterPoints(a, a.next);
c = filterPoints(c, c.next);
// run earcut on each half
earcutLinked(a, triangles, dim, minX, minY, invSize);
earcutLinked(c, triangles, dim, minX, minY, invSize);
return;
}
b = b.next;
}
a = a.next;
} while (a !== start);
}
// link every hole into the outer loop, producing a single-ring polygon without holes
function eliminateHoles(data, holeIndices, outerNode, dim) {
var queue = [],
i, len, start, end, list;
for (i = 0, len = holeIndices.length; i < len; i++) {
start = holeIndices[i] * dim;
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
list = linkedList(data, start, end, dim, false);
if (list === list.next) { list.steiner = true; }
queue.push(getLeftmost(list));
}
queue.sort(compareX);
// process holes from left to right
for (i = 0; i < queue.length; i++) {
eliminateHole(queue[i], outerNode);
outerNode = filterPoints(outerNode, outerNode.next);
}
return outerNode;
}
function compareX(a, b) {
return a.x - b.x;
}
// find a bridge between vertices that connects hole with an outer ring and and link it
function eliminateHole(hole, outerNode) {
outerNode = findHoleBridge(hole, outerNode);
if (outerNode) {
var b = splitPolygon(outerNode, hole);
filterPoints(b, b.next);
}
}
// David Eberly's algorithm for finding a bridge between hole and outer polygon
function findHoleBridge(hole, outerNode) {
var p = outerNode,
hx = hole.x,
hy = hole.y,
qx = -Infinity,
m;
// find a segment intersected by a ray from the hole's leftmost point to the left;
// segment's endpoint with lesser x will be potential connection point
do {
if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
if (x <= hx && x > qx) {
qx = x;
if (x === hx) {
if (hy === p.y) { return p; }
if (hy === p.next.y) { return p.next; }
}
m = p.x < p.next.x ? p : p.next;
}
}
p = p.next;
} while (p !== outerNode);
if (!m) { return null; }
if (hx === qx) { return m.prev; } // hole touches outer segment; pick lower endpoint
// look for points inside the triangle of hole point, segment intersection and endpoint;
// if there are no points found, we have a valid connection;
// otherwise choose the point of the minimum angle with the ray as connection point
var stop = m,
mx = m.x,
my = m.y,
tanMin = Infinity,
tan;
p = m.next;
while (p !== stop) {
if (hx >= p.x && p.x >= mx && hx !== p.x &&
pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) {
m = p;
tanMin = tan;
}
}
p = p.next;
}
return m;
}
// interlink polygon nodes in z-order
function indexCurve(start, minX, minY, invSize) {
var p = start;
do {
if (p.z === null) { p.z = zOrder(p.x, p.y, minX, minY, invSize); }
p.prevZ = p.prev;
p.nextZ = p.next;
p = p.next;
} while (p !== start);
p.prevZ.nextZ = null;
p.prevZ = null;
sortLinked(p);
}
// Simon Tatham's linked list merge sort algorithm
// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
function sortLinked(list) {
var i, p, q, e, tail, numMerges, pSize, qSize,
inSize = 1;
do {
p = list;
list = null;
tail = null;
numMerges = 0;
while (p) {
numMerges++;
q = p;
pSize = 0;
for (i = 0; i < inSize; i++) {
pSize++;
q = q.nextZ;
if (!q) { break; }
}
qSize = inSize;
while (pSize > 0 || (qSize > 0 && q)) {
if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
e = p;
p = p.nextZ;
pSize--;
} else {
e = q;
q = q.nextZ;
qSize--;
}
if (tail) { tail.nextZ = e; }
else { list = e; }
e.prevZ = tail;
tail = e;
}
p = q;
}
tail.nextZ = null;
inSize *= 2;
} while (numMerges > 1);
return list;
}
// z-order of a point given coords and inverse of the longer side of data bbox
function zOrder(x, y, minX, minY, invSize) {
// coords are transformed into non-negative 15-bit integer range
x = 32767 * (x - minX) * invSize;
y = 32767 * (y - minY) * invSize;
x = (x | (x << 8)) & 0x00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F;
x = (x | (x << 2)) & 0x33333333;
x = (x | (x << 1)) & 0x55555555;
y = (y | (y << 8)) & 0x00FF00FF;
y = (y | (y << 4)) & 0x0F0F0F0F;
y = (y | (y << 2)) & 0x33333333;
y = (y | (y << 1)) & 0x55555555;
return x | (y << 1);
}
// find the leftmost node of a polygon ring
function getLeftmost(start) {
var p = start,
leftmost = start;
do {
if (p.x < leftmost.x) { leftmost = p; }
p = p.next;
} while (p !== start);
return leftmost;
}
// check if a point lies within a convex triangle
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
(ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
(bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
}
// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
function isValidDiagonal(a, b) {
return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) &&
locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b);
}
// signed area of a triangle
function area(p, q, r) {
return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
}
// check if two points are equal
function equals$a(p1, p2) {
return p1.x === p2.x && p1.y === p2.y;
}
// check if two segments intersect
function intersects(p1, q1, p2, q2) {
if ((equals$a(p1, q1) && equals$a(p2, q2)) ||
(equals$a(p1, q2) && equals$a(p2, q1))) { return true; }
return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 &&
area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0;
}
// check if a polygon diagonal intersects any polygon segments
function intersectsPolygon(a, b) {
var p = a;
do {
if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
intersects(p, p.next, a, b)) { return true; }
p = p.next;
} while (p !== a);
return false;
}
// check if a polygon diagonal is locally inside the polygon
function locallyInside(a, b) {
return area(a.prev, a, a.next) < 0 ?
area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :
area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
}
// check if the middle point of a polygon diagonal is inside the polygon
function middleInside(a, b) {
var p = a,
inside = false,
px = (a.x + b.x) / 2,
py = (a.y + b.y) / 2;
do {
if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&
(px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
{ inside = !inside; }
p = p.next;
} while (p !== a);
return inside;
}
// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
// if one belongs to the outer ring and another to a hole, it merges it into a single ring
function splitPolygon(a, b) {
var a2 = new Node(a.i, a.x, a.y),
b2 = new Node(b.i, b.x, b.y),
an = a.next,
bp = b.prev;
a.next = b;
b.prev = a;
a2.next = an;
an.prev = a2;
b2.next = a2;
a2.prev = b2;
bp.next = b2;
b2.prev = bp;
return b2;
}
// create a node and optionally link it with previous one (in a circular doubly linked list)
function insertNode(i, x, y, last) {
var p = new Node(i, x, y);
if (!last) {
p.prev = p;
p.next = p;
} else {
p.next = last.next;
p.prev = last;
last.next.prev = p;
last.next = p;
}
return p;
}
function removeNode(p) {
p.next.prev = p.prev;
p.prev.next = p.next;
if (p.prevZ) { p.prevZ.nextZ = p.nextZ; }
if (p.nextZ) { p.nextZ.prevZ = p.prevZ; }
}
function Node(i, x, y) {
// vertice index in coordinates array
this.i = i;
// vertex coordinates
this.x = x;
this.y = y;
// previous and next vertice nodes in a polygon ring
this.prev = null;
this.next = null;
// z-order curve value
this.z = null;
// previous and next nodes in z-order
this.prevZ = null;
this.nextZ = null;
// indicates whether this is a steiner point
this.steiner = false;
}
// return a percentage difference between the polygon area and its triangulation area;
// used to verify correctness of triangulation
earcut.deviation = function (data, holeIndices, dim, triangles) {
var hasHoles = holeIndices && holeIndices.length;
var outerLen = hasHoles ? holeIndices[0] * dim : data.length;
var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));
if (hasHoles) {
for (var i = 0, len = holeIndices.length; i < len; i++) {
var start = holeIndices[i] * dim;
var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
polygonArea -= Math.abs(signedArea(data, start, end, dim));
}
}
var trianglesArea = 0;
for (i = 0; i < triangles.length; i += 3) {
var a = triangles[i] * dim;
var b = triangles[i + 1] * dim;
var c = triangles[i + 2] * dim;
trianglesArea += Math.abs(
(data[a] - data[c]) * (data[b + 1] - data[a + 1]) -
(data[a] - data[b]) * (data[c + 1] - data[a + 1]));
}
return polygonArea === 0 && trianglesArea === 0 ? 0 :
Math.abs((trianglesArea - polygonArea) / polygonArea);
};
function signedArea(data, start, end, dim) {
var sum = 0;
for (var i = start, j = end - dim; i < end; i += dim) {
sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
j = i;
}
return sum;
}
// turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts
earcut.flatten = function (data) {
var dim = data[0][0].length,
result = {vertices: [], holes: [], dimensions: dim},
holeIndex = 0;
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].length; j++) {
for (var d = 0; d < dim; d++) { result.vertices.push(data[i][j][d]); }
}
if (i > 0) {
holeIndex += data[i - 1].length;
result.holes.push(holeIndex);
}
}
return result;
};
earcut_1.default = default_1;
'use strict';
var quickselect_1 = quickselect;
var default_1$1 = quickselect;
function quickselect(arr, k, left, right, compare) {
quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);
}
function quickselectStep(arr, k, left, right, compare) {
while (right > left) {
if (right - left > 600) {
var n = right - left + 1;
var m = k - left + 1;
var z = Math.log(n);
var s = 0.5 * Math.exp(2 * z / 3);
var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
quickselectStep(arr, k, newLeft, newRight, compare);
}
var t = arr[k];
var i = left;
var j = right;
swap(arr, left, k);
if (compare(arr[right], t) > 0) { swap(arr, left, right); }
while (i < j) {
swap(arr, i, j);
i++;
j--;
while (compare(arr[i], t) < 0) { i++; }
while (compare(arr[j], t) > 0) { j--; }
}
if (compare(arr[left], t) === 0) { swap(arr, left, j); }
else {
j++;
swap(arr, j, right);
}
if (j <= k) { left = j + 1; }
if (k <= j) { right = j - 1; }
}
}
function swap(arr, i, j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
function defaultCompare(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
}
quickselect_1.default = default_1$1;
//
// classifies an array of rings into polygons with outer rings and holes
function classifyRings(rings , maxRings ) {
var len = rings.length;
if (len <= 1) { return [rings]; }
var polygons = [];
var polygon,
ccw;
for (var i = 0; i < len; i++) {
var area = calculateSignedArea(rings[i]);
if (area === 0) { continue; }
(rings[i] ).area = Math.abs(area);
if (ccw === undefined) { ccw = area < 0; }
if (ccw === area < 0) {
if (polygon) { polygons.push(polygon); }
polygon = [rings[i]];
} else {
(polygon ).push(rings[i]);
}
}
if (polygon) { polygons.push(polygon); }
// Earcut performance degrages with the # of rings in a polygon. For this
// reason, we limit strip out all but the `maxRings` largest rings.
if (maxRings > 1) {
for (var j = 0; j < polygons.length; j++) {
if (polygons[j].length <= maxRings) { continue; }
quickselect_1(polygons[j], maxRings, 1, polygons[j].length - 1, compareAreas);
polygons[j] = polygons[j].slice(0, maxRings);
}
}
return polygons;
}
function compareAreas(a, b) {
return b.area - a.area;
}
//
var EARCUT_MAX_RINGS = 500;
var FillBucket = function FillBucket(options ) {
this.zoom = options.zoom;
this.overscaling = options.overscaling;
this.layers = options.layers;
this.layerIds = this.layers.map(function (layer) { return layer.id; });
this.index = options.index;
this.layoutVertexArray = new StructArrayLayout2i4();
this.indexArray = new StructArrayLayout3ui6();
this.indexArray2 = new StructArrayLayout2ui4();
this.programConfigurations = new ProgramConfigurationSet(members$1, options.layers, options.zoom);
this.segments = new SegmentVector();
this.segments2 = new SegmentVector();
};
FillBucket.prototype.populate = function populate (features , options ) {
var this$1 = this;
for (var i = 0, list = features; i < list.length; i += 1) {
var ref = list[i];
var feature = ref.feature;
var index = ref.index;
var sourceLayerIndex = ref.sourceLayerIndex;
if (this$1.layers[0]._featureFilter(new EvaluationParameters(this$1.zoom), feature)) {
var geometry = loadGeometry(feature);
this$1.addFeature(feature, geometry, index);
options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this$1.index);
}
}
};
FillBucket.prototype.update = function update (states , vtLayer ) {
if (!this.stateDependentLayers.length) { return; }
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers);
};
FillBucket.prototype.isEmpty = function isEmpty () {
return this.layoutVertexArray.length === 0;
};
FillBucket.prototype.uploadPending = function uploadPending () {
return !this.uploaded || this.programConfigurations.needsUpload;
};
FillBucket.prototype.upload = function upload (context ) {
if (!this.uploaded) {
this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, members$1);
this.indexBuffer = context.createIndexBuffer(this.indexArray);
this.indexBuffer2 = context.createIndexBuffer(this.indexArray2);
}
this.programConfigurations.upload(context);
this.uploaded = true;
};
FillBucket.prototype.destroy = function destroy () {
if (!this.layoutVertexBuffer) { return; }
this.layoutVertexBuffer.destroy();
this.indexBuffer.destroy();
this.indexBuffer2.destroy();
this.programConfigurations.destroy();
this.segments.destroy();
this.segments2.destroy();
};
FillBucket.prototype.addFeature = function addFeature (feature , geometry , index ) {
var this$1 = this;
for (var i$4 = 0, list$2 = classifyRings(geometry, EARCUT_MAX_RINGS); i$4 < list$2.length; i$4 += 1) {
var polygon = list$2[i$4];
var numVertices = 0;
for (var i$2 = 0, list = polygon; i$2 < list.length; i$2 += 1) {
var ring = list[i$2];
numVertices += ring.length;
}
var triangleSegment = this$1.segments.prepareSegment(numVertices, this$1.layoutVertexArray, this$1.indexArray);
var triangleIndex = triangleSegment.vertexLength;
var flattened = [];
var holeIndices = [];
for (var i$3 = 0, list$1 = polygon; i$3 < list$1.length; i$3 += 1) {
var ring$1 = list$1[i$3];
if (ring$1.length === 0) {
continue;
}
if (ring$1 !== polygon[0]) {
holeIndices.push(flattened.length / 2);
}
var lineSegment = this$1.segments2.prepareSegment(ring$1.length, this$1.layoutVertexArray, this$1.indexArray2);
var lineIndex = lineSegment.vertexLength;
this$1.layoutVertexArray.emplaceBack(ring$1[0].x, ring$1[0].y);
this$1.indexArray2.emplaceBack(lineIndex + ring$1.length - 1, lineIndex);
flattened.push(ring$1[0].x);
flattened.push(ring$1[0].y);
for (var i = 1; i < ring$1.length; i++) {
this$1.layoutVertexArray.emplaceBack(ring$1[i].x, ring$1[i].y);
this$1.indexArray2.emplaceBack(lineIndex + i - 1, lineIndex + i);
flattened.push(ring$1[i].x);
flattened.push(ring$1[i].y);
}
lineSegment.vertexLength += ring$1.length;
lineSegment.primitiveLength += ring$1.length;
}
var indices = earcut_1(flattened, holeIndices);
assert_1(indices.length % 3 === 0);
for (var i$1 = 0; i$1 < indices.length; i$1 += 3) {
this$1.indexArray.emplaceBack(
triangleIndex + indices[i$1],
triangleIndex + indices[i$1 + 1],
triangleIndex + indices[i$1 + 2]);
}
triangleSegment.vertexLength += numVertices;
triangleSegment.primitiveLength += indices.length / 3;
}
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index);
};
register('FillBucket', FillBucket, {omit: ['layers']});
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
var paint$4 = new Properties({
"fill-antialias": new DataConstantProperty(styleSpec["paint_fill"]["fill-antialias"]),
"fill-opacity": new DataDrivenProperty(styleSpec["paint_fill"]["fill-opacity"]),
"fill-color": new DataDrivenProperty(styleSpec["paint_fill"]["fill-color"]),
"fill-outline-color": new DataDrivenProperty(styleSpec["paint_fill"]["fill-outline-color"]),
"fill-translate": new DataConstantProperty(styleSpec["paint_fill"]["fill-translate"]),
"fill-translate-anchor": new DataConstantProperty(styleSpec["paint_fill"]["fill-translate-anchor"]),
"fill-pattern": new CrossFadedProperty(styleSpec["paint_fill"]["fill-pattern"]),
});
// Note: without adding the explicit type annotation, Flow infers weaker types
// for these objects from their use in the constructor to StyleLayer, as
// {layout?: Properties<...>, paint: Properties<...>}
var properties$3 = ({ paint: paint$4 }
);
//
var FillStyleLayer = (function (StyleLayer$$1) {
function FillStyleLayer(layer ) {
StyleLayer$$1.call(this, layer, properties$3);
}
if ( StyleLayer$$1 ) FillStyleLayer.__proto__ = StyleLayer$$1;
FillStyleLayer.prototype = Object.create( StyleLayer$$1 && StyleLayer$$1.prototype );
FillStyleLayer.prototype.constructor = FillStyleLayer;
FillStyleLayer.prototype.recalculate = function recalculate (parameters ) {
this.paint = this._transitioningPaint.possiblyEvaluate(parameters);
var outlineColor = this.paint._values['fill-outline-color'];
if (outlineColor.value.kind === 'constant' && outlineColor.value.value === undefined) {
this.paint._values['fill-outline-color'] = this.paint._values['fill-color'];
}
};
FillStyleLayer.prototype.createBucket = function createBucket (parameters ) {
return new FillBucket(parameters);
};
FillStyleLayer.prototype.queryRadius = function queryRadius () {
return translateDistance(this.paint.get('fill-translate'));
};
FillStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature (queryGeometry ,
feature ,
featureState ,
geometry ,
zoom ,
transform ,
pixelsToTileUnits ) {
var translatedPolygon = translate(queryGeometry,
this.paint.get('fill-translate'),
this.paint.get('fill-translate-anchor'),
transform.angle, pixelsToTileUnits);
return multiPolygonIntersectsMultiPolygon(translatedPolygon, geometry);
};
return FillStyleLayer;
}(StyleLayer));
//
var layout$3 = createLayout([
{name: 'a_pos', components: 2, type: 'Int16'},
{name: 'a_normal_ed', components: 4, type: 'Int16'} ], 4);
var members$2 = layout$3.members;
var size$2 = layout$3.size;
var alignment$2 = layout$3.alignment;
//
var EARCUT_MAX_RINGS$1 = 500;
var FACTOR = Math.pow(2, 13);
function addVertex(vertexArray, x, y, nx, ny, nz, t, e) {
vertexArray.emplaceBack(
// a_pos
x,
y,
// a_normal_ed: 3-component normal and 1-component edgedistance
Math.floor(nx * FACTOR) * 2 + t,
ny * FACTOR * 2,
nz * FACTOR * 2,
// edgedistance (used for wrapping patterns around extrusion sides)
Math.round(e)
);
}
var FillExtrusionBucket = function FillExtrusionBucket(options ) {
this.zoom = options.zoom;
this.overscaling = options.overscaling;
this.layers = options.layers;
this.layerIds = this.layers.map(function (layer) { return layer.id; });
this.index = options.index;
this.layoutVertexArray = new StructArrayLayout2i4i12();
this.indexArray = new StructArrayLayout3ui6();
this.programConfigurations = new ProgramConfigurationSet(members$2, options.layers, options.zoom);
this.segments = new SegmentVector();
};
FillExtrusionBucket.prototype.populate = function populate (features , options ) {
var this$1 = this;
for (var i = 0, list = features; i < list.length; i += 1) {
var ref = list[i];
var feature = ref.feature;
var index = ref.index;
var sourceLayerIndex = ref.sourceLayerIndex;
if (this$1.layers[0]._featureFilter(new EvaluationParameters(this$1.zoom), feature)) {
var geometry = loadGeometry(feature);
this$1.addFeature(feature, geometry, index);
options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this$1.index);
}
}
};
FillExtrusionBucket.prototype.update = function update (states , vtLayer ) {
if (!this.stateDependentLayers.length) { return; }
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers);
};
FillExtrusionBucket.prototype.isEmpty = function isEmpty () {
return this.layoutVertexArray.length === 0;
};
FillExtrusionBucket.prototype.uploadPending = function uploadPending () {
return !this.uploaded || this.programConfigurations.needsUpload;
};
FillExtrusionBucket.prototype.upload = function upload (context ) {
if (!this.uploaded) {
this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, members$2);
this.indexBuffer = context.createIndexBuffer(this.indexArray);
}
this.programConfigurations.upload(context);
this.uploaded = true;
};
FillExtrusionBucket.prototype.destroy = function destroy () {
if (!this.layoutVertexBuffer) { return; }
this.layoutVertexBuffer.destroy();
this.indexBuffer.destroy();
this.programConfigurations.destroy();
this.segments.destroy();
};
FillExtrusionBucket.prototype.addFeature = function addFeature (feature , geometry , index ) {
var this$1 = this;
for (var i$4 = 0, list$3 = classifyRings(geometry, EARCUT_MAX_RINGS$1); i$4 < list$3.length; i$4 += 1) {
var polygon = list$3[i$4];
var numVertices = 0;
for (var i$1 = 0, list = polygon; i$1 < list.length; i$1 += 1) {
var ring = list[i$1];
numVertices += ring.length;
}
var segment = this$1.segments.prepareSegment(4, this$1.layoutVertexArray, this$1.indexArray);
for (var i$2 = 0, list$1 = polygon; i$2 < list$1.length; i$2 += 1) {
var ring$1 = list$1[i$2];
if (ring$1.length === 0) {
continue;
}
if (isEntirelyOutside(ring$1)) {
continue;
}
var edgeDistance = 0;
for (var p = 0; p < ring$1.length; p++) {
var p1 = ring$1[p];
if (p >= 1) {
var p2 = ring$1[p - 1];
if (!isBoundaryEdge(p1, p2)) {
if (segment.vertexLength + 4 > SegmentVector.MAX_VERTEX_ARRAY_LENGTH) {
segment = this$1.segments.prepareSegment(4, this$1.layoutVertexArray, this$1.indexArray);
}
var perp = p1.sub(p2)._perp()._unit();
var dist = p2.dist(p1);
if (edgeDistance + dist > 32768) { edgeDistance = 0; }
addVertex(this$1.layoutVertexArray, p1.x, p1.y, perp.x, perp.y, 0, 0, edgeDistance);
addVertex(this$1.layoutVertexArray, p1.x, p1.y, perp.x, perp.y, 0, 1, edgeDistance);
edgeDistance += dist;
addVertex(this$1.layoutVertexArray, p2.x, p2.y, perp.x, perp.y, 0, 0, edgeDistance);
addVertex(this$1.layoutVertexArray, p2.x, p2.y, perp.x, perp.y, 0, 1, edgeDistance);
var bottomRight = segment.vertexLength;
this$1.indexArray.emplaceBack(bottomRight, bottomRight + 1, bottomRight + 2);
this$1.indexArray.emplaceBack(bottomRight + 1, bottomRight + 2, bottomRight + 3);
segment.vertexLength += 4;
segment.primitiveLength += 2;
}
}
}
}
if (segment.vertexLength + numVertices > SegmentVector.MAX_VERTEX_ARRAY_LENGTH) {
segment = this$1.segments.prepareSegment(numVertices, this$1.layoutVertexArray, this$1.indexArray);
}
var flattened = [];
var holeIndices = [];
var triangleIndex = segment.vertexLength;
for (var i$3 = 0, list$2 = polygon; i$3 < list$2.length; i$3 += 1) {
var ring$2 = list$2[i$3];
if (ring$2.length === 0) {
continue;
}
if (ring$2 !== polygon[0]) {
holeIndices.push(flattened.length / 2);
}
for (var i = 0; i < ring$2.length; i++) {
var p$1 = ring$2[i];
addVertex(this$1.layoutVertexArray, p$1.x, p$1.y, 0, 0, 1, 1, 0);
flattened.push(p$1.x);
flattened.push(p$1.y);
}
}
var indices = earcut_1(flattened, holeIndices);
assert_1(indices.length % 3 === 0);
for (var j = 0; j < indices.length; j += 3) {
this$1.indexArray.emplaceBack(
triangleIndex + indices[j],
triangleIndex + indices[j + 1],
triangleIndex + indices[j + 2]);
}
segment.primitiveLength += indices.length / 3;
segment.vertexLength += numVertices;
}
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index);
};
register('FillExtrusionBucket', FillExtrusionBucket, {omit: ['layers']});
function isBoundaryEdge(p1, p2) {
return (p1.x === p2.x && (p1.x < 0 || p1.x > EXTENT)) ||
(p1.y === p2.y && (p1.y < 0 || p1.y > EXTENT));
}
function isEntirelyOutside(ring) {
return ring.every(function (p) { return p.x < 0; }) ||
ring.every(function (p) { return p.x > EXTENT; }) ||
ring.every(function (p) { return p.y < 0; }) ||
ring.every(function (p) { return p.y > EXTENT; });
}
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
var paint$5 = new Properties({
"fill-extrusion-opacity": new DataConstantProperty(styleSpec["paint_fill-extrusion"]["fill-extrusion-opacity"]),
"fill-extrusion-color": new DataDrivenProperty(styleSpec["paint_fill-extrusion"]["fill-extrusion-color"]),
"fill-extrusion-translate": new DataConstantProperty(styleSpec["paint_fill-extrusion"]["fill-extrusion-translate"]),
"fill-extrusion-translate-anchor": new DataConstantProperty(styleSpec["paint_fill-extrusion"]["fill-extrusion-translate-anchor"]),
"fill-extrusion-pattern": new CrossFadedProperty(styleSpec["paint_fill-extrusion"]["fill-extrusion-pattern"]),
"fill-extrusion-height": new DataDrivenProperty(styleSpec["paint_fill-extrusion"]["fill-extrusion-height"]),
"fill-extrusion-base": new DataDrivenProperty(styleSpec["paint_fill-extrusion"]["fill-extrusion-base"]),
});
// Note: without adding the explicit type annotation, Flow infers weaker types
// for these objects from their use in the constructor to StyleLayer, as
// {layout?: Properties<...>, paint: Properties<...>}
var properties$4 = ({ paint: paint$5 }
);
//
var FillExtrusionStyleLayer = (function (StyleLayer$$1) {
function FillExtrusionStyleLayer(layer ) {
StyleLayer$$1.call(this, layer, properties$4);
}
if ( StyleLayer$$1 ) FillExtrusionStyleLayer.__proto__ = StyleLayer$$1;
FillExtrusionStyleLayer.prototype = Object.create( StyleLayer$$1 && StyleLayer$$1.prototype );
FillExtrusionStyleLayer.prototype.constructor = FillExtrusionStyleLayer;
FillExtrusionStyleLayer.prototype.createBucket = function createBucket (parameters ) {
return new FillExtrusionBucket(parameters);
};
FillExtrusionStyleLayer.prototype.queryRadius = function queryRadius () {
return translateDistance(this.paint.get('fill-extrusion-translate'));
};
FillExtrusionStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature (queryGeometry ,
feature ,
featureState ,
geometry ,
zoom ,
transform ,
pixelsToTileUnits ) {
var translatedPolygon = translate(queryGeometry,
this.paint.get('fill-extrusion-translate'),
this.paint.get('fill-extrusion-translate-anchor'),
transform.angle, pixelsToTileUnits);
return multiPolygonIntersectsMultiPolygon(translatedPolygon, geometry);
};
FillExtrusionStyleLayer.prototype.hasOffscreenPass = function hasOffscreenPass () {
return this.paint.get('fill-extrusion-opacity') !== 0 && this.visibility !== 'none';
};
FillExtrusionStyleLayer.prototype.resize = function resize () {
if (this.viewportFrame) {
this.viewportFrame.destroy();
this.viewportFrame = null;
}
};
return FillExtrusionStyleLayer;
}(StyleLayer));
//
var layout$4 = createLayout([
{name: 'a_pos_normal', components: 4, type: 'Int16'},
{name: 'a_data', components: 4, type: 'Uint8'}
], 4);
var members$3 = layout$4.members;
var size$3 = layout$4.size;
var alignment$3 = layout$4.alignment;
'use strict';
var vectortilefeature = VectorTileFeature;
function VectorTileFeature(pbf, end, extent, keys, values) {
// Public
this.properties = {};
this.extent = extent;
this.type = 0;
// Private
this._pbf = pbf;
this._geometry = -1;
this._keys = keys;
this._values = values;
pbf.readFields(readFeature, this, end);
}
function readFeature(tag, feature, pbf) {
if (tag == 1) { feature.id = pbf.readVarint(); }
else if (tag == 2) { readTag(pbf, feature); }
else if (tag == 3) { feature.type = pbf.readVarint(); }
else if (tag == 4) { feature._geometry = pbf.pos; }
}
function readTag(pbf, feature) {
var end = pbf.readVarint() + pbf.pos;
while (pbf.pos < end) {
var key = feature._keys[pbf.readVarint()],
value = feature._values[pbf.readVarint()];
feature.properties[key] = value;
}
}
VectorTileFeature.types = ['Unknown', 'Point', 'LineString', 'Polygon'];
VectorTileFeature.prototype.loadGeometry = function() {
var pbf = this._pbf;
pbf.pos = this._geometry;
var end = pbf.readVarint() + pbf.pos,
cmd = 1,
length = 0,
x = 0,
y = 0,
lines = [],
line;
while (pbf.pos < end) {
if (length <= 0) {
var cmdLen = pbf.readVarint();
cmd = cmdLen & 0x7;
length = cmdLen >> 3;
}
length--;
if (cmd === 1 || cmd === 2) {
x += pbf.readSVarint();
y += pbf.readSVarint();
if (cmd === 1) { // moveTo
if (line) { lines.push(line); }
line = [];
}
line.push(new pointGeometry(x, y));
} else if (cmd === 7) {
// Workaround for https://github.com/mapbox/mapnik-vector-tile/issues/90
if (line) {
line.push(line[0].clone()); // closePolygon
}
} else {
throw new Error('unknown command ' + cmd);
}
}
if (line) { lines.push(line); }
return lines;
};
VectorTileFeature.prototype.bbox = function() {
var pbf = this._pbf;
pbf.pos = this._geometry;
var end = pbf.readVarint() + pbf.pos,
cmd = 1,
length = 0,
x = 0,
y = 0,
x1 = Infinity,
x2 = -Infinity,
y1 = Infinity,
y2 = -Infinity;
while (pbf.pos < end) {
if (length <= 0) {
var cmdLen = pbf.readVarint();
cmd = cmdLen & 0x7;
length = cmdLen >> 3;
}
length--;
if (cmd === 1 || cmd === 2) {
x += pbf.readSVarint();
y += pbf.readSVarint();
if (x < x1) { x1 = x; }
if (x > x2) { x2 = x; }
if (y < y1) { y1 = y; }
if (y > y2) { y2 = y; }
} else if (cmd !== 7) {
throw new Error('unknown command ' + cmd);
}
}
return [x1, y1, x2, y2];
};
VectorTileFeature.prototype.toGeoJSON = function(x, y, z) {
var size = this.extent * Math.pow(2, z),
x0 = this.extent * x,
y0 = this.extent * y,
coords = this.loadGeometry(),
type = VectorTileFeature.types[this.type],
i, j;
function project(line) {
for (var j = 0; j < line.length; j++) {
var p = line[j], y2 = 180 - (p.y + y0) * 360 / size;
line[j] = [
(p.x + x0) * 360 / size - 180,
360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90
];
}
}
switch (this.type) {
case 1:
var points = [];
for (i = 0; i < coords.length; i++) {
points[i] = coords[i][0];
}
coords = points;
project(coords);
break;
case 2:
for (i = 0; i < coords.length; i++) {
project(coords[i]);
}
break;
case 3:
coords = classifyRings$1(coords);
for (i = 0; i < coords.length; i++) {
for (j = 0; j < coords[i].length; j++) {
project(coords[i][j]);
}
}
break;
}
if (coords.length === 1) {
coords = coords[0];
} else {
type = 'Multi' + type;
}
var result = {
type: "Feature",
geometry: {
type: type,
coordinates: coords
},
properties: this.properties
};
if ('id' in this) {
result.id = this.id;
}
return result;
};
// classifies an array of rings into polygons with outer rings and holes
function classifyRings$1(rings) {
var len = rings.length;
if (len <= 1) { return [rings]; }
var polygons = [],
polygon,
ccw;
for (var i = 0; i < len; i++) {
var area = signedArea$1(rings[i]);
if (area === 0) { continue; }
if (ccw === undefined) { ccw = area < 0; }
if (ccw === area < 0) {
if (polygon) { polygons.push(polygon); }
polygon = [rings[i]];
} else {
polygon.push(rings[i]);
}
}
if (polygon) { polygons.push(polygon); }
return polygons;
}
function signedArea$1(ring) {
var sum = 0;
for (var i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
p1 = ring[i];
p2 = ring[j];
sum += (p2.x - p1.x) * (p1.y + p2.y);
}
return sum;
}
'use strict';
var vectortilelayer = VectorTileLayer;
function VectorTileLayer(pbf, end) {
// Public
this.version = 1;
this.name = null;
this.extent = 4096;
this.length = 0;
// Private
this._pbf = pbf;
this._keys = [];
this._values = [];
this._features = [];
pbf.readFields(readLayer, this, end);
this.length = this._features.length;
}
function readLayer(tag, layer, pbf) {
if (tag === 15) { layer.version = pbf.readVarint(); }
else if (tag === 1) { layer.name = pbf.readString(); }
else if (tag === 5) { layer.extent = pbf.readVarint(); }
else if (tag === 2) { layer._features.push(pbf.pos); }
else if (tag === 3) { layer._keys.push(pbf.readString()); }
else if (tag === 4) { layer._values.push(readValueMessage(pbf)); }
}
function readValueMessage(pbf) {
var value = null,
end = pbf.readVarint() + pbf.pos;
while (pbf.pos < end) {
var tag = pbf.readVarint() >> 3;
value = tag === 1 ? pbf.readString() :
tag === 2 ? pbf.readFloat() :
tag === 3 ? pbf.readDouble() :
tag === 4 ? pbf.readVarint64() :
tag === 5 ? pbf.readVarint() :
tag === 6 ? pbf.readSVarint() :
tag === 7 ? pbf.readBoolean() : null;
}
return value;
}
// return feature `i` from this layer as a `VectorTileFeature`
VectorTileLayer.prototype.feature = function(i) {
if (i < 0 || i >= this._features.length) { throw new Error('feature index out of bounds'); }
this._pbf.pos = this._features[i];
var end = this._pbf.readVarint() + this._pbf.pos;
return new vectortilefeature(this._pbf, end, this.extent, this._keys, this._values);
};
'use strict';
var vectortile = VectorTile;
function VectorTile(pbf, end) {
this.layers = pbf.readFields(readTile, {}, end);
}
function readTile(tag, layers, pbf) {
if (tag === 3) {
var layer = new vectortilelayer(pbf, pbf.readVarint() + pbf.pos);
if (layer.length) { layers[layer.name] = layer; }
}
}
var VectorTile$1 = vectortile;
var VectorTileFeature$1 = vectortilefeature;
var VectorTileLayer$1 = vectortilelayer;
var vectorTile = {
VectorTile: VectorTile$1,
VectorTileFeature: VectorTileFeature$1,
VectorTileLayer: VectorTileLayer$1
};
//
var vectorTileFeatureTypes = vectorTile.VectorTileFeature.types;
// NOTE ON EXTRUDE SCALE:
// scale the extrusion vector so that the normal length is this value.
// contains the "texture" normals (-1..1). this is distinct from the extrude
// normals for line joins, because the x-value remains 0 for the texture
// normal array, while the extrude normal actually moves the vertex to create
// the acute/bevelled line join.
var EXTRUDE_SCALE = 63;
/*
* Sharp corners cause dashed lines to tilt because the distance along the line
* is the same at both the inner and outer corners. To improve the appearance of
* dashed lines we add extra points near sharp corners so that a smaller part
* of the line is tilted.
*
* COS_HALF_SHARP_CORNER controls how sharp a corner has to be for us to add an
* extra vertex. The default is 75 degrees.
*
* The newly created vertices are placed SHARP_CORNER_OFFSET pixels from the corner.
*/
var COS_HALF_SHARP_CORNER = Math.cos(75 / 2 * (Math.PI / 180));
var SHARP_CORNER_OFFSET = 15;
// The number of bits that is used to store the line distance in the buffer.
var LINE_DISTANCE_BUFFER_BITS = 15;
// We don't have enough bits for the line distance as we'd like to have, so
// use this value to scale the line distance (in tile units) down to a smaller
// value. This lets us store longer distances while sacrificing precision.
var LINE_DISTANCE_SCALE = 1 / 2;
// The maximum line distance, in tile units, that fits in the buffer.
var MAX_LINE_DISTANCE = Math.pow(2, LINE_DISTANCE_BUFFER_BITS - 1) / LINE_DISTANCE_SCALE;
function addLineVertex(layoutVertexBuffer, point , extrude , round , up , dir , linesofar ) {
layoutVertexBuffer.emplaceBack(
// a_pos_normal
point.x,
point.y,
round ? 1 : 0,
up ? 1 : -1,
// a_data
// add 128 to store a byte in an unsigned byte
Math.round(EXTRUDE_SCALE * extrude.x) + 128,
Math.round(EXTRUDE_SCALE * extrude.y) + 128,
// Encode the -1/0/1 direction value into the first two bits of .z of a_data.
// Combine it with the lower 6 bits of `linesofar` (shifted by 2 bites to make
// room for the direction value). The upper 8 bits of `linesofar` are placed in
// the `w` component. `linesofar` is scaled down by `LINE_DISTANCE_SCALE` so that
// we can store longer distances while sacrificing precision.
((dir === 0 ? 0 : (dir < 0 ? -1 : 1)) + 1) | (((linesofar * LINE_DISTANCE_SCALE) & 0x3F) << 2),
(linesofar * LINE_DISTANCE_SCALE) >> 6);
}
/**
* @private
*/
var LineBucket = function LineBucket(options ) {
this.zoom = options.zoom;
this.overscaling = options.overscaling;
this.layers = options.layers;
this.layerIds = this.layers.map(function (layer) { return layer.id; });
this.index = options.index;
this.layoutVertexArray = new StructArrayLayout4i4ub12();
this.indexArray = new StructArrayLayout3ui6();
this.programConfigurations = new ProgramConfigurationSet(members$3, options.layers, options.zoom);
this.segments = new SegmentVector();
};
LineBucket.prototype.populate = function populate (features , options ) {
var this$1 = this;
for (var i = 0, list = features; i < list.length; i += 1) {
var ref = list[i];
var feature = ref.feature;
var index = ref.index;
var sourceLayerIndex = ref.sourceLayerIndex;
if (this$1.layers[0]._featureFilter(new EvaluationParameters(this$1.zoom), feature)) {
var geometry = loadGeometry(feature);
this$1.addFeature(feature, geometry, index);
options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this$1.index);
}
}
};
LineBucket.prototype.update = function update (states , vtLayer ) {
if (!this.stateDependentLayers.length) { return; }
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers);
};
LineBucket.prototype.isEmpty = function isEmpty () {
return this.layoutVertexArray.length === 0;
};
LineBucket.prototype.uploadPending = function uploadPending () {
return !this.uploaded || this.programConfigurations.needsUpload;
};
LineBucket.prototype.upload = function upload (context ) {
if (!this.uploaded) {
this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, members$3);
this.indexBuffer = context.createIndexBuffer(this.indexArray);
}
this.programConfigurations.upload(context);
this.uploaded = true;
};
LineBucket.prototype.destroy = function destroy () {
if (!this.layoutVertexBuffer) { return; }
this.layoutVertexBuffer.destroy();
this.indexBuffer.destroy();
this.programConfigurations.destroy();
this.segments.destroy();
};
LineBucket.prototype.addFeature = function addFeature (feature , geometry , index ) {
var this$1 = this;
var layout = this.layers[0].layout;
var join = layout.get('line-join').evaluate(feature, {});
var cap = layout.get('line-cap');
var miterLimit = layout.get('line-miter-limit');
var roundLimit = layout.get('line-round-limit');
for (var i = 0, list = geometry; i < list.length; i += 1) {
var line = list[i];
this$1.addLine(line, feature, join, cap, miterLimit, roundLimit, index);
}
};
LineBucket.prototype.addLine = function addLine (vertices , feature , join , cap , miterLimit , roundLimit , index ) {
var this$1 = this;
var lineDistances = null;
if (!!feature.properties &&
feature.properties.hasOwnProperty('mapbox_clip_start') &&
feature.properties.hasOwnProperty('mapbox_clip_end')) {
lineDistances = {
start: feature.properties.mapbox_clip_start,
end: feature.properties.mapbox_clip_end,
tileTotal: undefined
};
}
var isPolygon = vectorTileFeatureTypes[feature.type] === 'Polygon';
// If the line has duplicate vertices at the ends, adjust start/length to remove them.
var len = vertices.length;
while (len >= 2 && vertices[len - 1].equals(vertices[len - 2])) {
len--;
}
var first = 0;
while (first < len - 1 && vertices[first].equals(vertices[first + 1])) {
first++;
}
// Ignore invalid geometry.
if (len < (isPolygon ? 3 : 2)) { return; }
if (lineDistances) {
lineDistances.tileTotal = calculateFullDistance(vertices, first, len);
}
if (join === 'bevel') { miterLimit = 1.05; }
var sharpCornerOffset = SHARP_CORNER_OFFSET * (EXTENT / (512 * this.overscaling));
var firstVertex = vertices[first];
// we could be more precise, but it would only save a negligible amount of space
var segment = this.segments.prepareSegment(len * 10, this.layoutVertexArray, this.indexArray);
this.distance = 0;
var beginCap = cap,
endCap = isPolygon ? 'butt' : cap;
var startOfLine = true;
var currentVertex;
var prevVertex = ((undefined ) );
var nextVertex = ((undefined ) );
var prevNormal = ((undefined ) );
var nextNormal = ((undefined ) );
var offsetA;
var offsetB;
// the last three vertices added
this.e1 = this.e2 = this.e3 = -1;
if (isPolygon) {
currentVertex = vertices[len - 2];
nextNormal = firstVertex.sub(currentVertex)._unit()._perp();
}
for (var i = first; i < len; i++) {
nextVertex = isPolygon && i === len - 1 ?
vertices[first + 1] : // if the line is closed, we treat the last vertex like the first
vertices[i + 1]; // just the next vertex
// if two consecutive vertices exist, skip the current one
if (nextVertex && vertices[i].equals(nextVertex)) { continue; }
if (nextNormal) { prevNormal = nextNormal; }
if (currentVertex) { prevVertex = currentVertex; }
currentVertex = vertices[i];
// Calculate the normal towards the next vertex in this line. In case
// there is no next vertex, pretend that the line is continuing straight,
// meaning that we are just using the previous normal.
nextNormal = nextVertex ? nextVertex.sub(currentVertex)._unit()._perp() : prevNormal;
// If we still don't have a previous normal, this is the beginning of a
// non-closed line, so we're doing a straight "join".
prevNormal = prevNormal || nextNormal;
// Determine the normal of the join extrusion. It is the angle bisector
// of the segments between the previous line and the next line.
// In the case of 180° angles, the prev and next normals cancel each other out:
// prevNormal + nextNormal = (0, 0), its magnitude is 0, so the unit vector would be
// undefined. In that case, we're keeping the joinNormal at (0, 0), so that the cosHalfAngle
// below will also become 0 and miterLength will become Infinity.
var joinNormal = prevNormal.add(nextNormal);
if (joinNormal.x !== 0 || joinNormal.y !== 0) {
joinNormal._unit();
}
/* joinNormal prevNormal
* ↖ ↑
* .________. prevVertex
* |
* nextNormal ← | currentVertex
* |
* nextVertex !
*
*/
// Calculate the length of the miter (the ratio of the miter to the width).
// Find the cosine of the angle between the next and join normals
// using dot product. The inverse of that is the miter length.
var cosHalfAngle = joinNormal.x * nextNormal.x + joinNormal.y * nextNormal.y;
var miterLength = cosHalfAngle !== 0 ? 1 / cosHalfAngle : Infinity;
var isSharpCorner = cosHalfAngle < COS_HALF_SHARP_CORNER && prevVertex && nextVertex;
if (isSharpCorner && i > first) {
var prevSegmentLength = currentVertex.dist(prevVertex);
if (prevSegmentLength > 2 * sharpCornerOffset) {
var newPrevVertex = currentVertex.sub(currentVertex.sub(prevVertex)._mult(sharpCornerOffset / prevSegmentLength)._round());
this$1.distance += newPrevVertex.dist(prevVertex);
this$1.addCurrentVertex(newPrevVertex, this$1.distance, prevNormal.mult(1), 0, 0, false, segment, lineDistances);
prevVertex = newPrevVertex;
}
}
// The join if a middle vertex, otherwise the cap.
var middleVertex = prevVertex && nextVertex;
var currentJoin = middleVertex ? join : nextVertex ? beginCap : endCap;
if (middleVertex && currentJoin === 'round') {
if (miterLength < roundLimit) {
currentJoin = 'miter';
} else if (miterLength <= 2) {
currentJoin = 'fakeround';
}
}
if (currentJoin === 'miter' && miterLength > miterLimit) {
currentJoin = 'bevel';
}
if (currentJoin === 'bevel') {
// The maximum extrude length is 128 / 63 = 2 times the width of the line
// so if miterLength >= 2 we need to draw a different type of bevel here.
if (miterLength > 2) { currentJoin = 'flipbevel'; }
// If the miterLength is really small and the line bevel wouldn't be visible,
// just draw a miter join to save a triangle.
if (miterLength < miterLimit) { currentJoin = 'miter'; }
}
// Calculate how far along the line the currentVertex is
if (prevVertex) { this$1.distance += currentVertex.dist(prevVertex); }
if (currentJoin === 'miter') {
joinNormal._mult(miterLength);
this$1.addCurrentVertex(currentVertex, this$1.distance, joinNormal, 0, 0, false, segment, lineDistances);
} else if (currentJoin === 'flipbevel') {
// miter is too big, flip the direction to make a beveled join
if (miterLength > 100) {
// Almost parallel lines
joinNormal = nextNormal.clone().mult(-1);
} else {
var direction = prevNormal.x * nextNormal.y - prevNormal.y * nextNormal.x > 0 ? -1 : 1;
var bevelLength = miterLength * prevNormal.add(nextNormal).mag() / prevNormal.sub(nextNormal).mag();
joinNormal._perp()._mult(bevelLength * direction);
}
this$1.addCurrentVertex(currentVertex, this$1.distance, joinNormal, 0, 0, false, segment, lineDistances);
this$1.addCurrentVertex(currentVertex, this$1.distance, joinNormal.mult(-1), 0, 0, false, segment, lineDistances);
} else if (currentJoin === 'bevel' || currentJoin === 'fakeround') {
var lineTurnsLeft = (prevNormal.x * nextNormal.y - prevNormal.y * nextNormal.x) > 0;
var offset = -Math.sqrt(miterLength * miterLength - 1);
if (lineTurnsLeft) {
offsetB = 0;
offsetA = offset;
} else {
offsetA = 0;
offsetB = offset;
}
// Close previous segment with a bevel
if (!startOfLine) {
this$1.addCurrentVertex(currentVertex, this$1.distance, prevNormal, offsetA, offsetB, false, segment, lineDistances);
}
if (currentJoin === 'fakeround') {
// The join angle is sharp enough that a round join would be visible.
// Bevel joins fill the gap between segments with a single pie slice triangle.
// Create a round join by adding multiple pie slices. The join isn't actually round, but
// it looks like it is at the sizes we render lines at.
// Add more triangles for sharper angles.
// This math is just a good enough approximation. It isn't "correct".
var n = Math.floor((0.5 - (cosHalfAngle - 0.5)) * 8);
var approxFractionalJoinNormal = (void 0);
for (var m = 0; m < n; m++) {
approxFractionalJoinNormal = nextNormal.mult((m + 1) / (n + 1))._add(prevNormal)._unit();
this$1.addPieSliceVertex(currentVertex, this$1.distance, approxFractionalJoinNormal, lineTurnsLeft, segment, lineDistances);
}
this$1.addPieSliceVertex(currentVertex, this$1.distance, joinNormal, lineTurnsLeft, segment, lineDistances);
for (var k = n - 1; k >= 0; k--) {
approxFractionalJoinNormal = prevNormal.mult((k + 1) / (n + 1))._add(nextNormal)._unit();
this$1.addPieSliceVertex(currentVertex, this$1.distance, approxFractionalJoinNormal, lineTurnsLeft, segment, lineDistances);
}
}
// Start next segment
if (nextVertex) {
this$1.addCurrentVertex(currentVertex, this$1.distance, nextNormal, -offsetA, -offsetB, false, segment, lineDistances);
}
} else if (currentJoin === 'butt') {
if (!startOfLine) {
// Close previous segment with a butt
this$1.addCurrentVertex(currentVertex, this$1.distance, prevNormal, 0, 0, false, segment, lineDistances);
}
// Start next segment with a butt
if (nextVertex) {
this$1.addCurrentVertex(currentVertex, this$1.distance, nextNormal, 0, 0, false, segment, lineDistances);
}
} else if (currentJoin === 'square') {
if (!startOfLine) {
// Close previous segment with a square cap
this$1.addCurrentVertex(currentVertex, this$1.distance, prevNormal, 1, 1, false, segment, lineDistances);
// The segment is done. Unset vertices to disconnect segments.
this$1.e1 = this$1.e2 = -1;
}
// Start next segment
if (nextVertex) {
this$1.addCurrentVertex(currentVertex, this$1.distance, nextNormal, -1, -1, false, segment, lineDistances);
}
} else if (currentJoin === 'round') {
if (!startOfLine) {
// Close previous segment with butt
this$1.addCurrentVertex(currentVertex, this$1.distance, prevNormal, 0, 0, false, segment, lineDistances);
// Add round cap or linejoin at end of segment
this$1.addCurrentVertex(currentVertex, this$1.distance, prevNormal, 1, 1, true, segment, lineDistances);
// The segment is done. Unset vertices to disconnect segments.
this$1.e1 = this$1.e2 = -1;
}
// Start next segment with a butt
if (nextVertex) {
// Add round cap before first segment
this$1.addCurrentVertex(currentVertex, this$1.distance, nextNormal, -1, -1, true, segment, lineDistances);
this$1.addCurrentVertex(currentVertex, this$1.distance, nextNormal, 0, 0, false, segment, lineDistances);
}
}
if (isSharpCorner && i < len - 1) {
var nextSegmentLength = currentVertex.dist(nextVertex);
if (nextSegmentLength > 2 * sharpCornerOffset) {
var newCurrentVertex = currentVertex.add(nextVertex.sub(currentVertex)._mult(sharpCornerOffset / nextSegmentLength)._round());
this$1.distance += newCurrentVertex.dist(currentVertex);
this$1.addCurrentVertex(newCurrentVertex, this$1.distance, nextNormal.mult(1), 0, 0, false, segment, lineDistances);
currentVertex = newCurrentVertex;
}
}
startOfLine = false;
}
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index);
};
/**
* Add two vertices to the buffers.
*
* @param {Object} currentVertex the line vertex to add buffer vertices for
* @param {number} distance the distance from the beginning of the line to the vertex
* @param {number} endLeft extrude to shift the left vertex along the line
* @param {number} endRight extrude to shift the left vertex along the line
* @param {boolean} round whether this is a round cap
* @private
*/
LineBucket.prototype.addCurrentVertex = function addCurrentVertex (currentVertex ,
distance ,
normal ,
endLeft ,
endRight ,
round ,
segment ,
distancesForScaling ) {
var extrude;
var layoutVertexArray = this.layoutVertexArray;
var indexArray = this.indexArray;
if (distancesForScaling) {
// For gradient lines, scale distance from tile units to [0, 2^15)
distance = scaleDistance(distance, distancesForScaling);
}
extrude = normal.clone();
if (endLeft) { extrude._sub(normal.perp()._mult(endLeft)); }
addLineVertex(layoutVertexArray, currentVertex, extrude, round, false, endLeft, distance);
this.e3 = segment.vertexLength++;
if (this.e1 >= 0 && this.e2 >= 0) {
indexArray.emplaceBack(this.e1, this.e2, this.e3);
segment.primitiveLength++;
}
this.e1 = this.e2;
this.e2 = this.e3;
extrude = normal.mult(-1);
if (endRight) { extrude._sub(normal.perp()._mult(endRight)); }
addLineVertex(layoutVertexArray, currentVertex, extrude, round, true, -endRight, distance);
this.e3 = segment.vertexLength++;
if (this.e1 >= 0 && this.e2 >= 0) {
indexArray.emplaceBack(this.e1, this.e2, this.e3);
segment.primitiveLength++;
}
this.e1 = this.e2;
this.e2 = this.e3;
// There is a maximum "distance along the line" that we can store in the buffers.
// When we get close to the distance, reset it to zero and add the vertex again with
// a distance of zero. The max distance is determined by the number of bits we allocate
// to `linesofar`.
if (distance > MAX_LINE_DISTANCE / 2 && !distancesForScaling) {
this.distance = 0;
this.addCurrentVertex(currentVertex, this.distance, normal, endLeft, endRight, round, segment);
}
};
/**
* Add a single new vertex and a triangle using two previous vertices.
* This adds a pie slice triangle near a join to simulate round joins
*
* @param currentVertex the line vertex to add buffer vertices for
* @param distance the distance from the beginning of the line to the vertex
* @param extrude the offset of the new vertex from the currentVertex
* @param lineTurnsLeft whether the line is turning left or right at this angle
* @private
*/
LineBucket.prototype.addPieSliceVertex = function addPieSliceVertex (currentVertex ,
distance ,
extrude ,
lineTurnsLeft ,
segment ,
distancesForScaling ) {
extrude = extrude.mult(lineTurnsLeft ? -1 : 1);
var layoutVertexArray = this.layoutVertexArray;
var indexArray = this.indexArray;
if (distancesForScaling) { distance = scaleDistance(distance, distancesForScaling); }
addLineVertex(layoutVertexArray, currentVertex, extrude, false, lineTurnsLeft, 0, distance);
this.e3 = segment.vertexLength++;
if (this.e1 >= 0 && this.e2 >= 0) {
indexArray.emplaceBack(this.e1, this.e2, this.e3);
segment.primitiveLength++;
}
if (lineTurnsLeft) {
this.e2 = this.e3;
} else {
this.e1 = this.e3;
}
};
/**
* Knowing the ratio of the full linestring covered by this tiled feature, as well
* as the total distance (in tile units) of this tiled feature, and the distance
* (in tile units) of the current vertex, we can determine the relative distance
* of this vertex along the full linestring feature and scale it to [0, 2^15)
*
* @param {number} tileDistance the distance from the beginning of the tiled line to this vertex
* @param {Object} stats
* @param {number} stats.start the ratio (0-1) along a full original linestring feature of the start of this tiled line feature
* @param {number} stats.end the ratio (0-1) along a full original linestring feature of the end of this tiled line feature
* @param {number} stats.tileTotal the total distance, in tile units, of this tiled line feature
*
* @private
*/
function scaleDistance(tileDistance , stats ) {
return ((tileDistance / stats.tileTotal) * (stats.end - stats.start) + stats.start) * (MAX_LINE_DISTANCE - 1);
}
/**
* Calculate the total distance, in tile units, of this tiled line feature
*
* @param {Array<Point>} vertices the full geometry of this tiled line feature
* @param {number} first the index in the vertices array representing the first vertex we should consider
* @param {number} len the count of vertices we should consider from `first`
*
* @private
*/
function calculateFullDistance(vertices , first , len ) {
var currentVertex, nextVertex;
var total = 0;
for (var i = first; i < len - 1; i++) {
currentVertex = vertices[i];
nextVertex = vertices[i + 1];
total += currentVertex.dist(nextVertex);
}
return total;
}
register('LineBucket', LineBucket, {omit: ['layers']});
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
var layout$5 = new Properties({
"line-cap": new DataConstantProperty(styleSpec["layout_line"]["line-cap"]),
"line-join": new DataDrivenProperty(styleSpec["layout_line"]["line-join"]),
"line-miter-limit": new DataConstantProperty(styleSpec["layout_line"]["line-miter-limit"]),
"line-round-limit": new DataConstantProperty(styleSpec["layout_line"]["line-round-limit"]),
});
var paint$6 = new Properties({
"line-opacity": new DataDrivenProperty(styleSpec["paint_line"]["line-opacity"]),
"line-color": new DataDrivenProperty(styleSpec["paint_line"]["line-color"]),
"line-translate": new DataConstantProperty(styleSpec["paint_line"]["line-translate"]),
"line-translate-anchor": new DataConstantProperty(styleSpec["paint_line"]["line-translate-anchor"]),
"line-width": new DataDrivenProperty(styleSpec["paint_line"]["line-width"]),
"line-gap-width": new DataDrivenProperty(styleSpec["paint_line"]["line-gap-width"]),
"line-offset": new DataDrivenProperty(styleSpec["paint_line"]["line-offset"]),
"line-blur": new DataDrivenProperty(styleSpec["paint_line"]["line-blur"]),
"line-dasharray": new CrossFadedProperty(styleSpec["paint_line"]["line-dasharray"]),
"line-pattern": new CrossFadedProperty(styleSpec["paint_line"]["line-pattern"]),
"line-gradient": new ColorRampProperty(styleSpec["paint_line"]["line-gradient"]),
});
// Note: without adding the explicit type annotation, Flow infers weaker types
// for these objects from their use in the constructor to StyleLayer, as
// {layout?: Properties<...>, paint: Properties<...>}
var properties$5 = ({ paint: paint$6, layout: layout$5 }
);
//
var LineFloorwidthProperty = (function (DataDrivenProperty$$1) {
function LineFloorwidthProperty () {
DataDrivenProperty$$1.apply(this, arguments);
}
if ( DataDrivenProperty$$1 ) LineFloorwidthProperty.__proto__ = DataDrivenProperty$$1;
LineFloorwidthProperty.prototype = Object.create( DataDrivenProperty$$1 && DataDrivenProperty$$1.prototype );
LineFloorwidthProperty.prototype.constructor = LineFloorwidthProperty;
LineFloorwidthProperty.prototype.possiblyEvaluate = function possiblyEvaluate (value, parameters) {
parameters = new EvaluationParameters(Math.floor(parameters.zoom), {
now: parameters.now,
fadeDuration: parameters.fadeDuration,
zoomHistory: parameters.zoomHistory,
transition: parameters.transition
});
return DataDrivenProperty$$1.prototype.possiblyEvaluate.call(this, value, parameters);
};
LineFloorwidthProperty.prototype.evaluate = function evaluate (value, globals, feature, featureState) {
globals = extend({}, globals, {zoom: Math.floor(globals.zoom)});
return DataDrivenProperty$$1.prototype.evaluate.call(this, value, globals, feature, featureState);
};
return LineFloorwidthProperty;
}(DataDrivenProperty));
var lineFloorwidthProperty = new LineFloorwidthProperty(properties$5.paint.properties['line-width'].specification);
lineFloorwidthProperty.useIntegerZoom = true;
var LineStyleLayer = (function (StyleLayer$$1) {
function LineStyleLayer(layer ) {
StyleLayer$$1.call(this, layer, properties$5);
}
if ( StyleLayer$$1 ) LineStyleLayer.__proto__ = StyleLayer$$1;
LineStyleLayer.prototype = Object.create( StyleLayer$$1 && StyleLayer$$1.prototype );
LineStyleLayer.prototype.constructor = LineStyleLayer;
LineStyleLayer.prototype._handleSpecialPaintPropertyUpdate = function _handleSpecialPaintPropertyUpdate (name ) {
if (name === 'line-gradient') {
this._updateGradient();
}
};
LineStyleLayer.prototype._updateGradient = function _updateGradient () {
var expression = this._transitionablePaint._values['line-gradient'].value.expression;
this.gradient = renderColorRamp(expression, 'lineProgress');
this.gradientTexture = null;
};
LineStyleLayer.prototype.recalculate = function recalculate (parameters ) {
StyleLayer$$1.prototype.recalculate.call(this, parameters);
(this.paint._values )['line-floorwidth'] =
lineFloorwidthProperty.possiblyEvaluate(this._transitioningPaint._values['line-width'].value, parameters);
};
LineStyleLayer.prototype.createBucket = function createBucket (parameters ) {
return new LineBucket(parameters);
};
LineStyleLayer.prototype.queryRadius = function queryRadius (bucket ) {
var lineBucket = (bucket );
var width = getLineWidth(
getMaximumPaintValue('line-width', this, lineBucket),
getMaximumPaintValue('line-gap-width', this, lineBucket));
var offset = getMaximumPaintValue('line-offset', this, lineBucket);
return width / 2 + Math.abs(offset) + translateDistance(this.paint.get('line-translate'));
};
LineStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature (queryGeometry ,
feature ,
featureState ,
geometry ,
zoom ,
transform ,
pixelsToTileUnits ) {
var translatedPolygon = translate(queryGeometry,
this.paint.get('line-translate'),
this.paint.get('line-translate-anchor'),
transform.angle, pixelsToTileUnits);
var halfWidth = pixelsToTileUnits / 2 * getLineWidth(
this.paint.get('line-width').evaluate(feature, featureState),
this.paint.get('line-gap-width').evaluate(feature, featureState));
var lineOffset = this.paint.get('line-offset').evaluate(feature, featureState);
if (lineOffset) {
geometry = offsetLine(geometry, lineOffset * pixelsToTileUnits);
}
return multiPolygonIntersectsBufferedMultiLine(translatedPolygon, geometry, halfWidth);
};
return LineStyleLayer;
}(StyleLayer));
function getLineWidth(lineWidth, lineGapWidth) {
if (lineGapWidth > 0) {
return lineGapWidth + 2 * lineWidth;
} else {
return lineWidth;
}
}
function offsetLine(rings, offset) {
var newRings = [];
var zero = new pointGeometry(0, 0);
for (var k = 0; k < rings.length; k++) {
var ring = rings[k];
var newRing = [];
for (var i = 0; i < ring.length; i++) {
var a = ring[i - 1];
var b = ring[i];
var c = ring[i + 1];
var aToB = i === 0 ? zero : b.sub(a)._unit()._perp();
var bToC = i === ring.length - 1 ? zero : c.sub(b)._unit()._perp();
var extrude = aToB._add(bToC)._unit();
var cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y;
extrude._mult(1 / cosHalfAngle);
newRing.push(extrude._mult(offset)._add(b));
}
newRings.push(newRing);
}
return newRings;
}
//
var symbolLayoutAttributes = createLayout([
{name: 'a_pos_offset', components: 4, type: 'Int16'},
{name: 'a_data', components: 4, type: 'Uint16'}
]);
var dynamicLayoutAttributes = createLayout([
{ name: 'a_projected_pos', components: 3, type: 'Float32' }
], 4);
var placementOpacityAttributes = createLayout([
{ name: 'a_fade_opacity', components: 1, type: 'Uint32' }
], 4);
var collisionVertexAttributes = createLayout([
{ name: 'a_placed', components: 2, type: 'Uint8' }
], 4);
var collisionBox = createLayout([
// the box is centered around the anchor point
{ type: 'Int16', name: 'anchorPointX' },
{ type: 'Int16', name: 'anchorPointY' },
// distances to the edges from the anchor
{ type: 'Int16', name: 'x1' },
{ type: 'Int16', name: 'y1' },
{ type: 'Int16', name: 'x2' },
{ type: 'Int16', name: 'y2' },
// the index of the feature in the original vectortile
{ type: 'Uint32', name: 'featureIndex' },
// the source layer the feature appears in
{ type: 'Uint16', name: 'sourceLayerIndex' },
// the bucket the feature appears in
{ type: 'Uint16', name: 'bucketIndex' },
// collision circles for lines store their distance to the anchor in tile units
// so that they can be ignored if the projected label doesn't extend into
// the box area
{ type: 'Int16', name: 'radius' },
{ type: 'Int16', name: 'signedDistanceFromAnchor' }
]);
var collisionBoxLayout = createLayout([ // used to render collision boxes for debugging purposes
{name: 'a_pos', components: 2, type: 'Int16'},
{name: 'a_anchor_pos', components: 2, type: 'Int16'},
{name: 'a_extrude', components: 2, type: 'Int16'}
], 4);
var collisionCircleLayout = createLayout([ // used to render collision circles for debugging purposes
{name: 'a_pos', components: 2, type: 'Int16'},
{name: 'a_anchor_pos', components: 2, type: 'Int16'},
{name: 'a_extrude', components: 2, type: 'Int16'}
], 4);
var placement = createLayout([
{ type: 'Int16', name: 'anchorX' },
{ type: 'Int16', name: 'anchorY' },
{ type: 'Uint16', name: 'glyphStartIndex' },
{ type: 'Uint16', name: 'numGlyphs' },
{ type: 'Uint32', name: 'vertexStartIndex' },
{ type: 'Uint32', name: 'lineStartIndex' },
{ type: 'Uint32', name: 'lineLength' },
{ type: 'Uint16', name: 'segment' },
{ type: 'Uint16', name: 'lowerSize' },
{ type: 'Uint16', name: 'upperSize' },
{ type: 'Float32', name: 'lineOffsetX' },
{ type: 'Float32', name: 'lineOffsetY' },
{ type: 'Uint8', name: 'writingMode' },
{ type: 'Uint8', name: 'hidden' }
]);
var glyphOffset = createLayout([
{ type: 'Float32', name: 'offsetX' }
]);
var lineVertex = createLayout([
{ type: 'Int16', name: 'x' },
{ type: 'Int16', name: 'y' },
{ type: 'Int16', name: 'tileUnitDistanceFromAnchor' }
]);
//
function transformText(text , layer , feature ) {
var transform = layer.layout.get('text-transform').evaluate(feature, {});
if (transform === 'uppercase') {
text = text.toLocaleUpperCase();
} else if (transform === 'lowercase') {
text = text.toLocaleLowerCase();
}
if (plugin.applyArabicShaping) {
text = plugin.applyArabicShaping(text);
}
return text;
}
function transformText$1(text , layer , feature ) {
if (text instanceof Formatted) {
text.sections.forEach(function (section) {
section.text = transformText(section.text, layer, feature);
});
return text;
} else {
return transformText(text, layer, feature);
}
}
//
function mergeLines (features ) {
var leftIndex = {};
var rightIndex = {};
var mergedFeatures = [];
var mergedIndex = 0;
function add(k) {
mergedFeatures.push(features[k]);
mergedIndex++;
}
function mergeFromRight(leftKey , rightKey , geom) {
var i = rightIndex[leftKey];
delete rightIndex[leftKey];
rightIndex[rightKey] = i;
mergedFeatures[i].geometry[0].pop();
mergedFeatures[i].geometry[0] = mergedFeatures[i].geometry[0].concat(geom[0]);
return i;
}
function mergeFromLeft(leftKey , rightKey , geom) {
var i = leftIndex[rightKey];
delete leftIndex[rightKey];
leftIndex[leftKey] = i;
mergedFeatures[i].geometry[0].shift();
mergedFeatures[i].geometry[0] = geom[0].concat(mergedFeatures[i].geometry[0]);
return i;
}
function getKey(text, geom, onRight) {
var point = onRight ? geom[0][geom[0].length - 1] : geom[0][0];
return (text + ":" + (point.x) + ":" + (point.y));
}
for (var k = 0; k < features.length; k++) {
var feature = features[k];
var geom = feature.geometry;
var text = feature.text instanceof Formatted ? feature.text.toString() : feature.text;
if (!text) {
add(k);
continue;
}
var leftKey = getKey(text, geom),
rightKey = getKey(text, geom, true);
if ((leftKey in rightIndex) && (rightKey in leftIndex) && (rightIndex[leftKey] !== leftIndex[rightKey])) {
// found lines with the same text adjacent to both ends of the current line, merge all three
var j = mergeFromLeft(leftKey, rightKey, geom);
var i = mergeFromRight(leftKey, rightKey, mergedFeatures[j].geometry);
delete leftIndex[leftKey];
delete rightIndex[rightKey];
rightIndex[getKey(text, mergedFeatures[i].geometry, true)] = i;
mergedFeatures[j].geometry = (null );
} else if (leftKey in rightIndex) {
// found mergeable line adjacent to the start of the current line, merge
mergeFromRight(leftKey, rightKey, geom);
} else if (rightKey in leftIndex) {
// found mergeable line adjacent to the end of the current line, merge
mergeFromLeft(leftKey, rightKey, geom);
} else {
// no adjacent lines, add as a new item
add(k);
leftIndex[leftKey] = mergedIndex - 1;
rightIndex[rightKey] = mergedIndex - 1;
}
}
return mergedFeatures.filter(function (f) { return f.geometry; });
}
//
var verticalizedCharacterMap = {
'!': '︕',
'#': '#',
'$': '$',
'%': '%',
'&': '&',
'(': '︵',
')': '︶',
'*': '*',
'+': '+',
',': '︐',
'-': '︲',
'.': '・',
'/': '/',
':': '︓',
';': '︔',
'<': '︿',
'=': '=',
'>': '﹀',
'?': '︖',
'@': '@',
'[': '﹇',
'\\': '\',
']': '﹈',
'^': '^',
'_': '︳',
'`': '`',
'{': '︷',
'|': '―',
'}': '︸',
'~': '~',
'¢': '¢',
'£': '£',
'¥': '¥',
'¦': '¦',
'¬': '¬',
'¯': ' ̄',
'–': '︲',
'—': '︱',
'‘': '﹃',
'’': '﹄',
'“': '﹁',
'”': '﹂',
'…': '︙',
'‧': '・',
'₩': '₩',
'、': '︑',
'。': '︒',
'〈': '︿',
'〉': '﹀',
'《': '︽',
'》': '︾',
'「': '﹁',
'」': '﹂',
'『': '﹃',
'』': '﹄',
'【': '︻',
'】': '︼',
'〔': '︹',
'〕': '︺',
'〖': '︗',
'〗': '︘',
'!': '︕',
'(': '︵',
')': '︶',
',': '︐',
'-': '︲',
'.': '・',
':': '︓',
';': '︔',
'<': '︿',
'>': '﹀',
'?': '︖',
'[': '﹇',
']': '﹈',
'_': '︳',
'{': '︷',
'|': '―',
'}': '︸',
'⦅': '︵',
'⦆': '︶',
'。': '︒',
'「': '﹁',
'」': '﹂'
};
function verticalizePunctuation(input ) {
var output = '';
for (var i = 0; i < input.length; i++) {
var nextCharCode = input.charCodeAt(i + 1) || null;
var prevCharCode = input.charCodeAt(i - 1) || null;
var canReplacePunctuation = (
(!nextCharCode || !charHasRotatedVerticalOrientation(nextCharCode) || verticalizedCharacterMap[input[i + 1]]) &&
(!prevCharCode || !charHasRotatedVerticalOrientation(prevCharCode) || verticalizedCharacterMap[input[i - 1]])
);
if (canReplacePunctuation && verticalizedCharacterMap[input[i]]) {
output += verticalizedCharacterMap[input[i]];
} else {
output += input[i];
}
}
return output;
}
//
var Anchor = (function (Point) {
function Anchor(x , y , angle , segment ) {
Point.call(this, x, y);
this.angle = angle;
if (segment !== undefined) {
this.segment = segment;
}
}
if ( Point ) Anchor.__proto__ = Point;
Anchor.prototype = Object.create( Point && Point.prototype );
Anchor.prototype.constructor = Anchor;
Anchor.prototype.clone = function clone () {
return new Anchor(this.x, this.y, this.angle, this.segment);
};
return Anchor;
}(pointGeometry));
register('Anchor', Anchor);
//
var SIZE_PACK_FACTOR = 256;
// For {text,icon}-size, get the bucket-level data that will be needed by
// the painter to set symbol-size-related uniforms
function getSizeData(tileZoom , value ) {
var expression = value.expression;
if (expression.kind === 'constant') {
return {
functionType: 'constant',
layoutSize: expression.evaluate(new EvaluationParameters(tileZoom + 1))
};
} else if (expression.kind === 'source') {
return {
functionType: 'source'
};
} else {
// calculate covering zoom stops for zoom-dependent values
var levels = expression.zoomStops;
var lower = 0;
while (lower < levels.length && levels[lower] <= tileZoom) { lower++; }
lower = Math.max(0, lower - 1);
var upper = lower;
while (upper < levels.length && levels[upper] < tileZoom + 1) { upper++; }
upper = Math.min(levels.length - 1, upper);
var zoomRange = {
min: levels[lower],
max: levels[upper]
};
// We'd like to be able to use CameraExpression or CompositeExpression in these
// return types rather than ExpressionSpecification, but the former are not
// transferrable across Web Worker boundaries.
if (expression.kind === 'composite') {
return {
functionType: 'composite',
zoomRange: zoomRange,
propertyValue: (value.value )
};
} else {
// for camera functions, also save off the function values
// evaluated at the covering zoom levels
return {
functionType: 'camera',
layoutSize: expression.evaluate(new EvaluationParameters(tileZoom + 1)),
zoomRange: zoomRange,
sizeRange: {
min: expression.evaluate(new EvaluationParameters(zoomRange.min)),
max: expression.evaluate(new EvaluationParameters(zoomRange.max))
},
propertyValue: (value.value )
};
}
}
}
function evaluateSizeForFeature(sizeData ,
partiallyEvaluatedSize ,
symbol ) {
var part = partiallyEvaluatedSize;
if (sizeData.functionType === 'source') {
return symbol.lowerSize / SIZE_PACK_FACTOR;
} else if (sizeData.functionType === 'composite') {
return number(symbol.lowerSize / SIZE_PACK_FACTOR, symbol.upperSize / SIZE_PACK_FACTOR, part.uSizeT);
} else {
return part.uSize;
}
}
function evaluateSizeForZoom(sizeData , currentZoom , property ) {
if (sizeData.functionType === 'constant') {
return {
uSizeT: 0,
uSize: sizeData.layoutSize
};
} else if (sizeData.functionType === 'source') {
return {
uSizeT: 0,
uSize: 0
};
} else if (sizeData.functionType === 'camera') {
var propertyValue = sizeData.propertyValue;
var zoomRange = sizeData.zoomRange;
var sizeRange = sizeData.sizeRange;
var expression = ((normalizePropertyExpression(propertyValue, property.specification) ) );
// Even though we could get the exact value of the camera function
// at z = tr.zoom, we intentionally do not: instead, we interpolate
// between the camera function values at a pair of zoom stops covering
// [tileZoom, tileZoom + 1] in order to be consistent with this
// restriction on composite functions
var t = clamp(
expression.interpolationFactor(currentZoom, zoomRange.min, zoomRange.max),
0,
1
);
return {
uSizeT: 0,
uSize: sizeRange.min + t * (sizeRange.max - sizeRange.min)
};
} else {
var propertyValue$1 = sizeData.propertyValue;
var zoomRange$1 = sizeData.zoomRange;
var expression$1 = ((normalizePropertyExpression(propertyValue$1, property.specification) ) );
return {
uSizeT: clamp(
expression$1.interpolationFactor(currentZoom, zoomRange$1.min, zoomRange$1.max),
0,
1
),
uSize: 0
};
}
}
//
var vectorTileFeatureTypes$1 = vectorTile.VectorTileFeature.types;
// Opacity arrays are frequently updated but don't contain a lot of information, so we pack them
// tight. Each Uint32 is actually four duplicate Uint8s for the four corners of a glyph
// 7 bits are for the current opacity, and the lowest bit is the target opacity
// actually defined in symbol_attributes.js
// const placementOpacityAttributes = [
// { name: 'a_fade_opacity', components: 1, type: 'Uint32' }
// ];
var shaderOpacityAttributes = [
{ name: 'a_fade_opacity', components: 1, type: 'Uint8', offset: 0 }
];
function addVertex$1(array, anchorX, anchorY, ox, oy, tx, ty, sizeVertex) {
array.emplaceBack(
// a_pos_offset
anchorX,
anchorY,
Math.round(ox * 32),
Math.round(oy * 32),
// a_data
tx, // x coordinate of symbol on glyph atlas texture
ty, // y coordinate of symbol on glyph atlas texture
sizeVertex ? sizeVertex[0] : 0,
sizeVertex ? sizeVertex[1] : 0
);
}
function addDynamicAttributes(dynamicLayoutVertexArray , p , angle ) {
dynamicLayoutVertexArray.emplaceBack(p.x, p.y, angle);
dynamicLayoutVertexArray.emplaceBack(p.x, p.y, angle);
dynamicLayoutVertexArray.emplaceBack(p.x, p.y, angle);
dynamicLayoutVertexArray.emplaceBack(p.x, p.y, angle);
}
var SymbolBuffers = function SymbolBuffers(programConfigurations ) {
this.layoutVertexArray = new StructArrayLayout4i4ui16();
this.indexArray = new StructArrayLayout3ui6();
this.programConfigurations = programConfigurations;
this.segments = new SegmentVector();
this.dynamicLayoutVertexArray = new StructArrayLayout3f12();
this.opacityVertexArray = new StructArrayLayout1ul4();
this.placedSymbolArray = new PlacedSymbolArray();
};
SymbolBuffers.prototype.upload = function upload (context , dynamicIndexBuffer , upload$1 , update ) {
if (upload$1) {
this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, symbolLayoutAttributes.members);
this.indexBuffer = context.createIndexBuffer(this.indexArray, dynamicIndexBuffer);
this.dynamicLayoutVertexBuffer = context.createVertexBuffer(this.dynamicLayoutVertexArray, dynamicLayoutAttributes.members, true);
this.opacityVertexBuffer = context.createVertexBuffer(this.opacityVertexArray, shaderOpacityAttributes, true);
// This is a performance hack so that we can write to opacityVertexArray with uint32s
// even though the shaders read uint8s
this.opacityVertexBuffer.itemSize = 1;
}
if (upload$1 || update) {
this.programConfigurations.upload(context);
}
};
SymbolBuffers.prototype.destroy = function destroy () {
if (!this.layoutVertexBuffer) { return; }
this.layoutVertexBuffer.destroy();
this.indexBuffer.destroy();
this.programConfigurations.destroy();
this.segments.destroy();
this.dynamicLayoutVertexBuffer.destroy();
this.opacityVertexBuffer.destroy();
};
register('SymbolBuffers', SymbolBuffers);
var CollisionBuffers = function CollisionBuffers(LayoutArray ,
layoutAttributes ,
IndexArray ) {
this.layoutVertexArray = new LayoutArray();
this.layoutAttributes = layoutAttributes;
this.indexArray = new IndexArray();
this.segments = new SegmentVector();
this.collisionVertexArray = new StructArrayLayout2ub4();
};
CollisionBuffers.prototype.upload = function upload (context ) {
this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, this.layoutAttributes);
this.indexBuffer = context.createIndexBuffer(this.indexArray);
this.collisionVertexBuffer = context.createVertexBuffer(this.collisionVertexArray, collisionVertexAttributes.members, true);
};
CollisionBuffers.prototype.destroy = function destroy () {
if (!this.layoutVertexBuffer) { return; }
this.layoutVertexBuffer.destroy();
this.indexBuffer.destroy();
this.segments.destroy();
this.collisionVertexBuffer.destroy();
};
register('CollisionBuffers', CollisionBuffers);
/**
* Unlike other buckets, which simply implement #addFeature with type-specific
* logic for (essentially) triangulating feature geometries, SymbolBucket
* requires specialized behavior:
*
* 1. WorkerTile#parse(), the logical owner of the bucket creation process,
* calls SymbolBucket#populate(), which resolves text and icon tokens on
* each feature, adds each glyphs and symbols needed to the passed-in
* collections options.glyphDependencies and options.iconDependencies, and
* stores the feature data for use in subsequent step (this.features).
*
* 2. WorkerTile asynchronously requests from the main thread all of the glyphs
* and icons needed (by this bucket and any others). When glyphs and icons
* have been received, the WorkerTile creates a CollisionIndex and invokes:
*
* 3. performSymbolLayout(bucket, stacks, icons) perform texts shaping and
* layout on a Symbol Bucket. This step populates:
* `this.symbolInstances`: metadata on generated symbols
* `this.collisionBoxArray`: collision data for use by foreground
* `this.text`: SymbolBuffers for text symbols
* `this.icons`: SymbolBuffers for icons
* `this.collisionBox`: Debug SymbolBuffers for collision boxes
* `this.collisionCircle`: Debug SymbolBuffers for collision circles
* The results are sent to the foreground for rendering
*
* 4. performSymbolPlacement(bucket, collisionIndex) is run on the foreground,
* and uses the CollisionIndex along with current camera settings to determine
* which symbols can actually show on the map. Collided symbols are hidden
* using a dynamic "OpacityVertexArray".
*
* @private
*/
var SymbolBucket = function SymbolBucket(options ) {
this.collisionBoxArray = options.collisionBoxArray;
this.zoom = options.zoom;
this.overscaling = options.overscaling;
this.layers = options.layers;
this.layerIds = this.layers.map(function (layer) { return layer.id; });
this.index = options.index;
this.pixelRatio = options.pixelRatio;
this.sourceLayerIndex = options.sourceLayerIndex;
var layer = this.layers[0];
var unevaluatedLayoutValues = layer._unevaluatedLayout._values;
this.textSizeData = getSizeData(this.zoom, unevaluatedLayoutValues['text-size']);
this.iconSizeData = getSizeData(this.zoom, unevaluatedLayoutValues['icon-size']);
var layout = this.layers[0].layout;
this.sortFeaturesByY = layout.get('text-allow-overlap') || layout.get('icon-allow-overlap') ||
layout.get('text-ignore-placement') || layout.get('icon-ignore-placement');
this.sourceID = options.sourceID;
};
SymbolBucket.prototype.createArrays = function createArrays () {
this.text = new SymbolBuffers(new ProgramConfigurationSet(symbolLayoutAttributes.members, this.layers, this.zoom, function (property) { return /^text/.test(property); }));
this.icon = new SymbolBuffers(new ProgramConfigurationSet(symbolLayoutAttributes.members, this.layers, this.zoom, function (property) { return /^icon/.test(property); }));
this.collisionBox = new CollisionBuffers(StructArrayLayout2i2i2i12, collisionBoxLayout.members, StructArrayLayout2ui4);
this.collisionCircle = new CollisionBuffers(StructArrayLayout2i2i2i12, collisionCircleLayout.members, StructArrayLayout3ui6);
this.glyphOffsetArray = new GlyphOffsetArray();
this.lineVertexArray = new SymbolLineVertexArray();
};
SymbolBucket.prototype.calculateGlyphDependencies = function calculateGlyphDependencies (text , stack , textAlongLine , doesAllowVerticalWritingMode ) {
for (var i = 0; i < text.length; i++) {
stack[text.charCodeAt(i)] = true;
if (textAlongLine && doesAllowVerticalWritingMode) {
var verticalChar = verticalizedCharacterMap[text.charAt(i)];
if (verticalChar) {
stack[verticalChar.charCodeAt(0)] = true;
}
}
}
};
SymbolBucket.prototype.populate = function populate (features , options ) {
var this$1 = this;
var layer = this.layers[0];
var layout = layer.layout;
var textFont = layout.get('text-font');
var textField = layout.get('text-field');
var iconImage = layout.get('icon-image');
var hasText =
(textField.value.kind !== 'constant' || textField.value.value.toString().length > 0) &&
(textFont.value.kind !== 'constant' || textFont.value.value.length > 0);
var hasIcon = iconImage.value.kind !== 'constant' || iconImage.value.value && iconImage.value.value.length > 0;
this.features = [];
if (!hasText && !hasIcon) {
return;
}
var icons = options.iconDependencies;
var stacks = options.glyphDependencies;
var globalProperties = new EvaluationParameters(this.zoom);
for (var i$1 = 0, list$1 = features; i$1 < list$1.length; i$1 += 1) {
var ref = list$1[i$1];
var feature = ref.feature;
var index = ref.index;
var sourceLayerIndex = ref.sourceLayerIndex;
if (!layer._featureFilter(globalProperties, feature)) {
continue;
}
var text = (void 0);
if (hasText) {
text = layer.getValueAndResolveTokens('text-field', feature);
text = transformText$1(text, layer, feature);
}
var icon = (void 0);
if (hasIcon) {
icon = layer.getValueAndResolveTokens('icon-image', feature);
}
if (!text && !icon) {
continue;
}
var symbolFeature = {
text: text,
icon: icon,
index: index,
sourceLayerIndex: sourceLayerIndex,
geometry: loadGeometry(feature),
properties: feature.properties,
type: vectorTileFeatureTypes$1[feature.type]
};
if (typeof feature.id !== 'undefined') {
symbolFeature.id = feature.id;
}
this$1.features.push(symbolFeature);
if (icon) {
icons[icon] = true;
}
if (text) {
var fontStack = textFont.evaluate(feature, {}).join(',');
var stack = stacks[fontStack] = stacks[fontStack] || {};
var textAlongLine = layout.get('text-rotation-alignment') === 'map' && layout.get('symbol-placement') !== 'point';
if (text instanceof Formatted) {
for (var i = 0, list = text.sections; i < list.length; i += 1) {
var section = list[i];
var doesAllowVerticalWritingMode = allowsVerticalWritingMode(text.toString());
var sectionFont = section.fontStack || fontStack;
var sectionStack = stacks[sectionFont] = stacks[sectionFont] || {};
this$1.calculateGlyphDependencies(section.text, sectionStack, textAlongLine, doesAllowVerticalWritingMode);
}
} else {
var doesAllowVerticalWritingMode$1 = allowsVerticalWritingMode(text);
this$1.calculateGlyphDependencies(text, stack, textAlongLine, doesAllowVerticalWritingMode$1);
}
}
}
if (layout.get('symbol-placement') === 'line') {
// Merge adjacent lines with the same text to improve labelling.
// It's better to place labels on one long line than on many short segments.
this.features = mergeLines(this.features);
}
};
SymbolBucket.prototype.update = function update (states , vtLayer ) {
if (!this.stateDependentLayers.length) { return; }
this.text.programConfigurations.updatePaintArrays(states, vtLayer, this.layers);
this.icon.programConfigurations.updatePaintArrays(states, vtLayer, this.layers);
};
SymbolBucket.prototype.isEmpty = function isEmpty () {
return this.symbolInstances.length === 0;
};
SymbolBucket.prototype.uploadPending = function uploadPending () {
return !this.uploaded || this.text.programConfigurations.needsUpload || this.icon.programConfigurations.needsUpload;
};
SymbolBucket.prototype.upload = function upload (context ) {
if (!this.uploaded) {
this.collisionBox.upload(context);
this.collisionCircle.upload(context);
}
this.text.upload(context, this.sortFeaturesByY, !this.uploaded, this.text.programConfigurations.needsUpload);
this.icon.upload(context, this.sortFeaturesByY, !this.uploaded, this.icon.programConfigurations.needsUpload);
this.uploaded = true;
};
SymbolBucket.prototype.destroy = function destroy () {
this.text.destroy();
this.icon.destroy();
this.collisionBox.destroy();
this.collisionCircle.destroy();
};
SymbolBucket.prototype.addToLineVertexArray = function addToLineVertexArray (anchor , line ) {
var this$1 = this;
var lineStartIndex = this.lineVertexArray.length;
if (anchor.segment !== undefined) {
var sumForwardLength = anchor.dist(line[anchor.segment + 1]);
var sumBackwardLength = anchor.dist(line[anchor.segment]);
var vertices = {};
for (var i = anchor.segment + 1; i < line.length; i++) {
vertices[i] = { x: line[i].x, y: line[i].y, tileUnitDistanceFromAnchor: sumForwardLength };
if (i < line.length - 1) {
sumForwardLength += line[i + 1].dist(line[i]);
}
}
for (var i$1 = anchor.segment || 0; i$1 >= 0; i$1--) {
vertices[i$1] = { x: line[i$1].x, y: line[i$1].y, tileUnitDistanceFromAnchor: sumBackwardLength };
if (i$1 > 0) {
sumBackwardLength += line[i$1 - 1].dist(line[i$1]);
}
}
for (var i$2 = 0; i$2 < line.length; i$2++) {
var vertex = vertices[i$2];
this$1.lineVertexArray.emplaceBack(vertex.x, vertex.y, vertex.tileUnitDistanceFromAnchor);
}
}
return {
lineStartIndex: lineStartIndex,
lineLength: this.lineVertexArray.length - lineStartIndex
};
};
SymbolBucket.prototype.addSymbols = function addSymbols (arrays ,
quads ,
sizeVertex ,
lineOffset ,
alongLine ,
feature ,
writingMode ,
labelAnchor ,
lineStartIndex ,
lineLength ) {
var this$1 = this;
var indexArray = arrays.indexArray;
var layoutVertexArray = arrays.layoutVertexArray;
var dynamicLayoutVertexArray = arrays.dynamicLayoutVertexArray;
var segment = arrays.segments.prepareSegment(4 * quads.length, arrays.layoutVertexArray, arrays.indexArray);
var glyphOffsetArrayStart = this.glyphOffsetArray.length;
var vertexStartIndex = segment.vertexLength;
for (var i = 0, list = quads; i < list.length; i += 1) {
var symbol = list[i];
var tl = symbol.tl,
tr = symbol.tr,
bl = symbol.bl,
br = symbol.br,
tex = symbol.tex;
var index = segment.vertexLength;
var y = symbol.glyphOffset[1];
addVertex$1(layoutVertexArray, labelAnchor.x, labelAnchor.y, tl.x, y + tl.y, tex.x, tex.y, sizeVertex);
addVertex$1(layoutVertexArray, labelAnchor.x, labelAnchor.y, tr.x, y + tr.y, tex.x + tex.w, tex.y, sizeVertex);
addVertex$1(layoutVertexArray, labelAnchor.x, labelAnchor.y, bl.x, y + bl.y, tex.x, tex.y + tex.h, sizeVertex);
addVertex$1(layoutVertexArray, labelAnchor.x, labelAnchor.y, br.x, y + br.y, tex.x + tex.w, tex.y + tex.h, sizeVertex);
addDynamicAttributes(dynamicLayoutVertexArray, labelAnchor, 0);
indexArray.emplaceBack(index, index + 1, index + 2);
indexArray.emplaceBack(index + 1, index + 2, index + 3);
segment.vertexLength += 4;
segment.primitiveLength += 2;
this$1.glyphOffsetArray.emplaceBack(symbol.glyphOffset[0]);
}
arrays.placedSymbolArray.emplaceBack(labelAnchor.x, labelAnchor.y,
glyphOffsetArrayStart, this.glyphOffsetArray.length - glyphOffsetArrayStart, vertexStartIndex,
lineStartIndex, lineLength, (labelAnchor.segment ),
sizeVertex ? sizeVertex[0] : 0, sizeVertex ? sizeVertex[1] : 0,
lineOffset[0], lineOffset[1],
writingMode, (false ));
arrays.programConfigurations.populatePaintArrays(arrays.layoutVertexArray.length, feature, feature.index);
};
SymbolBucket.prototype._addCollisionDebugVertex = function _addCollisionDebugVertex (layoutVertexArray , collisionVertexArray , point , anchor , extrude ) {
collisionVertexArray.emplaceBack(0, 0);
return layoutVertexArray.emplaceBack(
// pos
point.x,
point.y,
// a_anchor_pos
anchor.x,
anchor.y,
// extrude
Math.round(extrude.x),
Math.round(extrude.y));
};
SymbolBucket.prototype.addCollisionDebugVertices = function addCollisionDebugVertices (x1 , y1 , x2 , y2 , arrays , boxAnchorPoint , symbolInstance , isCircle ) {
var segment = arrays.segments.prepareSegment(4, arrays.layoutVertexArray, arrays.indexArray);
var index = segment.vertexLength;
var layoutVertexArray = arrays.layoutVertexArray;
var collisionVertexArray = arrays.collisionVertexArray;
this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, symbolInstance.anchor, new pointGeometry(x1, y1));
this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, symbolInstance.anchor, new pointGeometry(x2, y1));
this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, symbolInstance.anchor, new pointGeometry(x2, y2));
this._addCollisionDebugVertex(layoutVertexArray, collisionVertexArray, boxAnchorPoint, symbolInstance.anchor, new pointGeometry(x1, y2));
segment.vertexLength += 4;
if (isCircle) {
var indexArray = (arrays.indexArray );
indexArray.emplaceBack(index, index + 1, index + 2);
indexArray.emplaceBack(index, index + 2, index + 3);
segment.primitiveLength += 2;
} else {
var indexArray$1 = (arrays.indexArray );
indexArray$1.emplaceBack(index, index + 1);
indexArray$1.emplaceBack(index + 1, index + 2);
indexArray$1.emplaceBack(index + 2, index + 3);
indexArray$1.emplaceBack(index + 3, index);
segment.primitiveLength += 4;
}
};
SymbolBucket.prototype.generateCollisionDebugBuffers = function generateCollisionDebugBuffers () {
var this$1 = this;
for (var i$1 = 0, list = this$1.symbolInstances; i$1 < list.length; i$1 += 1) {
var symbolInstance = list[i$1];
symbolInstance.textCollisionFeature = {boxStartIndex: symbolInstance.textBoxStartIndex, boxEndIndex: symbolInstance.textBoxEndIndex};
symbolInstance.iconCollisionFeature = {boxStartIndex: symbolInstance.iconBoxStartIndex, boxEndIndex: symbolInstance.iconBoxEndIndex};
for (var i = 0; i < 2; i++) {
var feature = symbolInstance[i === 0 ? 'textCollisionFeature' : 'iconCollisionFeature'];
if (!feature) { continue; }
for (var b = feature.boxStartIndex; b < feature.boxEndIndex; b++) {
var box = (this$1.collisionBoxArray.get(b) );
var x1 = box.x1;
var y1 = box.y1;
var x2 = box.x2;
var y2 = box.y2;
// If the radius > 0, this collision box is actually a circle
// The data we add to the buffers is exactly the same, but we'll render with a different shader.
var isCircle = box.radius > 0;
this$1.addCollisionDebugVertices(x1, y1, x2, y2, isCircle ? this$1.collisionCircle : this$1.collisionBox, box.anchorPoint, symbolInstance, isCircle);
}
}
}
};
// These flat arrays are meant to be quicker to iterate over than the source
// CollisionBoxArray
SymbolBucket.prototype.deserializeCollisionBoxes = function deserializeCollisionBoxes (collisionBoxArray , textStartIndex , textEndIndex , iconStartIndex , iconEndIndex ) {
var collisionArrays = {};
for (var k = textStartIndex; k < textEndIndex; k++) {
var box = (collisionBoxArray.get(k) );
if (box.radius === 0) {
collisionArrays.textBox = { x1: box.x1, y1: box.y1, x2: box.x2, y2: box.y2, anchorPointX: box.anchorPointX, anchorPointY: box.anchorPointY };
collisionArrays.textFeatureIndex = box.featureIndex;
break; // Only one box allowed per instance
} else {
if (!collisionArrays.textCircles) {
collisionArrays.textCircles = [];
collisionArrays.textFeatureIndex = box.featureIndex;
}
var used = 1; // May be updated at collision detection time
collisionArrays.textCircles.push(box.anchorPointX, box.anchorPointY, box.radius, box.signedDistanceFromAnchor, used);
}
}
for (var k$1 = iconStartIndex; k$1 < iconEndIndex; k$1++) {
// An icon can only have one box now, so this indexing is a bit vestigial...
var box$1 = (collisionBoxArray.get(k$1) );
if (box$1.radius === 0) {
collisionArrays.iconBox = { x1: box$1.x1, y1: box$1.y1, x2: box$1.x2, y2: box$1.y2, anchorPointX: box$1.anchorPointX, anchorPointY: box$1.anchorPointY };
collisionArrays.iconFeatureIndex = box$1.featureIndex;
break; // Only one box allowed per instance
}
}
return collisionArrays;
};
SymbolBucket.prototype.hasTextData = function hasTextData () {
return this.text.segments.get().length > 0;
};
SymbolBucket.prototype.hasIconData = function hasIconData () {
return this.icon.segments.get().length > 0;
};
SymbolBucket.prototype.hasCollisionBoxData = function hasCollisionBoxData () {
return this.collisionBox.segments.get().length > 0;
};
SymbolBucket.prototype.hasCollisionCircleData = function hasCollisionCircleData () {
return this.collisionCircle.segments.get().length > 0;
};
SymbolBucket.prototype.sortFeatures = function sortFeatures (angle ) {
var this$1 = this;
if (!this.sortFeaturesByY) { return; }
if (this.sortedAngle === angle) { return; }
this.sortedAngle = angle;
// The current approach to sorting doesn't sort across segments so don't try.
// Sorting within segments separately seemed not to be worth the complexity.
if (this.text.segments.get().length > 1 || this.icon.segments.get().length > 1) { return; }
// If the symbols are allowed to overlap sort them by their vertical screen position.
// The index array buffer is rewritten to reference the (unchanged) vertices in the
// sorted order.
// To avoid sorting the actual symbolInstance array we sort an array of indexes.
var symbolInstanceIndexes = [];
for (var i = 0; i < this.symbolInstances.length; i++) {
symbolInstanceIndexes.push(i);
}
var sin = Math.sin(angle),
cos = Math.cos(angle);
symbolInstanceIndexes.sort(function (aIndex, bIndex) {
var a = this$1.symbolInstances[aIndex];
var b = this$1.symbolInstances[bIndex];
var aRotated = Math.round(sin * a.anchor.x + cos * a.anchor.y) | 0;
var bRotated = Math.round(sin * b.anchor.x + cos * b.anchor.y) | 0;
return (aRotated - bRotated) || (b.featureIndex - a.featureIndex);
});
this.text.indexArray.clear();
this.icon.indexArray.clear();
this.featureSortOrder = [];
for (var i$3 = 0, list$1 = symbolInstanceIndexes; i$3 < list$1.length; i$3 += 1) {
var i$1 = list$1[i$3];
var symbolInstance = this$1.symbolInstances[i$1];
this$1.featureSortOrder.push(symbolInstance.featureIndex);
for (var i$2 = 0, list = symbolInstance.placedTextSymbolIndices; i$2 < list.length; i$2 += 1) {
var placedTextSymbolIndex = list[i$2];
var placedSymbol = this$1.text.placedSymbolArray.get(placedTextSymbolIndex);
var endIndex = placedSymbol.vertexStartIndex + placedSymbol.numGlyphs * 4;
for (var vertexIndex = placedSymbol.vertexStartIndex; vertexIndex < endIndex; vertexIndex += 4) {
this$1.text.indexArray.emplaceBack(vertexIndex, vertexIndex + 1, vertexIndex + 2);
this$1.text.indexArray.emplaceBack(vertexIndex + 1, vertexIndex + 2, vertexIndex + 3);
}
}
var placedIcon = this$1.icon.placedSymbolArray.get(i$1);
if (placedIcon.numGlyphs) {
var vertexIndex$1 = placedIcon.vertexStartIndex;
this$1.icon.indexArray.emplaceBack(vertexIndex$1, vertexIndex$1 + 1, vertexIndex$1 + 2);
this$1.icon.indexArray.emplaceBack(vertexIndex$1 + 1, vertexIndex$1 + 2, vertexIndex$1 + 3);
}
}
if (this.text.indexBuffer) { this.text.indexBuffer.updateData(this.text.indexArray); }
if (this.icon.indexBuffer) { this.icon.indexBuffer.updateData(this.icon.indexArray); }
};
register('SymbolBucket', SymbolBucket, {
omit: ['layers', 'collisionBoxArray', 'features', 'compareText'],
shallow: ['symbolInstances']
});
// this constant is based on the size of StructArray indexes used in a symbol
// bucket--namely, glyphOffsetArrayStart
// eg the max valid UInt16 is 65,535
// See https://github.com/mapbox/mapbox-gl-js/issues/2907 for motivation
// lineStartIndex and textBoxStartIndex could potentially be concerns
// but we expect there to be many fewer boxes/lines than glyphs
SymbolBucket.MAX_GLYPHS = 65535;
SymbolBucket.addDynamicAttributes = addDynamicAttributes;
//
/**
* Replace tokens in a string template with values in an object
*
* @param properties a key/value relationship between tokens and replacements
* @param text the template string
* @returns the template with tokens replaced
* @private
*/
function resolveTokens(properties , text ) {
return text.replace(/{([^{}]+)}/g, function (match, key ) {
return key in properties ? String(properties[key]) : '';
});
}
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
var layout$6 = new Properties({
"symbol-placement": new DataConstantProperty(styleSpec["layout_symbol"]["symbol-placement"]),
"symbol-spacing": new DataConstantProperty(styleSpec["layout_symbol"]["symbol-spacing"]),
"symbol-avoid-edges": new DataConstantProperty(styleSpec["layout_symbol"]["symbol-avoid-edges"]),
"icon-allow-overlap": new DataConstantProperty(styleSpec["layout_symbol"]["icon-allow-overlap"]),
"icon-ignore-placement": new DataConstantProperty(styleSpec["layout_symbol"]["icon-ignore-placement"]),
"icon-optional": new DataConstantProperty(styleSpec["layout_symbol"]["icon-optional"]),
"icon-rotation-alignment": new DataConstantProperty(styleSpec["layout_symbol"]["icon-rotation-alignment"]),
"icon-size": new DataDrivenProperty(styleSpec["layout_symbol"]["icon-size"]),
"icon-text-fit": new DataConstantProperty(styleSpec["layout_symbol"]["icon-text-fit"]),
"icon-text-fit-padding": new DataConstantProperty(styleSpec["layout_symbol"]["icon-text-fit-padding"]),
"icon-image": new DataDrivenProperty(styleSpec["layout_symbol"]["icon-image"]),
"icon-rotate": new DataDrivenProperty(styleSpec["layout_symbol"]["icon-rotate"]),
"icon-padding": new DataConstantProperty(styleSpec["layout_symbol"]["icon-padding"]),
"icon-keep-upright": new DataConstantProperty(styleSpec["layout_symbol"]["icon-keep-upright"]),
"icon-offset": new DataDrivenProperty(styleSpec["layout_symbol"]["icon-offset"]),
"icon-anchor": new DataDrivenProperty(styleSpec["layout_symbol"]["icon-anchor"]),
"icon-pitch-alignment": new DataConstantProperty(styleSpec["layout_symbol"]["icon-pitch-alignment"]),
"text-pitch-alignment": new DataConstantProperty(styleSpec["layout_symbol"]["text-pitch-alignment"]),
"text-rotation-alignment": new DataConstantProperty(styleSpec["layout_symbol"]["text-rotation-alignment"]),
"text-field": new DataDrivenProperty(styleSpec["layout_symbol"]["text-field"]),
"text-font": new DataDrivenProperty(styleSpec["layout_symbol"]["text-font"]),
"text-size": new DataDrivenProperty(styleSpec["layout_symbol"]["text-size"]),
"text-max-width": new DataDrivenProperty(styleSpec["layout_symbol"]["text-max-width"]),
"text-line-height": new DataConstantProperty(styleSpec["layout_symbol"]["text-line-height"]),
"text-letter-spacing": new DataDrivenProperty(styleSpec["layout_symbol"]["text-letter-spacing"]),
"text-justify": new DataDrivenProperty(styleSpec["layout_symbol"]["text-justify"]),
"text-anchor": new DataDrivenProperty(styleSpec["layout_symbol"]["text-anchor"]),
"text-max-angle": new DataConstantProperty(styleSpec["layout_symbol"]["text-max-angle"]),
"text-rotate": new DataDrivenProperty(styleSpec["layout_symbol"]["text-rotate"]),
"text-padding": new DataConstantProperty(styleSpec["layout_symbol"]["text-padding"]),
"text-keep-upright": new DataConstantProperty(styleSpec["layout_symbol"]["text-keep-upright"]),
"text-transform": new DataDrivenProperty(styleSpec["layout_symbol"]["text-transform"]),
"text-offset": new DataDrivenProperty(styleSpec["layout_symbol"]["text-offset"]),
"text-allow-overlap": new DataConstantProperty(styleSpec["layout_symbol"]["text-allow-overlap"]),
"text-ignore-placement": new DataConstantProperty(styleSpec["layout_symbol"]["text-ignore-placement"]),
"text-optional": new DataConstantProperty(styleSpec["layout_symbol"]["text-optional"]),
});
var paint$7 = new Properties({
"icon-opacity": new DataDrivenProperty(styleSpec["paint_symbol"]["icon-opacity"]),
"icon-color": new DataDrivenProperty(styleSpec["paint_symbol"]["icon-color"]),
"icon-halo-color": new DataDrivenProperty(styleSpec["paint_symbol"]["icon-halo-color"]),
"icon-halo-width": new DataDrivenProperty(styleSpec["paint_symbol"]["icon-halo-width"]),
"icon-halo-blur": new DataDrivenProperty(styleSpec["paint_symbol"]["icon-halo-blur"]),
"icon-translate": new DataConstantProperty(styleSpec["paint_symbol"]["icon-translate"]),
"icon-translate-anchor": new DataConstantProperty(styleSpec["paint_symbol"]["icon-translate-anchor"]),
"text-opacity": new DataDrivenProperty(styleSpec["paint_symbol"]["text-opacity"]),
"text-color": new DataDrivenProperty(styleSpec["paint_symbol"]["text-color"]),
"text-halo-color": new DataDrivenProperty(styleSpec["paint_symbol"]["text-halo-color"]),
"text-halo-width": new DataDrivenProperty(styleSpec["paint_symbol"]["text-halo-width"]),
"text-halo-blur": new DataDrivenProperty(styleSpec["paint_symbol"]["text-halo-blur"]),
"text-translate": new DataConstantProperty(styleSpec["paint_symbol"]["text-translate"]),
"text-translate-anchor": new DataConstantProperty(styleSpec["paint_symbol"]["text-translate-anchor"]),
});
// Note: without adding the explicit type annotation, Flow infers weaker types
// for these objects from their use in the constructor to StyleLayer, as
// {layout?: Properties<...>, paint: Properties<...>}
var properties$6 = ({ paint: paint$7, layout: layout$6 }
);
//
var SymbolStyleLayer = (function (StyleLayer$$1) {
function SymbolStyleLayer(layer ) {
StyleLayer$$1.call(this, layer, properties$6);
}
if ( StyleLayer$$1 ) SymbolStyleLayer.__proto__ = StyleLayer$$1;
SymbolStyleLayer.prototype = Object.create( StyleLayer$$1 && StyleLayer$$1.prototype );
SymbolStyleLayer.prototype.constructor = SymbolStyleLayer;
SymbolStyleLayer.prototype.recalculate = function recalculate (parameters ) {
StyleLayer$$1.prototype.recalculate.call(this, parameters);
if (this.layout.get('icon-rotation-alignment') === 'auto') {
if (this.layout.get('symbol-placement') !== 'point') {
this.layout._values['icon-rotation-alignment'] = 'map';
} else {
this.layout._values['icon-rotation-alignment'] = 'viewport';
}
}
if (this.layout.get('text-rotation-alignment') === 'auto') {
if (this.layout.get('symbol-placement') !== 'point') {
this.layout._values['text-rotation-alignment'] = 'map';
} else {
this.layout._values['text-rotation-alignment'] = 'viewport';
}
}
// If unspecified, `*-pitch-alignment` inherits `*-rotation-alignment`
if (this.layout.get('text-pitch-alignment') === 'auto') {
this.layout._values['text-pitch-alignment'] = this.layout.get('text-rotation-alignment');
}
if (this.layout.get('icon-pitch-alignment') === 'auto') {
this.layout._values['icon-pitch-alignment'] = this.layout.get('icon-rotation-alignment');
}
};
SymbolStyleLayer.prototype.getValueAndResolveTokens = function getValueAndResolveTokens (name , feature ) {
var value = this.layout.get(name).evaluate(feature, {});
var unevaluated = this._unevaluatedLayout._values[name];
if (!unevaluated.isDataDriven() && !isExpression(unevaluated.value)) {
return resolveTokens(feature.properties, value);
}
return value;
};
SymbolStyleLayer.prototype.createBucket = function createBucket (parameters ) {
return new SymbolBucket(parameters);
};
SymbolStyleLayer.prototype.queryRadius = function queryRadius () {
return 0;
};
SymbolStyleLayer.prototype.queryIntersectsFeature = function queryIntersectsFeature () {
assert_1(false); // Should take a different path in FeatureIndex
return false;
};
return SymbolStyleLayer;
}(StyleLayer));
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
var paint$8 = new Properties({
"background-color": new DataConstantProperty(styleSpec["paint_background"]["background-color"]),
"background-pattern": new CrossFadedProperty(styleSpec["paint_background"]["background-pattern"]),
"background-opacity": new DataConstantProperty(styleSpec["paint_background"]["background-opacity"]),
});
// Note: without adding the explicit type annotation, Flow infers weaker types
// for these objects from their use in the constructor to StyleLayer, as
// {layout?: Properties<...>, paint: Properties<...>}
var properties$7 = ({ paint: paint$8 }
);
//
var BackgroundStyleLayer = (function (StyleLayer$$1) {
function BackgroundStyleLayer(layer ) {
StyleLayer$$1.call(this, layer, properties$7);
}
if ( StyleLayer$$1 ) BackgroundStyleLayer.__proto__ = StyleLayer$$1;
BackgroundStyleLayer.prototype = Object.create( StyleLayer$$1 && StyleLayer$$1.prototype );
BackgroundStyleLayer.prototype.constructor = BackgroundStyleLayer;
return BackgroundStyleLayer;
}(StyleLayer));
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
var paint$9 = new Properties({
"raster-opacity": new DataConstantProperty(styleSpec["paint_raster"]["raster-opacity"]),
"raster-hue-rotate": new DataConstantProperty(styleSpec["paint_raster"]["raster-hue-rotate"]),
"raster-brightness-min": new DataConstantProperty(styleSpec["paint_raster"]["raster-brightness-min"]),
"raster-brightness-max": new DataConstantProperty(styleSpec["paint_raster"]["raster-brightness-max"]),
"raster-saturation": new DataConstantProperty(styleSpec["paint_raster"]["raster-saturation"]),
"raster-contrast": new DataConstantProperty(styleSpec["paint_raster"]["raster-contrast"]),
"raster-resampling": new DataConstantProperty(styleSpec["paint_raster"]["raster-resampling"]),
"raster-fade-duration": new DataConstantProperty(styleSpec["paint_raster"]["raster-fade-duration"]),
});
// Note: without adding the explicit type annotation, Flow infers weaker types
// for these objects from their use in the constructor to StyleLayer, as
// {layout?: Properties<...>, paint: Properties<...>}
var properties$8 = ({ paint: paint$9 }
);
//
var RasterStyleLayer = (function (StyleLayer$$1) {
function RasterStyleLayer(layer ) {
StyleLayer$$1.call(this, layer, properties$8);
}
if ( StyleLayer$$1 ) RasterStyleLayer.__proto__ = StyleLayer$$1;
RasterStyleLayer.prototype = Object.create( StyleLayer$$1 && StyleLayer$$1.prototype );
RasterStyleLayer.prototype.constructor = RasterStyleLayer;
return RasterStyleLayer;
}(StyleLayer));
//
var subclasses = {
circle: CircleStyleLayer,
heatmap: HeatmapStyleLayer,
hillshade: HillshadeStyleLayer,
fill: FillStyleLayer,
'fill-extrusion': FillExtrusionStyleLayer,
line: LineStyleLayer,
symbol: SymbolStyleLayer,
background: BackgroundStyleLayer,
raster: RasterStyleLayer
};
function createStyleLayer(layer ) {
return new subclasses[layer.type](layer);
}
/**
* Create a new ShelfPack bin allocator.
*
* Uses the Shelf Best Height Fit algorithm from
* http://clb.demon.fi/files/RectangleBinPack.pdf
*
* @class ShelfPack
* @param {number} [w=64] Initial width of the sprite
* @param {number} [h=64] Initial width of the sprite
* @param {Object} [options]
* @param {boolean} [options.autoResize=false] If `true`, the sprite will automatically grow
* @example
* var sprite = new ShelfPack(64, 64, { autoResize: false });
*/
function ShelfPack(w, h, options) {
options = options || {};
this.w = w || 64;
this.h = h || 64;
this.autoResize = !!options.autoResize;
this.shelves = [];
this.freebins = [];
this.stats = {};
this.bins = {};
this.maxId = 0;
}
/**
* Batch pack multiple bins into the sprite.
*
* @param {Object[]} bins Array of requested bins - each object should have `width`, `height` (or `w`, `h`) properties
* @param {number} bins[].w Requested bin width
* @param {number} bins[].h Requested bin height
* @param {Object} [options]
* @param {boolean} [options.inPlace=false] If `true`, the supplied bin objects will be updated inplace with `x` and `y` properties
* @returns {Bin[]} Array of allocated Bins - each Bin is an object with `id`, `x`, `y`, `w`, `h` properties
* @example
* var bins = [
* { id: 1, w: 12, h: 12 },
* { id: 2, w: 12, h: 16 },
* { id: 3, w: 12, h: 24 }
* ];
* var results = sprite.pack(bins, { inPlace: false });
*/
ShelfPack.prototype.pack = function(bins, options) {
var this$1 = this;
bins = [].concat(bins);
options = options || {};
var results = [],
w, h, id, allocation;
for (var i = 0; i < bins.length; i++) {
w = bins[i].w || bins[i].width;
h = bins[i].h || bins[i].height;
id = bins[i].id;
if (w && h) {
allocation = this$1.packOne(w, h, id);
if (!allocation) {
continue;
}
if (options.inPlace) {
bins[i].x = allocation.x;
bins[i].y = allocation.y;
bins[i].id = allocation.id;
}
results.push(allocation);
}
}
this.shrink();
return results;
};
/**
* Pack a single bin into the sprite.
*
* Each bin will have a unique identitifer.
* If no identifier is supplied in the `id` parameter, one will be created.
* Note: The supplied `id` is used as an object index, so numeric values are fastest!
*
* Bins are automatically refcounted (i.e. a newly packed Bin will have a refcount of 1).
* When a bin is no longer needed, use the `ShelfPack.unref` function to mark it
* as unused. When a Bin's refcount decrements to 0, the Bin will be marked
* as free and its space may be reused by the packing code.
*
* @param {number} w Width of the bin to allocate
* @param {number} h Height of the bin to allocate
* @param {number|string} [id] Unique identifier for this bin, (if unsupplied, assume it's a new bin and create an id)
* @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties, or `null` if allocation failed
* @example
* var results = sprite.packOne(12, 16, 'a');
*/
ShelfPack.prototype.packOne = function(w, h, id) {
var this$1 = this;
var best = { freebin: -1, shelf: -1, waste: Infinity },
y = 0,
bin, shelf, waste, i;
// if id was supplied, attempt a lookup..
if (typeof id === 'string' || typeof id === 'number') {
bin = this.getBin(id);
if (bin) { // we packed this bin already
this.ref(bin);
return bin;
}
if (typeof id === 'number') {
this.maxId = Math.max(id, this.maxId);
}
} else {
id = ++this.maxId;
}
// First try to reuse a free bin..
for (i = 0; i < this.freebins.length; i++) {
bin = this$1.freebins[i];
// exactly the right height and width, use it..
if (h === bin.maxh && w === bin.maxw) {
return this$1.allocFreebin(i, w, h, id);
}
// not enough height or width, skip it..
if (h > bin.maxh || w > bin.maxw) {
continue;
}
// extra height or width, minimize wasted area..
if (h <= bin.maxh && w <= bin.maxw) {
waste = (bin.maxw * bin.maxh) - (w * h);
if (waste < best.waste) {
best.waste = waste;
best.freebin = i;
}
}
}
// Next find the best shelf..
for (i = 0; i < this.shelves.length; i++) {
shelf = this$1.shelves[i];
y += shelf.h;
// not enough width on this shelf, skip it..
if (w > shelf.free) {
continue;
}
// exactly the right height, pack it..
if (h === shelf.h) {
return this$1.allocShelf(i, w, h, id);
}
// not enough height, skip it..
if (h > shelf.h) {
continue;
}
// extra height, minimize wasted area..
if (h < shelf.h) {
waste = (shelf.h - h) * w;
if (waste < best.waste) {
best.freebin = -1;
best.waste = waste;
best.shelf = i;
}
}
}
if (best.freebin !== -1) {
return this.allocFreebin(best.freebin, w, h, id);
}
if (best.shelf !== -1) {
return this.allocShelf(best.shelf, w, h, id);
}
// No free bins or shelves.. add shelf..
if (h <= (this.h - y) && w <= this.w) {
shelf = new Shelf(y, this.w, h);
return this.allocShelf(this.shelves.push(shelf) - 1, w, h, id);
}
// No room for more shelves..
// If `autoResize` option is set, grow the sprite as follows:
// * double whichever sprite dimension is smaller (`w1` or `h1`)
// * if sprite dimensions are equal, grow width before height
// * accomodate very large bin requests (big `w` or `h`)
if (this.autoResize) {
var h1, h2, w1, w2;
h1 = h2 = this.h;
w1 = w2 = this.w;
if (w1 <= h1 || w > w1) { // grow width..
w2 = Math.max(w, w1) * 2;
}
if (h1 < w1 || h > h1) { // grow height..
h2 = Math.max(h, h1) * 2;
}
this.resize(w2, h2);
return this.packOne(w, h, id); // retry
}
return null;
};
/**
* Called by packOne() to allocate a bin by reusing an existing freebin
*
* @private
* @param {number} index Index into the `this.freebins` array
* @param {number} w Width of the bin to allocate
* @param {number} h Height of the bin to allocate
* @param {number|string} id Unique identifier for this bin
* @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties
* @example
* var bin = sprite.allocFreebin(0, 12, 16, 'a');
*/
ShelfPack.prototype.allocFreebin = function (index, w, h, id) {
var bin = this.freebins.splice(index, 1)[0];
bin.id = id;
bin.w = w;
bin.h = h;
bin.refcount = 0;
this.bins[id] = bin;
this.ref(bin);
return bin;
};
/**
* Called by `packOne() to allocate bin on an existing shelf
*
* @private
* @param {number} index Index into the `this.shelves` array
* @param {number} w Width of the bin to allocate
* @param {number} h Height of the bin to allocate
* @param {number|string} id Unique identifier for this bin
* @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties
* @example
* var results = sprite.allocShelf(0, 12, 16, 'a');
*/
ShelfPack.prototype.allocShelf = function(index, w, h, id) {
var shelf = this.shelves[index];
var bin = shelf.alloc(w, h, id);
this.bins[id] = bin;
this.ref(bin);
return bin;
};
/**
* Shrink the width/height of the sprite to the bare minimum.
* Since shelf-pack doubles first width, then height when running out of shelf space
* this can result in fairly large unused space both in width and height if that happens
* towards the end of bin packing.
*/
ShelfPack.prototype.shrink = function() {
var this$1 = this;
if (this.shelves.length > 0) {
var w2 = 0;
var h2 = 0;
for (var j = 0; j < this.shelves.length; j++) {
var shelf = this$1.shelves[j];
h2 += shelf.h;
w2 = Math.max(shelf.w - shelf.free, w2);
}
this.resize(w2, h2);
}
};
/**
* Return a packed bin given its id, or undefined if the id is not found
*
* @param {number|string} id Unique identifier for this bin,
* @returns {Bin} The requested bin, or undefined if not yet packed
* @example
* var b = sprite.getBin('a');
*/
ShelfPack.prototype.getBin = function(id) {
return this.bins[id];
};
/**
* Increment the ref count of a bin and update statistics.
*
* @param {Bin} bin Bin instance
* @returns {number} New refcount of the bin
* @example
* var bin = sprite.getBin('a');
* sprite.ref(bin);
*/
ShelfPack.prototype.ref = function(bin) {
if (++bin.refcount === 1) { // a new Bin.. record height in stats historgram..
var h = bin.h;
this.stats[h] = (this.stats[h] | 0) + 1;
}
return bin.refcount;
};
/**
* Decrement the ref count of a bin and update statistics.
* The bin will be automatically marked as free space once the refcount reaches 0.
*
* @param {Bin} bin Bin instance
* @returns {number} New refcount of the bin
* @example
* var bin = sprite.getBin('a');
* sprite.unref(bin);
*/
ShelfPack.prototype.unref = function(bin) {
if (bin.refcount === 0) {
return 0;
}
if (--bin.refcount === 0) {
this.stats[bin.h]--;
delete this.bins[bin.id];
this.freebins.push(bin);
}
return bin.refcount;
};
/**
* Clear the sprite. Resets everything and resets statistics.
*
* @example
* sprite.clear();
*/
ShelfPack.prototype.clear = function() {
this.shelves = [];
this.freebins = [];
this.stats = {};
this.bins = {};
this.maxId = 0;
};
/**
* Resize the sprite.
*
* @param {number} w Requested new sprite width
* @param {number} h Requested new sprite height
* @returns {boolean} `true` if resize succeeded, `false` if failed
* @example
* sprite.resize(256, 256);
*/
ShelfPack.prototype.resize = function(w, h) {
var this$1 = this;
this.w = w;
this.h = h;
for (var i = 0; i < this.shelves.length; i++) {
this$1.shelves[i].resize(w);
}
return true;
};
/**
* Create a new Shelf.
*
* @private
* @class Shelf
* @param {number} y Top coordinate of the new shelf
* @param {number} w Width of the new shelf
* @param {number} h Height of the new shelf
* @example
* var shelf = new Shelf(64, 512, 24);
*/
function Shelf(y, w, h) {
this.x = 0;
this.y = y;
this.w = this.free = w;
this.h = h;
}
/**
* Allocate a single bin into the shelf.
*
* @private
* @param {number} w Width of the bin to allocate
* @param {number} h Height of the bin to allocate
* @param {number|string} id Unique id of the bin to allocate
* @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties, or `null` if allocation failed
* @example
* shelf.alloc(12, 16, 'a');
*/
Shelf.prototype.alloc = function(w, h, id) {
if (w > this.free || h > this.h) {
return null;
}
var x = this.x;
this.x += w;
this.free -= w;
return new Bin(id, x, this.y, w, h, w, this.h);
};
/**
* Resize the shelf.
*
* @private
* @param {number} w Requested new width of the shelf
* @returns {boolean} true
* @example
* shelf.resize(512);
*/
Shelf.prototype.resize = function(w) {
this.free += (w - this.w);
this.w = w;
return true;
};
/**
* Create a new Bin object.
*
* @class Bin
* @param {number|string} id Unique id of the bin
* @param {number} x Left coordinate of the bin
* @param {number} y Top coordinate of the bin
* @param {number} w Width of the bin
* @param {number} h Height of the bin
* @param {number} [maxw] Max width of the bin (defaults to `w` if not provided)
* @param {number} [maxh] Max height of the bin (defaults to `h` if not provided)
* @example
* var bin = new Bin('a', 0, 0, 12, 16);
*/
function Bin(id, x, y, w, h, maxw, maxh) {
this.id = id;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.maxw = maxw || w;
this.maxh = maxh || h;
this.refcount = 0;
}
//
var padding = 1;
var ImagePosition = function ImagePosition(paddedRect , ref ) {
var pixelRatio = ref.pixelRatio;
this.paddedRect = paddedRect;
this.pixelRatio = pixelRatio;
};
var prototypeAccessors = { tl: { configurable: true },br: { configurable: true },displaySize: { configurable: true } };
prototypeAccessors.tl.get = function () {
return [
this.paddedRect.x + padding,
this.paddedRect.y + padding
];
};
prototypeAccessors.br.get = function () {
return [
this.paddedRect.x + this.paddedRect.w - padding,
this.paddedRect.y + this.paddedRect.h - padding
];
};
prototypeAccessors.displaySize.get = function () {
return [
(this.paddedRect.w - padding * 2) / this.pixelRatio,
(this.paddedRect.h - padding * 2) / this.pixelRatio
];
};
Object.defineProperties( ImagePosition.prototype, prototypeAccessors );
var ImageAtlas = function ImageAtlas(images ) {
var positions = {};
var pack = new ShelfPack(0, 0, {autoResize: true});
var bins = [];
for (var id in images) {
var src = images[id];
var bin = {
x: 0,
y: 0,
w: src.data.width + 2 * padding,
h: src.data.height + 2 * padding,
};
bins.push(bin);
positions[id] = new ImagePosition(bin, src);
}
pack.pack(bins, {inPlace: true});
var image = new RGBAImage({width: pack.w, height: pack.h});
for (var id$1 in images) {
var src$1 = images[id$1];
var bin$1 = positions[id$1].paddedRect;
RGBAImage.copy(src$1.data, image, {x: 0, y: 0}, {x: bin$1.x + padding, y: bin$1.y + padding}, src$1.data);
}
this.image = image;
this.positions = positions;
};
register('ImagePosition', ImagePosition);
register('ImageAtlas', ImageAtlas);
//
var HTMLImageElement = self.HTMLImageElement;
var HTMLCanvasElement = self.HTMLCanvasElement;
var HTMLVideoElement = self.HTMLVideoElement;
var ImageData$1 = self.ImageData;
var Texture = function Texture(context , image , format , options ) {
this.context = context;
this.format = format;
this.texture = context.gl.createTexture();
this.update(image, options);
};
Texture.prototype.update = function update (image , options ) {
var width = image.width;
var height = image.height;
var resize = !this.size || this.size[0] !== width || this.size[1] !== height;
var ref = this;
var context = ref.context;
var gl = context.gl;
this.useMipmap = Boolean(options && options.useMipmap);
gl.bindTexture(gl.TEXTURE_2D, this.texture);
if (resize) {
this.size = [width, height];
context.pixelStoreUnpack.set(1);
if (this.format === gl.RGBA && (!options || options.premultiply !== false)) {
context.pixelStoreUnpackPremultiplyAlpha.set(true);
}
if (image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof HTMLVideoElement || image instanceof ImageData$1) {
gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, gl.UNSIGNED_BYTE, image);
} else {
gl.texImage2D(gl.TEXTURE_2D, 0, this.format, width, height, 0, this.format, gl.UNSIGNED_BYTE, image.data);
}
} else {
if (image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof HTMLVideoElement || image instanceof ImageData$1) {
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image);
} else {
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, image.data);
}
}
if (this.useMipmap && this.isSizePowerOfTwo()) {
gl.generateMipmap(gl.TEXTURE_2D);
}
};
Texture.prototype.bind = function bind (filter , wrap , minFilter ) {
var ref = this;
var context = ref.context;
var gl = context.gl;
gl.bindTexture(gl.TEXTURE_2D, this.texture);
if (minFilter === gl.LINEAR_MIPMAP_NEAREST && !this.isSizePowerOfTwo()) {
minFilter = gl.LINEAR;
}
if (filter !== this.filter) {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter || filter);
this.filter = filter;
}
if (wrap !== this.wrap) {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);
this.wrap = wrap;
}
};
Texture.prototype.isSizePowerOfTwo = function isSizePowerOfTwo () {
return this.size[0] === this.size[1] && (Math.log(this.size[0]) / Math.LN2) % 1 === 0;
};
Texture.prototype.destroy = function destroy () {
var ref = this.context;
var gl = ref.gl;
gl.deleteTexture(this.texture);
this.texture = (null );
};
var read = function (buffer, offset, isLE, mLen, nBytes) {
var e, m;
var eLen = nBytes * 8 - mLen - 1;
var eMax = (1 << eLen) - 1;
var eBias = eMax >> 1;
var nBits = -7;
var i = isLE ? (nBytes - 1) : 0;
var d = isLE ? -1 : 1;
var s = buffer[offset + i];
i += d;
e = s & ((1 << (-nBits)) - 1);
s >>= (-nBits);
nBits += eLen;
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
m = e & ((1 << (-nBits)) - 1);
e >>= (-nBits);
nBits += mLen;
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
if (e === 0) {
e = 1 - eBias;
} else if (e === eMax) {
return m ? NaN : ((s ? -1 : 1) * Infinity)
} else {
m = m + Math.pow(2, mLen);
e = e - eBias;
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
};
var write = function (buffer, value, offset, isLE, mLen, nBytes) {
var e, m, c;
var eLen = nBytes * 8 - mLen - 1;
var eMax = (1 << eLen) - 1;
var eBias = eMax >> 1;
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0);
var i = isLE ? 0 : (nBytes - 1);
var d = isLE ? 1 : -1;
var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
value = Math.abs(value);
if (isNaN(value) || value === Infinity) {
m = isNaN(value) ? 1 : 0;
e = eMax;
} else {
e = Math.floor(Math.log(value) / Math.LN2);
if (value * (c = Math.pow(2, -e)) < 1) {
e--;
c *= 2;
}
if (e + eBias >= 1) {
value += rt / c;
} else {
value += rt * Math.pow(2, 1 - eBias);
}
if (value * c >= 2) {
e++;
c /= 2;
}
if (e + eBias >= eMax) {
m = 0;
e = eMax;
} else if (e + eBias >= 1) {
m = (value * c - 1) * Math.pow(2, mLen);
e = e + eBias;
} else {
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
e = 0;
}
}
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
e = (e << mLen) | m;
eLen += mLen;
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
buffer[offset + i - d] |= s * 128;
};
var ieee754 = {
read: read,
write: write
};
'use strict';
var pbf = Pbf;
function Pbf(buf) {
this.buf = ArrayBuffer.isView && ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf || 0);
this.pos = 0;
this.type = 0;
this.length = this.buf.length;
}
Pbf.Varint = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum
Pbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64
Pbf.Bytes = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields
Pbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32
var SHIFT_LEFT_32 = (1 << 16) * (1 << 16),
SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;
Pbf.prototype = {
destroy: function() {
this.buf = null;
},
// === READING =================================================================
readFields: function(readField, result, end) {
var this$1 = this;
end = end || this.length;
while (this.pos < end) {
var val = this$1.readVarint(),
tag = val >> 3,
startPos = this$1.pos;
this$1.type = val & 0x7;
readField(tag, result, this$1);
if (this$1.pos === startPos) { this$1.skip(val); }
}
return result;
},
readMessage: function(readField, result) {
return this.readFields(readField, result, this.readVarint() + this.pos);
},
readFixed32: function() {
var val = readUInt32(this.buf, this.pos);
this.pos += 4;
return val;
},
readSFixed32: function() {
var val = readInt32(this.buf, this.pos);
this.pos += 4;
return val;
},
// 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
readFixed64: function() {
var val = readUInt32(this.buf, this.pos) + readUInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
this.pos += 8;
return val;
},
readSFixed64: function() {
var val = readUInt32(this.buf, this.pos) + readInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
this.pos += 8;
return val;
},
readFloat: function() {
var val = ieee754.read(this.buf, this.pos, true, 23, 4);
this.pos += 4;
return val;
},
readDouble: function() {
var val = ieee754.read(this.buf, this.pos, true, 52, 8);
this.pos += 8;
return val;
},
readVarint: function(isSigned) {
var buf = this.buf,
val, b;
b = buf[this.pos++]; val = b & 0x7f; if (b < 0x80) { return val; }
b = buf[this.pos++]; val |= (b & 0x7f) << 7; if (b < 0x80) { return val; }
b = buf[this.pos++]; val |= (b & 0x7f) << 14; if (b < 0x80) { return val; }
b = buf[this.pos++]; val |= (b & 0x7f) << 21; if (b < 0x80) { return val; }
b = buf[this.pos]; val |= (b & 0x0f) << 28;
return readVarintRemainder(val, isSigned, this);
},
readVarint64: function() { // for compatibility with v2.0.1
return this.readVarint(true);
},
readSVarint: function() {
var num = this.readVarint();
return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding
},
readBoolean: function() {
return Boolean(this.readVarint());
},
readString: function() {
var end = this.readVarint() + this.pos,
str = readUtf8(this.buf, this.pos, end);
this.pos = end;
return str;
},
readBytes: function() {
var end = this.readVarint() + this.pos,
buffer = this.buf.subarray(this.pos, end);
this.pos = end;
return buffer;
},
// verbose for performance reasons; doesn't affect gzipped size
readPackedVarint: function(arr, isSigned) {
var this$1 = this;
var end = readPackedEnd(this);
arr = arr || [];
while (this.pos < end) { arr.push(this$1.readVarint(isSigned)); }
return arr;
},
readPackedSVarint: function(arr) {
var this$1 = this;
var end = readPackedEnd(this);
arr = arr || [];
while (this.pos < end) { arr.push(this$1.readSVarint()); }
return arr;
},
readPackedBoolean: function(arr) {
var this$1 = this;
var end = readPackedEnd(this);
arr = arr || [];
while (this.pos < end) { arr.push(this$1.readBoolean()); }
return arr;
},
readPackedFloat: function(arr) {
var this$1 = this;
var end = readPackedEnd(this);
arr = arr || [];
while (this.pos < end) { arr.push(this$1.readFloat()); }
return arr;
},
readPackedDouble: function(arr) {
var this$1 = this;
var end = readPackedEnd(this);
arr = arr || [];
while (this.pos < end) { arr.push(this$1.readDouble()); }
return arr;
},
readPackedFixed32: function(arr) {
var this$1 = this;
var end = readPackedEnd(this);
arr = arr || [];
while (this.pos < end) { arr.push(this$1.readFixed32()); }
return arr;
},
readPackedSFixed32: function(arr) {
var this$1 = this;
var end = readPackedEnd(this);
arr = arr || [];
while (this.pos < end) { arr.push(this$1.readSFixed32()); }
return arr;
},
readPackedFixed64: function(arr) {
var this$1 = this;
var end = readPackedEnd(this);
arr = arr || [];
while (this.pos < end) { arr.push(this$1.readFixed64()); }
return arr;
},
readPackedSFixed64: function(arr) {
var this$1 = this;
var end = readPackedEnd(this);
arr = arr || [];
while (this.pos < end) { arr.push(this$1.readSFixed64()); }
return arr;
},
skip: function(val) {
var type = val & 0x7;
if (type === Pbf.Varint) { while (this.buf[this.pos++] > 0x7f) {} }
else if (type === Pbf.Bytes) { this.pos = this.readVarint() + this.pos; }
else if (type === Pbf.Fixed32) { this.pos += 4; }
else if (type === Pbf.Fixed64) { this.pos += 8; }
else { throw new Error('Unimplemented type: ' + type); }
},
// === WRITING =================================================================
writeTag: function(tag, type) {
this.writeVarint((tag << 3) | type);
},
realloc: function(min) {
var length = this.length || 16;
while (length < this.pos + min) { length *= 2; }
if (length !== this.length) {
var buf = new Uint8Array(length);
buf.set(this.buf);
this.buf = buf;
this.length = length;
}
},
finish: function() {
this.length = this.pos;
this.pos = 0;
return this.buf.subarray(0, this.length);
},
writeFixed32: function(val) {
this.realloc(4);
writeInt32(this.buf, val, this.pos);
this.pos += 4;
},
writeSFixed32: function(val) {
this.realloc(4);
writeInt32(this.buf, val, this.pos);
this.pos += 4;
},
writeFixed64: function(val) {
this.realloc(8);
writeInt32(this.buf, val & -1, this.pos);
writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
this.pos += 8;
},
writeSFixed64: function(val) {
this.realloc(8);
writeInt32(this.buf, val & -1, this.pos);
writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
this.pos += 8;
},
writeVarint: function(val) {
val = +val || 0;
if (val > 0xfffffff || val < 0) {
writeBigVarint(val, this);
return;
}
this.realloc(4);
this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) { return; }
this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) { return; }
this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) { return; }
this.buf[this.pos++] = (val >>> 7) & 0x7f;
},
writeSVarint: function(val) {
this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
},
writeBoolean: function(val) {
this.writeVarint(Boolean(val));
},
writeString: function(str) {
str = String(str);
this.realloc(str.length * 4);
this.pos++; // reserve 1 byte for short string length
var startPos = this.pos;
// write the string directly to the buffer and see how much was written
this.pos = writeUtf8(this.buf, str, this.pos);
var len = this.pos - startPos;
if (len >= 0x80) { makeRoomForExtraLength(startPos, len, this); }
// finally, write the message length in the reserved place and restore the position
this.pos = startPos - 1;
this.writeVarint(len);
this.pos += len;
},
writeFloat: function(val) {
this.realloc(4);
ieee754.write(this.buf, val, this.pos, true, 23, 4);
this.pos += 4;
},
writeDouble: function(val) {
this.realloc(8);
ieee754.write(this.buf, val, this.pos, true, 52, 8);
this.pos += 8;
},
writeBytes: function(buffer) {
var this$1 = this;
var len = buffer.length;
this.writeVarint(len);
this.realloc(len);
for (var i = 0; i < len; i++) { this$1.buf[this$1.pos++] = buffer[i]; }
},
writeRawMessage: function(fn, obj) {
this.pos++; // reserve 1 byte for short message length
// write the message directly to the buffer and see how much was written
var startPos = this.pos;
fn(obj, this);
var len = this.pos - startPos;
if (len >= 0x80) { makeRoomForExtraLength(startPos, len, this); }
// finally, write the message length in the reserved place and restore the position
this.pos = startPos - 1;
this.writeVarint(len);
this.pos += len;
},
writeMessage: function(tag, fn, obj) {
this.writeTag(tag, Pbf.Bytes);
this.writeRawMessage(fn, obj);
},
writePackedVarint: function(tag, arr) { this.writeMessage(tag, writePackedVarint, arr); },
writePackedSVarint: function(tag, arr) { this.writeMessage(tag, writePackedSVarint, arr); },
writePackedBoolean: function(tag, arr) { this.writeMessage(tag, writePackedBoolean, arr); },
writePackedFloat: function(tag, arr) { this.writeMessage(tag, writePackedFloat, arr); },
writePackedDouble: function(tag, arr) { this.writeMessage(tag, writePackedDouble, arr); },
writePackedFixed32: function(tag, arr) { this.writeMessage(tag, writePackedFixed32, arr); },
writePackedSFixed32: function(tag, arr) { this.writeMessage(tag, writePackedSFixed32, arr); },
writePackedFixed64: function(tag, arr) { this.writeMessage(tag, writePackedFixed64, arr); },
writePackedSFixed64: function(tag, arr) { this.writeMessage(tag, writePackedSFixed64, arr); },
writeBytesField: function(tag, buffer) {
this.writeTag(tag, Pbf.Bytes);
this.writeBytes(buffer);
},
writeFixed32Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed32);
this.writeFixed32(val);
},
writeSFixed32Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed32);
this.writeSFixed32(val);
},
writeFixed64Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed64);
this.writeFixed64(val);
},
writeSFixed64Field: function(tag, val) {
this.writeTag(tag, Pbf.Fixed64);
this.writeSFixed64(val);
},
writeVarintField: function(tag, val) {
this.writeTag(tag, Pbf.Varint);
this.writeVarint(val);
},
writeSVarintField: function(tag, val) {
this.writeTag(tag, Pbf.Varint);
this.writeSVarint(val);
},
writeStringField: function(tag, str) {
this.writeTag(tag, Pbf.Bytes);
this.writeString(str);
},
writeFloatField: function(tag, val) {
this.writeTag(tag, Pbf.Fixed32);
this.writeFloat(val);
},
writeDoubleField: function(tag, val) {
this.writeTag(tag, Pbf.Fixed64);
this.writeDouble(val);
},
writeBooleanField: function(tag, val) {
this.writeVarintField(tag, Boolean(val));
}
};
function readVarintRemainder(l, s, p) {
var buf = p.buf,
h, b;
b = buf[p.pos++]; h = (b & 0x70) >> 4; if (b < 0x80) { return toNum(l, h, s); }
b = buf[p.pos++]; h |= (b & 0x7f) << 3; if (b < 0x80) { return toNum(l, h, s); }
b = buf[p.pos++]; h |= (b & 0x7f) << 10; if (b < 0x80) { return toNum(l, h, s); }
b = buf[p.pos++]; h |= (b & 0x7f) << 17; if (b < 0x80) { return toNum(l, h, s); }
b = buf[p.pos++]; h |= (b & 0x7f) << 24; if (b < 0x80) { return toNum(l, h, s); }
b = buf[p.pos++]; h |= (b & 0x01) << 31; if (b < 0x80) { return toNum(l, h, s); }
throw new Error('Expected varint not more than 10 bytes');
}
function readPackedEnd(pbf) {
return pbf.type === Pbf.Bytes ?
pbf.readVarint() + pbf.pos : pbf.pos + 1;
}
function toNum(low, high, isSigned) {
if (isSigned) {
return high * 0x100000000 + (low >>> 0);
}
return ((high >>> 0) * 0x100000000) + (low >>> 0);
}
function writeBigVarint(val, pbf) {
var low, high;
if (val >= 0) {
low = (val % 0x100000000) | 0;
high = (val / 0x100000000) | 0;
} else {
low = ~(-val % 0x100000000);
high = ~(-val / 0x100000000);
if (low ^ 0xffffffff) {
low = (low + 1) | 0;
} else {
low = 0;
high = (high + 1) | 0;
}
}
if (val >= 0x10000000000000000 || val < -0x10000000000000000) {
throw new Error('Given varint doesn\'t fit into 10 bytes');
}
pbf.realloc(10);
writeBigVarintLow(low, high, pbf);
writeBigVarintHigh(high, pbf);
}
function writeBigVarintLow(low, high, pbf) {
pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
pbf.buf[pbf.pos] = low & 0x7f;
}
function writeBigVarintHigh(high, pbf) {
var lsb = (high & 0x07) << 4;
pbf.buf[pbf.pos++] |= lsb | ((high >>>= 3) ? 0x80 : 0); if (!high) { return; }
pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) { return; }
pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) { return; }
pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) { return; }
pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) { return; }
pbf.buf[pbf.pos++] = high & 0x7f;
}
function makeRoomForExtraLength(startPos, len, pbf) {
var extraLen =
len <= 0x3fff ? 1 :
len <= 0x1fffff ? 2 :
len <= 0xfffffff ? 3 : Math.ceil(Math.log(len) / (Math.LN2 * 7));
// if 1 byte isn't enough for encoding message length, shift the data to the right
pbf.realloc(extraLen);
for (var i = pbf.pos - 1; i >= startPos; i--) { pbf.buf[i + extraLen] = pbf.buf[i]; }
}
function writePackedVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) { pbf.writeVarint(arr[i]); } }
function writePackedSVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) { pbf.writeSVarint(arr[i]); } }
function writePackedFloat(arr, pbf) { for (var i = 0; i < arr.length; i++) { pbf.writeFloat(arr[i]); } }
function writePackedDouble(arr, pbf) { for (var i = 0; i < arr.length; i++) { pbf.writeDouble(arr[i]); } }
function writePackedBoolean(arr, pbf) { for (var i = 0; i < arr.length; i++) { pbf.writeBoolean(arr[i]); } }
function writePackedFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) { pbf.writeFixed32(arr[i]); } }
function writePackedSFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) { pbf.writeSFixed32(arr[i]); } }
function writePackedFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) { pbf.writeFixed64(arr[i]); } }
function writePackedSFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) { pbf.writeSFixed64(arr[i]); } }
// Buffer code below from https://github.com/feross/buffer, MIT-licensed
function readUInt32(buf, pos) {
return ((buf[pos]) |
(buf[pos + 1] << 8) |
(buf[pos + 2] << 16)) +
(buf[pos + 3] * 0x1000000);
}
function writeInt32(buf, val, pos) {
buf[pos] = val;
buf[pos + 1] = (val >>> 8);
buf[pos + 2] = (val >>> 16);
buf[pos + 3] = (val >>> 24);
}
function readInt32(buf, pos) {
return ((buf[pos]) |
(buf[pos + 1] << 8) |
(buf[pos + 2] << 16)) +
(buf[pos + 3] << 24);
}
function readUtf8(buf, pos, end) {
var str = '';
var i = pos;
while (i < end) {
var b0 = buf[i];
var c = null; // codepoint
var bytesPerSequence =
b0 > 0xEF ? 4 :
b0 > 0xDF ? 3 :
b0 > 0xBF ? 2 : 1;
if (i + bytesPerSequence > end) { break; }
var b1, b2, b3;
if (bytesPerSequence === 1) {
if (b0 < 0x80) {
c = b0;
}
} else if (bytesPerSequence === 2) {
b1 = buf[i + 1];
if ((b1 & 0xC0) === 0x80) {
c = (b0 & 0x1F) << 0x6 | (b1 & 0x3F);
if (c <= 0x7F) {
c = null;
}
}
} else if (bytesPerSequence === 3) {
b1 = buf[i + 1];
b2 = buf[i + 2];
if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80) {
c = (b0 & 0xF) << 0xC | (b1 & 0x3F) << 0x6 | (b2 & 0x3F);
if (c <= 0x7FF || (c >= 0xD800 && c <= 0xDFFF)) {
c = null;
}
}
} else if (bytesPerSequence === 4) {
b1 = buf[i + 1];
b2 = buf[i + 2];
b3 = buf[i + 3];
if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {
c = (b0 & 0xF) << 0x12 | (b1 & 0x3F) << 0xC | (b2 & 0x3F) << 0x6 | (b3 & 0x3F);
if (c <= 0xFFFF || c >= 0x110000) {
c = null;
}
}
}
if (c === null) {
c = 0xFFFD;
bytesPerSequence = 1;
} else if (c > 0xFFFF) {
c -= 0x10000;
str += String.fromCharCode(c >>> 10 & 0x3FF | 0xD800);
c = 0xDC00 | c & 0x3FF;
}
str += String.fromCharCode(c);
i += bytesPerSequence;
}
return str;
}
function writeUtf8(buf, str, pos) {
for (var i = 0, c, lead; i < str.length; i++) {
c = str.charCodeAt(i); // code point
if (c > 0xD7FF && c < 0xE000) {
if (lead) {
if (c < 0xDC00) {
buf[pos++] = 0xEF;
buf[pos++] = 0xBF;
buf[pos++] = 0xBD;
lead = c;
continue;
} else {
c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;
lead = null;
}
} else {
if (c > 0xDBFF || (i + 1 === str.length)) {
buf[pos++] = 0xEF;
buf[pos++] = 0xBF;
buf[pos++] = 0xBD;
} else {
lead = c;
}
continue;
}
} else if (lead) {
buf[pos++] = 0xEF;
buf[pos++] = 0xBF;
buf[pos++] = 0xBD;
lead = null;
}
if (c < 0x80) {
buf[pos++] = c;
} else {
if (c < 0x800) {
buf[pos++] = c >> 0x6 | 0xC0;
} else {
if (c < 0x10000) {
buf[pos++] = c >> 0xC | 0xE0;
} else {
buf[pos++] = c >> 0x12 | 0xF0;
buf[pos++] = c >> 0xC & 0x3F | 0x80;
}
buf[pos++] = c >> 0x6 & 0x3F | 0x80;
}
buf[pos++] = c & 0x3F | 0x80;
}
}
return pos;
}
//
var border = 3;
function readFontstacks(tag , glyphs , pbf$$1 ) {
if (tag === 1) {
pbf$$1.readMessage(readFontstack, glyphs);
}
}
function readFontstack(tag , glyphs , pbf$$1 ) {
if (tag === 3) {
var ref = pbf$$1.readMessage(readGlyph, {});
var id = ref.id;
var bitmap = ref.bitmap;
var width = ref.width;
var height = ref.height;
var left = ref.left;
var top = ref.top;
var advance = ref.advance;
glyphs.push({
id: id,
bitmap: new AlphaImage({
width: width + 2 * border,
height: height + 2 * border
}, bitmap),
metrics: {width: width, height: height, left: left, top: top, advance: advance}
});
}
}
function readGlyph(tag , glyph , pbf$$1 ) {
if (tag === 1) { glyph.id = pbf$$1.readVarint(); }
else if (tag === 2) { glyph.bitmap = pbf$$1.readBytes(); }
else if (tag === 3) { glyph.width = pbf$$1.readVarint(); }
else if (tag === 4) { glyph.height = pbf$$1.readVarint(); }
else if (tag === 5) { glyph.left = pbf$$1.readSVarint(); }
else if (tag === 6) { glyph.top = pbf$$1.readSVarint(); }
else if (tag === 7) { glyph.advance = pbf$$1.readVarint(); }
}
function parseGlyphPBF (data ) {
return new pbf(data).readFields(readFontstacks, []);
}
var GLYPH_PBF_BORDER = border;
//
/**
* An implementation of the [Actor design pattern](http://en.wikipedia.org/wiki/Actor_model)
* that maintains the relationship between asynchronous tasks and the objects
* that spin them off - in this case, tasks like parsing parts of styles,
* owned by the styles
*
* @param {WebWorker} target
* @param {WebWorker} parent
* @param {string|number} mapId A unique identifier for the Map instance using this Actor.
* @private
*/
var Actor = function Actor(target , parent , mapId ) {
this.target = target;
this.parent = parent;
this.mapId = mapId;
this.callbacks = {};
this.callbackID = 0;
bindAll(['receive'], this);
this.target.addEventListener('message', this.receive, false);
};
/**
* Sends a message from a main-thread map to a Worker or from a Worker back to
* a main-thread map instance.
*
* @param type The name of the target method to invoke or '[source-type].[source-name].name' for a method on a WorkerSource.
* @param targetMapId A particular mapId to which to send this message.
* @private
*/
Actor.prototype.send = function send (type , data , callback , targetMapId ) {
var id = callback ? ((this.mapId) + ":" + (this.callbackID++)) : null;
if (callback) { this.callbacks[id] = callback; }
var buffers = [];
this.target.postMessage({
targetMapId: targetMapId,
sourceMapId: this.mapId,
type: type,
id: String(id),
data: serialize(data, buffers)
}, buffers);
};
Actor.prototype.receive = function receive (message ) {
var this$1 = this;
var data = message.data,
id = data.id;
var callback;
if (data.targetMapId && this.mapId !== data.targetMapId)
{ return; }
var done = function (err, data) {
var buffers = [];
this$1.target.postMessage({
sourceMapId: this$1.mapId,
type: '<response>',
id: String(id),
error: err ? serialize(err) : null,
data: serialize(data, buffers)
}, buffers);
};
if (data.type === '<response>') {
callback = this.callbacks[data.id];
delete this.callbacks[data.id];
if (callback && data.error) {
callback(deserialize(data.error));
} else if (callback) {
callback(null, deserialize(data.data));
}
} else if (typeof data.id !== 'undefined' && this.parent[data.type]) {
// data.type == 'loadTile', 'removeTile', etc.
this.parent[data.type](data.sourceMapId, deserialize(data.data), done);
} else if (typeof data.id !== 'undefined' && this.parent.getWorkerSource) {
// data.type == sourcetype.method
var keys = data.type.split('.');
var params = (deserialize(data.data) );
var workerSource = (this.parent ).getWorkerSource(data.sourceMapId, keys[0], params.source);
workerSource[keys[1]](params, done);
} else {
this.parent[data.type](deserialize(data.data));
}
};
Actor.prototype.remove = function remove () {
this.target.removeEventListener('message', this.receive, false);
};
/**
* getURL
*
* @param {String} baseUrl Base url of the WMS server
* @param {String} layer Layer name
* @param {Number} x Tile coordinate x
* @param {Number} y Tile coordinate y
* @param {Number} z Tile zoom
* @param {Object} [options]
* @param {String} [options.format='image/png']
* @param {String} [options.service='WMS']
* @param {String} [options.version='1.1.1']
* @param {String} [options.request='GetMap']
* @param {String} [options.srs='EPSG:3857']
* @param {Number} [options.width='256']
* @param {Number} [options.height='256']
* @returns {String} url
* @example
* var baseUrl = 'http://geodata.state.nj.us/imagerywms/Natural2015';
* var layer = 'Natural2015';
* var url = whoots.getURL(baseUrl, layer, 154308, 197167, 19);
*/
function getURL(baseUrl, layer, x, y, z, options) {
options = options || {};
var url = baseUrl + '?' + [
'bbox=' + getTileBBox(x, y, z),
'format=' + (options.format || 'image/png'),
'service=' + (options.service || 'WMS'),
'version=' + (options.version || '1.1.1'),
'request=' + (options.request || 'GetMap'),
'srs=' + (options.srs || 'EPSG:3857'),
'width=' + (options.width || 256),
'height=' + (options.height || 256),
'layers=' + layer
].join('&');
return url;
}
/**
* getTileBBox
*
* @param {Number} x Tile coordinate x
* @param {Number} y Tile coordinate y
* @param {Number} z Tile zoom
* @returns {String} String of the bounding box
*/
function getTileBBox(x, y, z) {
// for Google/OSM tile scheme we need to alter the y
y = (Math.pow(2, z) - y - 1);
var min = getMercCoords(x * 256, y * 256, z),
max = getMercCoords((x + 1) * 256, (y + 1) * 256, z);
return min[0] + ',' + min[1] + ',' + max[0] + ',' + max[1];
}
/**
* getMercCoords
*
* @param {Number} x Pixel coordinate x
* @param {Number} y Pixel coordinate y
* @param {Number} z Tile zoom
* @returns {Array} [x, y]
*/
function getMercCoords(x, y, z) {
var resolution = (2 * Math.PI * 6378137 / 256) / Math.pow(2, z),
merc_x = (x * resolution - 2 * Math.PI * 6378137 / 2.0),
merc_y = (y * resolution - 2 * Math.PI * 6378137 / 2.0);
return [merc_x, merc_y];
}
//
var CanonicalTileID = function CanonicalTileID(z , x , y ) {
assert_1(z >= 0 && z <= 25);
assert_1(x >= 0 && x < Math.pow(2, z));
assert_1(y >= 0 && y < Math.pow(2, z));
this.z = z;
this.x = x;
this.y = y;
this.key = calculateKey(0, z, x, y);
};
CanonicalTileID.prototype.equals = function equals (id ) {
return this.z === id.z && this.x === id.x && this.y === id.y;
};
// given a list of urls, choose a url template and return a tile URL
CanonicalTileID.prototype.url = function url (urls , scheme ) {
var bbox = getTileBBox(this.x, this.y, this.z);
var quadkey = getQuadkey(this.z, this.x, this.y);
return urls[(this.x + this.y) % urls.length]
.replace('{prefix}', (this.x % 16).toString(16) + (this.y % 16).toString(16))
.replace('{z}', String(this.z))
.replace('{x}', String(this.x))
.replace('{y}', String(scheme === 'tms' ? (Math.pow(2, this.z) - this.y - 1) : this.y))
.replace('{quadkey}', quadkey)
.replace('{bbox-epsg-3857}', bbox);
};
var UnwrappedTileID = function UnwrappedTileID(wrap , canonical ) {
this.wrap = wrap;
this.canonical = canonical;
this.key = calculateKey(wrap, canonical.z, canonical.x, canonical.y);
};
var OverscaledTileID = function OverscaledTileID(overscaledZ , wrap , z , x , y ) {
assert_1(overscaledZ >= z);
this.overscaledZ = overscaledZ;
this.wrap = wrap;
this.canonical = new CanonicalTileID(z, +x, +y);
this.key = calculateKey(wrap, overscaledZ, x, y);
};
OverscaledTileID.prototype.equals = function equals (id ) {
return this.overscaledZ === id.overscaledZ && this.wrap === id.wrap && this.canonical.equals(id.canonical);
};
OverscaledTileID.prototype.scaledTo = function scaledTo (targetZ ) {
assert_1(targetZ <= this.overscaledZ);
var zDifference = this.canonical.z - targetZ;
if (targetZ > this.canonical.z) {
return new OverscaledTileID(targetZ, this.wrap, this.canonical.z, this.canonical.x, this.canonical.y);
} else {
return new OverscaledTileID(targetZ, this.wrap, targetZ, this.canonical.x >> zDifference, this.canonical.y >> zDifference);
}
};
OverscaledTileID.prototype.isChildOf = function isChildOf (parent ) {
var zDifference = this.canonical.z - parent.canonical.z;
// We're first testing for z == 0, to avoid a 32 bit shift, which is undefined.
return parent.overscaledZ === 0 || (
parent.overscaledZ < this.overscaledZ &&
parent.canonical.x === (this.canonical.x >> zDifference) &&
parent.canonical.y === (this.canonical.y >> zDifference));
};
OverscaledTileID.prototype.children = function children (sourceMaxZoom ) {
if (this.overscaledZ >= sourceMaxZoom) {
// return a single tile coord representing a an overscaled tile
return [new OverscaledTileID(this.overscaledZ + 1, this.wrap, this.canonical.z, this.canonical.x, this.canonical.y)];
}
var z = this.canonical.z + 1;
var x = this.canonical.x * 2;
var y = this.canonical.y * 2;
return [
new OverscaledTileID(z, this.wrap, z, x, y),
new OverscaledTileID(z, this.wrap, z, x + 1, y),
new OverscaledTileID(z, this.wrap, z, x, y + 1),
new OverscaledTileID(z, this.wrap, z, x + 1, y + 1)
];
};
OverscaledTileID.prototype.isLessThan = function isLessThan (rhs ) {
if (this.wrap < rhs.wrap) { return true; }
if (this.wrap > rhs.wrap) { return false; }
if (this.overscaledZ < rhs.overscaledZ) { return true; }
if (this.overscaledZ > rhs.overscaledZ) { return false; }
if (this.canonical.x < rhs.canonical.x) { return true; }
if (this.canonical.x > rhs.canonical.x) { return false; }
if (this.canonical.y < rhs.canonical.y) { return true; }
return false;
};
OverscaledTileID.prototype.wrapped = function wrapped () {
return new OverscaledTileID(this.overscaledZ, 0, this.canonical.z, this.canonical.x, this.canonical.y);
};
OverscaledTileID.prototype.unwrapTo = function unwrapTo (wrap ) {
return new OverscaledTileID(this.overscaledZ, wrap, this.canonical.z, this.canonical.x, this.canonical.y);
};
OverscaledTileID.prototype.overscaleFactor = function overscaleFactor () {
return Math.pow(2, this.overscaledZ - this.canonical.z);
};
OverscaledTileID.prototype.toUnwrapped = function toUnwrapped () {
return new UnwrappedTileID(this.wrap, this.canonical);
};
OverscaledTileID.prototype.toString = function toString () {
return ((this.overscaledZ) + "/" + (this.canonical.x) + "/" + (this.canonical.y));
};
OverscaledTileID.prototype.toCoordinate = function toCoordinate () {
return new Coordinate(this.canonical.x + Math.pow(2, this.wrap), this.canonical.y, this.canonical.z);
};
function calculateKey(wrap , z , x , y ) {
wrap *= 2;
if (wrap < 0) { wrap = wrap * -1 - 1; }
var dim = 1 << z;
return ((dim * dim * wrap + dim * y + x) * 32) + z;
}
function getQuadkey(z, x, y) {
var quadkey = '', mask;
for (var i = z; i > 0; i--) {
mask = 1 << (i - 1);
quadkey += ((x & mask ? 1 : 0) + (y & mask ? 2 : 0));
}
return quadkey;
}
register('CanonicalTileID', CanonicalTileID);
register('OverscaledTileID', OverscaledTileID, {omit: ['posMatrix']});
//
// DEMData is a data structure for decoding, backfilling, and storing elevation data for processing in the hillshade shaders
// data can be populated either from a pngraw image tile or from serliazed data sent back from a worker. When data is initially
// loaded from a image tile, we decode the pixel values using the appropriate decoding formula, but we store the
// elevation data as an Int32 value. we add 65536 (2^16) to eliminate negative values and enable the use of
// integer overflow when creating the texture used in the hillshadePrepare step.
// DEMData also handles the backfilling of data from a tile's neighboring tiles. This is necessary because we use a pixel's 8
// surrounding pixel values to compute the slope at that pixel, and we cannot accurately calculate the slope at pixels on a
// tile's edge without backfilling from neighboring tiles.
var DEMData = function DEMData(uid , data , encoding ) {
var this$1 = this;
this.uid = uid;
if (data.height !== data.width) { throw new RangeError('DEM tiles must be square'); }
if (encoding && encoding !== "mapbox" && encoding !== "terrarium") { return warnOnce(
("\"" + encoding + "\" is not a valid encoding type. Valid types include \"mapbox\" and \"terrarium\".")
); }
var dim = this.dim = data.height;
this.border = Math.max(Math.ceil(data.height / 2), 1);
this.stride = this.dim + 2 * this.border;
this.data = new Int32Array(this.stride * this.stride);
var pixels = data.data;
var unpack = encoding === "terrarium" ? this._unpackTerrarium : this._unpackMapbox;
for (var y = 0; y < dim; y++) {
for (var x = 0; x < dim; x++) {
var i = y * dim + x;
var j = i * 4;
this$1.set(x, y, unpack(pixels[j], pixels[j + 1], pixels[j + 2]));
}
}
// in order to avoid flashing seams between tiles, here we are initially populating a 1px border of pixels around the image
// with the data of the nearest pixel from the image. this data is eventually replaced when the tile's neighboring
// tiles are loaded and the accurate data can be backfilled using DEMData#backfillBorder
for (var x$1 = 0; x$1 < dim; x$1++) {
// left vertical border
this$1.set(-1, x$1, this$1.get(0, x$1));
// right vertical border
this$1.set(dim, x$1, this$1.get(dim - 1, x$1));
// left horizontal border
this$1.set(x$1, -1, this$1.get(x$1, 0));
// right horizontal border
this$1.set(x$1, dim, this$1.get(x$1, dim - 1));
}
// corners
this.set(-1, -1, this.get(0, 0));
this.set(dim, -1, this.get(dim - 1, 0));
this.set(-1, dim, this.get(0, dim - 1));
this.set(dim, dim, this.get(dim - 1, dim - 1));
};
DEMData.prototype.set = function set (x , y , value ) {
this.data[this._idx(x, y)] = value + 65536;
};
DEMData.prototype.get = function get (x , y ) {
return this.data[this._idx(x, y)] - 65536;
};
DEMData.prototype._idx = function _idx (x , y ) {
if (x < -this.border || x >= this.dim + this.border || y < -this.border || y >= this.dim + this.border) { throw new RangeError('out of range source coordinates for DEM data'); }
return (y + this.border) * this.stride + (x + this.border);
};
DEMData.prototype._unpackMapbox = function _unpackMapbox (r , g , b ) {
// unpacking formula for mapbox.terrain-rgb:
// https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb
return ((r * 256 * 256 + g * 256.0 + b) / 10.0 - 10000.0);
};
DEMData.prototype._unpackTerrarium = function _unpackTerrarium (r , g , b ) {
// unpacking formula for mapzen terrarium:
// https://aws.amazon.com/public-datasets/terrain/
return ((r * 256 + g + b / 256) - 32768.0);
};
DEMData.prototype.getPixels = function getPixels () {
return new RGBAImage({width: this.dim + 2 * this.border, height: this.dim + 2 * this.border}, new Uint8Array(this.data.buffer));
};
DEMData.prototype.backfillBorder = function backfillBorder (borderTile , dx , dy ) {
var this$1 = this;
if (this.dim !== borderTile.dim) { throw new Error('dem dimension mismatch'); }
var _xMin = dx * this.dim,
_xMax = dx * this.dim + this.dim,
_yMin = dy * this.dim,
_yMax = dy * this.dim + this.dim;
switch (dx) {
case -1:
_xMin = _xMax - 1;
break;
case 1:
_xMax = _xMin + 1;
break;
}
switch (dy) {
case -1:
_yMin = _yMax - 1;
break;
case 1:
_yMax = _yMin + 1;
break;
}
var xMin = clamp(_xMin, -this.border, this.dim + this.border);
var xMax = clamp(_xMax, -this.border, this.dim + this.border);
var yMin = clamp(_yMin, -this.border, this.dim + this.border);
var yMax = clamp(_yMax, -this.border, this.dim + this.border);
var ox = -dx * this.dim;
var oy = -dy * this.dim;
for (var y = yMin; y < yMax; y++) {
for (var x = xMin; x < xMax; x++) {
this$1.set(x, y, borderTile.get(x + ox, y + oy));
}
}
};
register('DEMData', DEMData);
//
var rasterBoundsAttributes = createLayout([
{ name: 'a_pos', type: 'Int16', components: 2 },
{ name: 'a_texture_pos', type: 'Int16', components: 2 }
]);
//
/**
* The `Bucket` interface is the single point of knowledge about turning vector
* tiles into WebGL buffers.
*
* `Bucket` is an abstract interface. An implementation exists for each style layer type.
* Create a bucket via the `StyleLayer#createBucket` method.
*
* The concrete bucket types, using layout options from the style layer,
* transform feature geometries into vertex and index data for use by the
* vertex shader. They also (via `ProgramConfiguration`) use feature
* properties and the zoom level to populate the attributes needed for
* data-driven styling.
*
* Buckets are designed to be built on a worker thread and then serialized and
* transferred back to the main thread for rendering. On the worker side, a
* bucket's vertex, index, and attribute data is stored in `bucket.arrays:
* ArrayGroup`. When a bucket's data is serialized and sent back to the main
* thread, is gets deserialized (using `new Bucket(serializedBucketData)`, with
* the array data now stored in `bucket.buffers: BufferGroup`. BufferGroups
* hold the same data as ArrayGroups, but are tuned for consumption by WebGL.
*
* @private
*/
function deserialize$1(input , style ) {
var output = {};
// Guard against the case where the map's style has been set to null while
// this bucket has been parsing.
if (!style) { return output; }
for (var i$1 = 0, list$1 = input; i$1 < list$1.length; i$1 += 1) {
var bucket = list$1[i$1];
var layers = bucket.layerIds
.map(function (id) { return style.getLayer(id); })
.filter(Boolean);
if (layers.length === 0) {
continue;
}
// look up StyleLayer objects from layer ids (since we don't
// want to waste time serializing/copying them from the worker)
(bucket ).layers = layers;
(bucket ).stateDependentLayers = layers.filter(function (l) { return l.isStateDependent(); });
for (var i = 0, list = layers; i < list.length; i += 1) {
var layer = list[i];
output[layer.id] = bucket;
}
}
return output;
}
//
var DictionaryCoder = function DictionaryCoder(strings ) {
var this$1 = this;
this._stringToNumber = {};
this._numberToString = [];
for (var i = 0; i < strings.length; i++) {
var string = strings[i];
this$1._stringToNumber[string] = i;
this$1._numberToString[i] = string;
}
};
DictionaryCoder.prototype.encode = function encode (string ) {
assert_1(string in this._stringToNumber);
return this._stringToNumber[string];
};
DictionaryCoder.prototype.decode = function decode (n ) {
assert_1(n < this._numberToString.length);
return this._numberToString[n];
};
//
var Feature = function Feature(vectorTileFeature , z , x , y ) {
this.type = 'Feature';
this._vectorTileFeature = vectorTileFeature;
(vectorTileFeature )._z = z;
(vectorTileFeature )._x = x;
(vectorTileFeature )._y = y;
this.properties = vectorTileFeature.properties;
if (vectorTileFeature.id != null) {
this.id = vectorTileFeature.id;
}
};
var prototypeAccessors$1 = { geometry: { configurable: true } };
prototypeAccessors$1.geometry.get = function () {
if (this._geometry === undefined) {
this._geometry = this._vectorTileFeature.toGeoJSON(
(this._vectorTileFeature )._x,
(this._vectorTileFeature )._y,
(this._vectorTileFeature )._z).geometry;
}
return this._geometry;
};
prototypeAccessors$1.geometry.set = function (g ) {
this._geometry = g;
};
Feature.prototype.toJSON = function toJSON () {
var this$1 = this;
var json = {
geometry: this.geometry
};
for (var i in this$1) {
if (i === '_geometry' || i === '_vectorTileFeature') { continue; }
json[i] = (this$1 )[i];
}
return json;
};
Object.defineProperties( Feature.prototype, prototypeAccessors$1 );
//
/**
* SourceFeatureState manages the state and state changes
* to features in a source, separated by source layer.
*
* @private
*/
var SourceFeatureState = function SourceFeatureState() {
this.state = {};
this.stateChanges = {};
};
SourceFeatureState.prototype.updateState = function updateState (sourceLayer , feature , state ) {
feature = String(feature);
this.stateChanges[sourceLayer] = this.stateChanges[sourceLayer] || {};
this.stateChanges[sourceLayer][feature] = this.stateChanges[sourceLayer][feature] || {};
extend(this.stateChanges[sourceLayer][feature], state);
};
SourceFeatureState.prototype.getState = function getState (sourceLayer , feature ) {
feature = String(feature);
var base = this.state[sourceLayer] || {};
var changes = this.stateChanges[sourceLayer] || {};
return extend({}, base[feature], changes[feature]);
};
SourceFeatureState.prototype.initializeTileState = function initializeTileState (tile , painter ) {
tile.setFeatureState(this.state, painter);
};
SourceFeatureState.prototype.coalesceChanges = function coalesceChanges (tiles , painter ) {
var this$1 = this;
var changes = {};
for (var sourceLayer in this$1.stateChanges) {
this$1.state[sourceLayer] = this$1.state[sourceLayer] || {};
var layerStates = {};
for (var id in this$1.stateChanges[sourceLayer]) {
if (!this$1.state[sourceLayer][id]) {
this$1.state[sourceLayer][id] = {};
}
extend(this$1.state[sourceLayer][id], this$1.stateChanges[sourceLayer][id]);
layerStates[id] = this$1.state[sourceLayer][id];
}
changes[sourceLayer] = layerStates;
}
this.stateChanges = {};
if (Object.keys(changes).length === 0) { return; }
for (var id$1 in tiles) {
var tile = tiles[id$1];
tile.setFeatureState(changes, painter);
}
};
//
var FeatureIndex = function FeatureIndex(tileID ,
grid ,
featureIndexArray ) {
this.tileID = tileID;
this.x = tileID.canonical.x;
this.y = tileID.canonical.y;
this.z = tileID.canonical.z;
this.grid = grid || new gridIndex(EXTENT, 16, 0);
this.featureIndexArray = featureIndexArray || new FeatureIndexArray();
};
FeatureIndex.prototype.insert = function insert (feature , geometry , featureIndex , sourceLayerIndex , bucketIndex ) {
var this$1 = this;
var key = this.featureIndexArray.length;
this.featureIndexArray.emplaceBack(featureIndex, sourceLayerIndex, bucketIndex);
for (var r = 0; r < geometry.length; r++) {
var ring = geometry[r];
var bbox = [Infinity, Infinity, -Infinity, -Infinity];
for (var i = 0; i < ring.length; i++) {
var p = ring[i];
bbox[0] = Math.min(bbox[0], p.x);
bbox[1] = Math.min(bbox[1], p.y);
bbox[2] = Math.max(bbox[2], p.x);
bbox[3] = Math.max(bbox[3], p.y);
}
if (bbox[0] < EXTENT &&
bbox[1] < EXTENT &&
bbox[2] >= 0 &&
bbox[3] >= 0) {
this$1.grid.insert(key, bbox[0], bbox[1], bbox[2], bbox[3]);
}
}
};
FeatureIndex.prototype.loadVTLayers = function loadVTLayers () {
if (!this.vtLayers) {
this.vtLayers = new vectorTile.VectorTile(new pbf(this.rawTileData)).layers;
this.sourceLayerCoder = new DictionaryCoder(this.vtLayers ? Object.keys(this.vtLayers).sort() : ['_geojsonTileLayer']);
}
return this.vtLayers;
};
// Finds non-symbol features in this tile at a particular position.
FeatureIndex.prototype.query = function query (args , styleLayers , sourceFeatureState ) {
var this$1 = this;
this.loadVTLayers();
var params = args.params || {},
pixelsToTileUnits = EXTENT / args.tileSize / args.scale,
filter = createFilter(params.filter);
var queryGeometry = args.queryGeometry;
var queryPadding = args.queryPadding * pixelsToTileUnits;
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
for (var i = 0; i < queryGeometry.length; i++) {
var ring = queryGeometry[i];
for (var k = 0; k < ring.length; k++) {
var p = ring[k];
minX = Math.min(minX, p.x);
minY = Math.min(minY, p.y);
maxX = Math.max(maxX, p.x);
maxY = Math.max(maxY, p.y);
}
}
var matching = this.grid.query(minX - queryPadding, minY - queryPadding, maxX + queryPadding, maxY + queryPadding);
matching.sort(topDownFeatureComparator);
var result = {};
var previousIndex;
var loop = function ( k ) {
var index = matching[k];
// don't check the same feature more than once
if (index === previousIndex) { return; }
previousIndex = index;
var match = this$1.featureIndexArray.get(index);
var featureGeometry = null;
this$1.loadMatchingFeature(
result,
match.bucketIndex,
match.sourceLayerIndex,
match.featureIndex,
filter,
params.layers,
styleLayers,
function (feature , styleLayer ) {
if (!featureGeometry) {
featureGeometry = loadGeometry(feature);
}
var featureState = {};
if (feature.id) {
// `feature-state` expression evaluation requires feature state to be available
featureState = sourceFeatureState.getState(styleLayer.sourceLayer || '_geojsonTileLayer', String(feature.id));
}
return styleLayer.queryIntersectsFeature(queryGeometry, feature, featureState, featureGeometry, this$1.z, args.transform, pixelsToTileUnits, args.posMatrix);
}
);
};
for (var k$1 = 0; k$1 < matching.length; k$1++) loop( k$1 );
return result;
};
FeatureIndex.prototype.loadMatchingFeature = function loadMatchingFeature (
result ,
bucketIndex ,
sourceLayerIndex ,
featureIndex ,
filter ,
filterLayerIDs ,
styleLayers ,
intersectionTest ) {
var this$1 = this;
var layerIDs = this.bucketLayerIDs[bucketIndex];
if (filterLayerIDs && !arraysIntersect(filterLayerIDs, layerIDs))
{ return; }
var sourceLayerName = this.sourceLayerCoder.decode(sourceLayerIndex);
var sourceLayer = this.vtLayers[sourceLayerName];
var feature = sourceLayer.feature(featureIndex);
if (!filter(new EvaluationParameters(this.tileID.overscaledZ), feature))
{ return; }
for (var l = 0; l < layerIDs.length; l++) {
var layerID = layerIDs[l];
if (filterLayerIDs && filterLayerIDs.indexOf(layerID) < 0) {
continue;
}
var styleLayer = styleLayers[layerID];
if (!styleLayer) { continue; }
if (intersectionTest && !intersectionTest(feature, styleLayer)) {
// Only applied for non-symbol features
continue;
}
var geojsonFeature = new Feature(feature, this$1.z, this$1.x, this$1.y);
(geojsonFeature ).layer = styleLayer.serialize();
var layerResult = result[layerID];
if (layerResult === undefined) {
layerResult = result[layerID] = [];
}
layerResult.push({ featureIndex: featureIndex, feature: geojsonFeature });
}
};
// Given a set of symbol indexes that have already been looked up,
// return a matching set of GeoJSONFeatures
FeatureIndex.prototype.lookupSymbolFeatures = function lookupSymbolFeatures (symbolFeatureIndexes ,
bucketIndex ,
sourceLayerIndex ,
filterSpec ,
filterLayerIDs ,
styleLayers ) {
var this$1 = this;
var result = {};
this.loadVTLayers();
var filter = createFilter(filterSpec);
for (var i = 0, list = symbolFeatureIndexes; i < list.length; i += 1) {
var symbolFeatureIndex = list[i];
this$1.loadMatchingFeature(
result,
bucketIndex,
sourceLayerIndex,
symbolFeatureIndex,
filter,
filterLayerIDs,
styleLayers
);
}
return result;
};
FeatureIndex.prototype.hasLayer = function hasLayer (id ) {
var this$1 = this;
for (var i$1 = 0, list$1 = this$1.bucketLayerIDs; i$1 < list$1.length; i$1 += 1) {
var layerIDs = list$1[i$1];
for (var i = 0, list = layerIDs; i < list.length; i += 1) {
var layerID = list[i];
if (id === layerID) { return true; }
}
}
return false;
};
register(
'FeatureIndex',
FeatureIndex,
{ omit: ['rawTileData', 'sourceLayerCoder'] }
);
function topDownFeatureComparator(a, b) {
return b - a;
}
//
var CLOCK_SKEW_RETRY_TIMEOUT = 30000;
/* Tile data was previously loaded, but has expired per its
* HTTP headers and is in the process of refreshing. */
/**
* A tile object is the combination of a Coordinate, which defines
* its place, as well as a unique ID and data tracking for its content
*
* @private
*/
var Tile = function Tile(tileID , size ) {
this.tileID = tileID;
this.uid = uniqueId();
this.uses = 0;
this.tileSize = size;
this.buckets = {};
this.expirationTime = null;
this.queryPadding = 0;
this.hasSymbolBuckets = false;
// Counts the number of times a response was already expired when
// received. We're using this to add a delay when making a new request
// so we don't have to keep retrying immediately in case of a server
// serving expired tiles.
this.expiredRequestCount = 0;
this.state = 'loading';
};
Tile.prototype.registerFadeDuration = function registerFadeDuration (duration ) {
var fadeEndTime = duration + this.timeAdded;
if (fadeEndTime < exported.now()) { return; }
if (this.fadeEndTime && fadeEndTime < this.fadeEndTime) { return; }
this.fadeEndTime = fadeEndTime;
};
Tile.prototype.wasRequested = function wasRequested () {
return this.state === 'errored' || this.state === 'loaded' || this.state === 'reloading';
};
/**
* Given a data object with a 'buffers' property, load it into
* this tile's elementGroups and buffers properties and set loaded
* to true. If the data is null, like in the case of an empty
* GeoJSON tile, no-op but still set loaded to true.
* @param {Object} data
* @param painter
* @returns {undefined}
* @private
*/
Tile.prototype.loadVectorData = function loadVectorData (data , painter , justReloaded ) {
var this$1 = this;
if (this.hasData()) {
this.unloadVectorData();
}
this.state = 'loaded';
// empty GeoJSON tile
if (!data) {
this.collisionBoxArray = new CollisionBoxArray();
return;
}
if (data.featureIndex) {
this.latestFeatureIndex = data.featureIndex;
if (data.rawTileData) {
// Only vector tiles have rawTileData, and they won't update it for
// 'reloadTile'
this.latestRawTileData = data.rawTileData;
this.latestFeatureIndex.rawTileData = data.rawTileData;
} else if (this.latestRawTileData) {
// If rawTileData hasn't updated, hold onto a pointer to the last
// one we received
this.latestFeatureIndex.rawTileData = this.latestRawTileData;
}
}
this.collisionBoxArray = data.collisionBoxArray;
this.buckets = deserialize$1(data.buckets, painter.style);
this.hasSymbolBuckets = false;
for (var id in this$1.buckets) {
var bucket = this$1.buckets[id];
if (bucket instanceof SymbolBucket) {
this$1.hasSymbolBuckets = true;
if (justReloaded) {
bucket.justReloaded = true;
} else {
break;
}
}
}
this.queryPadding = 0;
for (var id$1 in this$1.buckets) {
var bucket$1 = this$1.buckets[id$1];
this$1.queryPadding = Math.max(this$1.queryPadding, painter.style.getLayer(id$1).queryRadius(bucket$1));
}
if (data.iconAtlasImage) {
this.iconAtlasImage = data.iconAtlasImage;
}
if (data.glyphAtlasImage) {
this.glyphAtlasImage = data.glyphAtlasImage;
}
};
/**
* Release any data or WebGL resources referenced by this tile.
* @returns {undefined}
* @private
*/
Tile.prototype.unloadVectorData = function unloadVectorData () {
var this$1 = this;
for (var id in this$1.buckets) {
this$1.buckets[id].destroy();
}
this.buckets = {};
if (this.iconAtlasTexture) {
this.iconAtlasTexture.destroy();
}
if (this.glyphAtlasTexture) {
this.glyphAtlasTexture.destroy();
}
this.latestFeatureIndex = null;
this.state = 'unloaded';
};
Tile.prototype.unloadDEMData = function unloadDEMData () {
this.dem = null;
this.neighboringTiles = null;
this.state = 'unloaded';
};
Tile.prototype.getBucket = function getBucket (layer ) {
return this.buckets[layer.id];
};
Tile.prototype.upload = function upload (context ) {
var this$1 = this;
for (var id in this$1.buckets) {
var bucket = this$1.buckets[id];
if (bucket.uploadPending()) {
bucket.upload(context);
}
}
var gl = context.gl;
if (this.iconAtlasImage) {
this.iconAtlasTexture = new Texture(context, this.iconAtlasImage, gl.RGBA);
this.iconAtlasImage = null;
}
if (this.glyphAtlasImage) {
this.glyphAtlasTexture = new Texture(context, this.glyphAtlasImage, gl.ALPHA);
this.glyphAtlasImage = null;
}
};
// Queries non-symbol features rendered for this tile.
// Symbol features are queried globally
Tile.prototype.queryRenderedFeatures = function queryRenderedFeatures (layers ,
sourceFeatureState ,
queryGeometry ,
scale ,
params ,
transform ,
maxPitchScaleFactor ,
posMatrix ) {
if (!this.latestFeatureIndex || !this.latestFeatureIndex.rawTileData)
{ return {}; }
return this.latestFeatureIndex.query({
queryGeometry: queryGeometry,
scale: scale,
tileSize: this.tileSize,
posMatrix: posMatrix,
transform: transform,
params: params,
queryPadding: this.queryPadding * maxPitchScaleFactor
}, layers, sourceFeatureState);
};
Tile.prototype.querySourceFeatures = function querySourceFeatures (result , params ) {
var this$1 = this;
if (!this.latestFeatureIndex || !this.latestFeatureIndex.rawTileData) { return; }
var vtLayers = this.latestFeatureIndex.loadVTLayers();
var sourceLayer = params ? params.sourceLayer : '';
var layer = vtLayers._geojsonTileLayer || vtLayers[sourceLayer];
if (!layer) { return; }
var filter = createFilter(params && params.filter);
var ref = this.tileID.canonical;
var z = ref.z;
var x = ref.x;
var y = ref.y;
var coord = {z: z, x: x, y: y};
for (var i = 0; i < layer.length; i++) {
var feature = layer.feature(i);
if (filter(new EvaluationParameters(this$1.tileID.overscaledZ), feature)) {
var geojsonFeature = new Feature(feature, z, x, y);
(geojsonFeature ).tile = coord;
result.push(geojsonFeature);
}
}
};
Tile.prototype.clearMask = function clearMask () {
if (this.segments) {
this.segments.destroy();
delete this.segments;
}
if (this.maskedBoundsBuffer) {
this.maskedBoundsBuffer.destroy();
delete this.maskedBoundsBuffer;
}
if (this.maskedIndexBuffer) {
this.maskedIndexBuffer.destroy();
delete this.maskedIndexBuffer;
}
};
Tile.prototype.setMask = function setMask (mask , context ) {
var this$1 = this;
// don't redo buffer work if the mask is the same;
if (deepEqual(this.mask, mask)) { return; }
this.mask = mask;
this.clearMask();
// We want to render the full tile, and keeping the segments/vertices/indices empty means
// using the global shared buffers for covering the entire tile.
if (deepEqual(mask, {'0': true})) { return; }
var maskedBoundsArray = new StructArrayLayout4i8();
var indexArray = new StructArrayLayout3ui6();
this.segments = new SegmentVector();
// Create a new segment so that we will upload (empty) buffers even when there is nothing to
// draw for this tile.
this.segments.prepareSegment(0, maskedBoundsArray, indexArray);
var maskArray = Object.keys(mask);
for (var i = 0; i < maskArray.length; i++) {
var maskCoord = mask[maskArray[i]];
var vertexExtent = EXTENT >> maskCoord.z;
var tlVertex = new pointGeometry(maskCoord.x * vertexExtent, maskCoord.y * vertexExtent);
var brVertex = new pointGeometry(tlVertex.x + vertexExtent, tlVertex.y + vertexExtent);
// not sure why flow is complaining here because it doesn't complain at L401
var segment = (this$1.segments ).prepareSegment(4, maskedBoundsArray, indexArray);
maskedBoundsArray.emplaceBack(tlVertex.x, tlVertex.y, tlVertex.x, tlVertex.y);
maskedBoundsArray.emplaceBack(brVertex.x, tlVertex.y, brVertex.x, tlVertex.y);
maskedBoundsArray.emplaceBack(tlVertex.x, brVertex.y, tlVertex.x, brVertex.y);
maskedBoundsArray.emplaceBack(brVertex.x, brVertex.y, brVertex.x, brVertex.y);
var offset = segment.vertexLength;
// 0, 1, 2
// 1, 2, 3
indexArray.emplaceBack(offset, offset + 1, offset + 2);
indexArray.emplaceBack(offset + 1, offset + 2, offset + 3);
segment.vertexLength += 4;
segment.primitiveLength += 2;
}
this.maskedBoundsBuffer = context.createVertexBuffer(maskedBoundsArray, rasterBoundsAttributes.members);
this.maskedIndexBuffer = context.createIndexBuffer(indexArray);
};
Tile.prototype.hasData = function hasData () {
return this.state === 'loaded' || this.state === 'reloading' || this.state === 'expired';
};
Tile.prototype.setExpiryData = function setExpiryData (data ) {
var prior = this.expirationTime;
if (data.cacheControl) {
var parsedCC = parseCacheControl(data.cacheControl);
if (parsedCC['max-age']) { this.expirationTime = Date.now() + parsedCC['max-age'] * 1000; }
} else if (data.expires) {
this.expirationTime = new Date(data.expires).getTime();
}
if (this.expirationTime) {
var now = Date.now();
var isExpired = false;
if (this.expirationTime > now) {
isExpired = false;
} else if (!prior) {
isExpired = true;
} else if (this.expirationTime < prior) {
// Expiring date is going backwards:
// fall back to exponential backoff
isExpired = true;
} else {
var delta = this.expirationTime - prior;
if (!delta) {
// Server is serving the same expired resource over and over: fall
// back to exponential backoff.
isExpired = true;
} else {
// Assume that either the client or the server clock is wrong and
// try to interpolate a valid expiration date (from the client POV)
// observing a minimum timeout.
this.expirationTime = now + Math.max(delta, CLOCK_SKEW_RETRY_TIMEOUT);
}
}
if (isExpired) {
this.expiredRequestCount++;
this.state = 'expired';
} else {
this.expiredRequestCount = 0;
}
}
};
Tile.prototype.getExpiryTimeout = function getExpiryTimeout () {
if (this.expirationTime) {
if (this.expiredRequestCount) {
return 1000 * (1 << Math.min(this.expiredRequestCount - 1, 31));
} else {
// Max value for `setTimeout` implementations is a 32 bit integer; cap this accordingly
return Math.min(this.expirationTime - new Date().getTime(), Math.pow(2, 31) - 1);
}
}
};
Tile.prototype.setFeatureState = function setFeatureState (states , painter ) {
var this$1 = this;
if (!this.latestFeatureIndex ||
!this.latestFeatureIndex.rawTileData ||
Object.keys(states).length === 0) {
return;
}
var vtLayers = this.latestFeatureIndex.loadVTLayers();
for (var id in this$1.buckets) {
var bucket = this$1.buckets[id];
// Buckets are grouped by common source-layer
var sourceLayerId = bucket.layers[0]['sourceLayer'] || '_geojsonTileLayer';
var sourceLayer = vtLayers[sourceLayerId];
var sourceLayerStates = states[sourceLayerId];
if (!sourceLayer || !sourceLayerStates || Object.keys(sourceLayerStates).length === 0) { continue; }
bucket.update(sourceLayerStates, sourceLayer);
if (painter && painter.style) {
this$1.queryPadding = Math.max(this$1.queryPadding, painter.style.getLayer(id).queryRadius(bucket));
}
}
};
Tile.prototype.holdingForFade = function holdingForFade () {
return this.symbolFadeHoldUntil !== undefined;
};
Tile.prototype.symbolFadeFinished = function symbolFadeFinished () {
return !this.symbolFadeHoldUntil || this.symbolFadeHoldUntil < exported.now();
};
Tile.prototype.clearFadeHold = function clearFadeHold () {
this.symbolFadeHoldUntil = undefined;
};
Tile.prototype.setHoldDuration = function setHoldDuration (duration ) {
this.symbolFadeHoldUntil = exported.now() + duration;
};
var refProperties = ['type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', 'layout'];
//
var WritingMode = {
horizontal: 1,
vertical: 2,
horizontalOnly: 3
};
// The position of a glyph relative to the text's anchor point.
// A collection of positioned glyphs and some metadata
var TaggedString = function TaggedString() {
this.text = "";
this.sectionIndex = [];
this.sections = [];
};
TaggedString.fromFeature = function fromFeature (text , defaultFontStack ) {
var result = new TaggedString();
if (text instanceof Formatted) {
for (var i = 0; i < text.sections.length; i++) {
var section = text.sections[i];
result.sections.push({
scale: section.scale || 1,
fontStack: section.fontStack || defaultFontStack
});
result.text += section.text;
for (var j = 0; j < section.text.length; j++) {
result.sectionIndex.push(i);
}
}
} else {
result.text = text;
result.sections.push({ scale: 1, fontStack: defaultFontStack });
for (var i$1 = 0; i$1 < text.length; i$1++) {
result.sectionIndex.push(0);
}
}
return result;
};
TaggedString.prototype.length = function length () {
return this.text.length;
};
TaggedString.prototype.getSection = function getSection (index ) {
return this.sections[this.sectionIndex[index]];
};
TaggedString.prototype.getCharCode = function getCharCode (index ) {
return this.text.charCodeAt(index);
};
TaggedString.prototype.verticalizePunctuation = function verticalizePunctuation$1 () {
this.text = verticalizePunctuation(this.text);
};
TaggedString.prototype.trim = function trim () {
var beginningWhitespace = 0;
for (var i = 0;
i < this.text.length && whitespace[this.text.charCodeAt(i)];
i++) {
beginningWhitespace++;
}
var trailingWhitespace = this.text.length;
for (var i$1 = this.text.length - 1;
i$1 >= 0 && i$1 >= beginningWhitespace && whitespace[this.text.charCodeAt(i$1)];
i$1--) {
trailingWhitespace--;
}
this.text = this.text.substring(beginningWhitespace, trailingWhitespace);
this.sectionIndex = this.sectionIndex.slice(beginningWhitespace, trailingWhitespace);
};
TaggedString.prototype.substring = function substring (start , end ) {
var substring = new TaggedString();
substring.text = this.text.substring(start, end);
substring.sectionIndex = this.sectionIndex.slice(start, end);
substring.sections = this.sections;
return substring;
};
TaggedString.prototype.toString = function toString () {
return this.text;
};
TaggedString.prototype.getMaxScale = function getMaxScale () {
var this$1 = this;
return this.sectionIndex.reduce(function (max, index) { return Math.max(max, this$1.sections[index].scale); }, 0);
};
function breakLines(input , lineBreakPoints ) {
var lines = [];
var text = input.text;
var start = 0;
for (var i = 0, list = lineBreakPoints; i < list.length; i += 1) {
var lineBreak = list[i];
lines.push(input.substring(start, lineBreak));
start = lineBreak;
}
if (start < text.length) {
lines.push(input.substring(start, text.length));
}
return lines;
}
function shapeText(text ,
glyphs ,
defaultFontStack ,
maxWidth ,
lineHeight ,
textAnchor ,
textJustify ,
spacing ,
translate ,
verticalHeight ,
writingMode ) {
var logicalInput = TaggedString.fromFeature(text, defaultFontStack);
if (writingMode === WritingMode.vertical) {
logicalInput.verticalizePunctuation();
}
var positionedGlyphs = [];
var shaping = {
positionedGlyphs: positionedGlyphs,
text: logicalInput,
top: translate[1],
bottom: translate[1],
left: translate[0],
right: translate[0],
writingMode: writingMode
};
var lines ;
var processBidirectionalText = plugin.processBidirectionalText;
var processStyledBidirectionalText = plugin.processStyledBidirectionalText;
if (processBidirectionalText && logicalInput.sections.length === 1) {
// Bidi doesn't have to be style-aware
lines = [];
var untaggedLines =
processBidirectionalText(logicalInput.toString(),
determineLineBreaks(logicalInput, spacing, maxWidth, glyphs));
for (var i$1 = 0, list = untaggedLines; i$1 < list.length; i$1 += 1) {
var line = list[i$1];
var taggedLine = new TaggedString();
taggedLine.text = line;
taggedLine.sections = logicalInput.sections;
for (var i = 0; i < line.length; i++) {
taggedLine.sectionIndex.push(0);
}
lines.push(taggedLine);
}
} else if (processStyledBidirectionalText) {
// Need version of mapbox-gl-rtl-text with style support for combining RTL text
// with formatting
lines = [];
var processedLines =
processStyledBidirectionalText(logicalInput.text,
logicalInput.sectionIndex,
determineLineBreaks(logicalInput, spacing, maxWidth, glyphs));
for (var i$2 = 0, list$1 = processedLines; i$2 < list$1.length; i$2 += 1) {
var line$1 = list$1[i$2];
var taggedLine$1 = new TaggedString();
taggedLine$1.text = line$1[0];
taggedLine$1.sectionIndex = line$1[1];
taggedLine$1.sections = logicalInput.sections;
lines.push(taggedLine$1);
}
} else {
lines = breakLines(logicalInput, determineLineBreaks(logicalInput, spacing, maxWidth, glyphs));
}
shapeLines(shaping, glyphs, lines, lineHeight, textAnchor, textJustify, writingMode, spacing, verticalHeight);
if (!positionedGlyphs.length)
{ return false; }
shaping.text = shaping.text.toString();
return shaping;
}
var whitespace = {};
whitespace[0x09] = true;
whitespace[0x0a] = true;
whitespace[0x0b] = true;
whitespace[0x0c] = true;
whitespace[0x0d] = true;
whitespace[0x20] = true;
var breakable = {};
breakable[0x0a] = true;
breakable[0x20] = true;
breakable[0x26] = true;
breakable[0x28] = true;
breakable[0x29] = true;
breakable[0x2b] = true;
breakable[0x2d] = true;
breakable[0x2f] = true;
breakable[0xad] = true;
breakable[0xb7] = true;
breakable[0x200b] = true;
breakable[0x2010] = true;
breakable[0x2013] = true;
breakable[0x2027] = true;
function determineAverageLineWidth(logicalInput ,
spacing ,
maxWidth ,
glyphMap ) {
var totalWidth = 0;
for (var index = 0; index < logicalInput.length(); index++) {
var section = logicalInput.getSection(index);
var positions = glyphMap[section.fontStack];
var glyph = positions && positions[logicalInput.getCharCode(index)];
if (!glyph)
{ continue; }
totalWidth += glyph.metrics.advance * section.scale + spacing;
}
var lineCount = Math.max(1, Math.ceil(totalWidth / maxWidth));
return totalWidth / lineCount;
}
function calculateBadness(lineWidth ,
targetWidth ,
penalty ,
isLastBreak ) {
var raggedness = Math.pow(lineWidth - targetWidth, 2);
if (isLastBreak) {
// Favor finals lines shorter than average over longer than average
if (lineWidth < targetWidth) {
return raggedness / 2;
} else {
return raggedness * 2;
}
}
return raggedness + Math.abs(penalty) * penalty;
}
function calculatePenalty(codePoint , nextCodePoint ) {
var penalty = 0;
// Force break on newline
if (codePoint === 0x0a) {
penalty -= 10000;
}
// Penalize open parenthesis at end of line
if (codePoint === 0x28 || codePoint === 0xff08) {
penalty += 50;
}
// Penalize close parenthesis at beginning of line
if (nextCodePoint === 0x29 || nextCodePoint === 0xff09) {
penalty += 50;
}
return penalty;
}
function evaluateBreak(breakIndex ,
breakX ,
targetWidth ,
potentialBreaks ,
penalty ,
isLastBreak ) {
// We could skip evaluating breaks where the line length (breakX - priorBreak.x) > maxWidth
// ...but in fact we allow lines longer than maxWidth (if there's no break points)
// ...and when targetWidth and maxWidth are close, strictly enforcing maxWidth can give
// more lopsided results.
var bestPriorBreak = null;
var bestBreakBadness = calculateBadness(breakX, targetWidth, penalty, isLastBreak);
for (var i = 0, list = potentialBreaks; i < list.length; i += 1) {
var potentialBreak = list[i];
var lineWidth = breakX - potentialBreak.x;
var breakBadness =
calculateBadness(lineWidth, targetWidth, penalty, isLastBreak) + potentialBreak.badness;
if (breakBadness <= bestBreakBadness) {
bestPriorBreak = potentialBreak;
bestBreakBadness = breakBadness;
}
}
return {
index: breakIndex,
x: breakX,
priorBreak: bestPriorBreak,
badness: bestBreakBadness
};
}
function leastBadBreaks(lastLineBreak ) {
if (!lastLineBreak) {
return [];
}
return leastBadBreaks(lastLineBreak.priorBreak).concat(lastLineBreak.index);
}
function determineLineBreaks(logicalInput ,
spacing ,
maxWidth ,
glyphMap ) {
if (!maxWidth)
{ return []; }
if (!logicalInput)
{ return []; }
var potentialLineBreaks = [];
var targetWidth = determineAverageLineWidth(logicalInput, spacing, maxWidth, glyphMap);
var currentX = 0;
for (var i = 0; i < logicalInput.length(); i++) {
var section = logicalInput.getSection(i);
var codePoint = logicalInput.getCharCode(i);
var positions = glyphMap[section.fontStack];
var glyph = positions && positions[codePoint];
if (glyph && !whitespace[codePoint])
{ currentX += glyph.metrics.advance * section.scale + spacing; }
// Ideographic characters, spaces, and word-breaking punctuation that often appear without
// surrounding spaces.
if ((i < logicalInput.length() - 1) &&
(breakable[codePoint] ||
charAllowsIdeographicBreaking(codePoint))) {
potentialLineBreaks.push(
evaluateBreak(
i + 1,
currentX,
targetWidth,
potentialLineBreaks,
calculatePenalty(codePoint, logicalInput.getCharCode(i + 1)),
false));
}
}
return leastBadBreaks(
evaluateBreak(
logicalInput.length(),
currentX,
targetWidth,
potentialLineBreaks,
0,
true));
}
function getAnchorAlignment(anchor ) {
var horizontalAlign = 0.5, verticalAlign = 0.5;
switch (anchor) {
case 'right':
case 'top-right':
case 'bottom-right':
horizontalAlign = 1;
break;
case 'left':
case 'top-left':
case 'bottom-left':
horizontalAlign = 0;
break;
}
switch (anchor) {
case 'bottom':
case 'bottom-right':
case 'bottom-left':
verticalAlign = 1;
break;
case 'top':
case 'top-right':
case 'top-left':
verticalAlign = 0;
break;
}
return { horizontalAlign: horizontalAlign, verticalAlign: verticalAlign };
}
function shapeLines(shaping ,
glyphMap ,
lines ,
lineHeight ,
textAnchor ,
textJustify ,
writingMode ,
spacing ,
verticalHeight ) {
// the y offset *should* be part of the font metadata
var yOffset = -17;
var x = 0;
var y = yOffset;
var maxLineLength = 0;
var positionedGlyphs = shaping.positionedGlyphs;
var justify =
textJustify === 'right' ? 1 :
textJustify === 'left' ? 0 : 0.5;
for (var i$1 = 0, list = lines; i$1 < list.length; i$1 += 1) {
var line = list[i$1];
line.trim();
var lineMaxScale = line.getMaxScale();
if (!line.length()) {
y += lineHeight; // Still need a line feed after empty line
continue;
}
var lineStartIndex = positionedGlyphs.length;
for (var i = 0; i < line.length(); i++) {
var section = line.getSection(i);
var codePoint = line.getCharCode(i);
// We don't know the baseline, but since we're laying out
// at 24 points, we can calculate how much it will move when
// we scale up or down.
var baselineOffset = (lineMaxScale - section.scale) * 24;
var positions = glyphMap[section.fontStack];
var glyph = positions && positions[codePoint];
if (!glyph) { continue; }
if (!charHasUprightVerticalOrientation(codePoint) || writingMode === WritingMode.horizontal) {
positionedGlyphs.push({glyph: codePoint, x: x, y: y + baselineOffset, vertical: false, scale: section.scale, fontStack: section.fontStack});
x += glyph.metrics.advance * section.scale + spacing;
} else {
positionedGlyphs.push({glyph: codePoint, x: x, y: baselineOffset, vertical: true, scale: section.scale, fontStack: section.fontStack});
x += verticalHeight * section.scale + spacing;
}
}
// Only justify if we placed at least one glyph
if (positionedGlyphs.length !== lineStartIndex) {
var lineLength = x - spacing;
maxLineLength = Math.max(lineLength, maxLineLength);
justifyLine(positionedGlyphs, glyphMap, lineStartIndex, positionedGlyphs.length - 1, justify);
}
x = 0;
y += lineHeight * lineMaxScale;
}
var ref = getAnchorAlignment(textAnchor);
var horizontalAlign = ref.horizontalAlign;
var verticalAlign = ref.verticalAlign;
align$1(positionedGlyphs, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, lines.length);
// Calculate the bounding box
var height = y - yOffset;
shaping.top += -verticalAlign * height;
shaping.bottom = shaping.top + height;
shaping.left += -horizontalAlign * maxLineLength;
shaping.right = shaping.left + maxLineLength;
}
// justify right = 1, left = 0, center = 0.5
function justifyLine(positionedGlyphs ,
glyphMap ,
start ,
end ,
justify ) {
if (!justify)
{ return; }
var lastPositionedGlyph = positionedGlyphs[end];
var positions = glyphMap[lastPositionedGlyph.fontStack];
var glyph = positions && positions[lastPositionedGlyph.glyph];
if (glyph) {
var lastAdvance = glyph.metrics.advance * lastPositionedGlyph.scale;
var lineIndent = (positionedGlyphs[end].x + lastAdvance) * justify;
for (var j = start; j <= end; j++) {
positionedGlyphs[j].x -= lineIndent;
}
}
}
function align$1(positionedGlyphs ,
justify ,
horizontalAlign ,
verticalAlign ,
maxLineLength ,
lineHeight ,
lineCount ) {
var shiftX = (justify - horizontalAlign) * maxLineLength;
var shiftY = (-verticalAlign * lineCount + 0.5) * lineHeight;
for (var j = 0; j < positionedGlyphs.length; j++) {
positionedGlyphs[j].x += shiftX;
positionedGlyphs[j].y += shiftY;
}
}
function shapeIcon(image , iconOffset , iconAnchor ) {
var ref = getAnchorAlignment(iconAnchor);
var horizontalAlign = ref.horizontalAlign;
var verticalAlign = ref.verticalAlign;
var dx = iconOffset[0];
var dy = iconOffset[1];
var x1 = dx - image.displaySize[0] * horizontalAlign;
var x2 = x1 + image.displaySize[0];
var y1 = dy - image.displaySize[1] * verticalAlign;
var y2 = y1 + image.displaySize[1];
return {image: image, top: y1, bottom: y2, left: x1, right: x2};
}
exports.commonjsGlobal = commonjsGlobal;
exports.commonjsRequire = commonjsRequire;
exports.unwrapExports = unwrapExports;
exports.createCommonjsModule = createCommonjsModule;
exports.Point = pointGeometry;
exports.window = self;
exports.assert = assert_1;
exports.browser = exported;
exports.uuid = uuid;
exports.validateUuid = validateUuid;
exports.storageAvailable = storageAvailable;
exports.warnOnce = warnOnce;
exports.postData = postData;
exports.getJSON = getJSON;
exports.getImage = getImage;
exports.ResourceType = ResourceType;
exports.RGBAImage = RGBAImage;
exports.ShelfPack = ShelfPack;
exports.ImagePosition = ImagePosition;
exports.Texture = Texture;
exports.getArrayBuffer = getArrayBuffer;
exports.parseGlyphPBF = parseGlyphPBF;
exports.isChar = unicodeBlockLookup;
exports.asyncAll = asyncAll;
exports.AlphaImage = AlphaImage;
exports.styleSpec = styleSpec;
exports.endsWith = endsWith;
exports.extend = extend;
exports.sphericalToCartesian = sphericalToCartesian;
exports.Evented = Evented;
exports.validateStyle = validateStyle;
exports.validateLight = validateLight$1;
exports.emitValidationErrors = emitValidationErrors;
exports.Color = Color;
exports.number = number;
exports.Properties = Properties;
exports.Transitionable = Transitionable;
exports.Transitioning = Transitioning;
exports.PossiblyEvaluated = PossiblyEvaluated;
exports.DataConstantProperty = DataConstantProperty;
exports.uniqueId = uniqueId;
exports.Actor = Actor;
exports.pick = pi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment