(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@antv/g-lite')) :
typeof define === 'function' && define.amd ? define(['exports', '@antv/g-lite'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.G = global.G || {}, global.G.Canvas2D = {}), global.window.G));
}(this, (function (exports, gLite) { 'use strict';
function _regeneratorRuntime() {
_regeneratorRuntime = function () {
return exports;
};
var exports = {},
Op = Object.prototype,
hasOwn = Op.hasOwnProperty,
defineProperty = Object.defineProperty || function (obj, key, desc) {
obj[key] = desc.value;
},
$Symbol = "function" == typeof Symbol ? Symbol : {},
iteratorSymbol = $Symbol.iterator || "@@iterator",
asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
function define(obj, key, value) {
return Object.defineProperty(obj, key, {
value: value,
enumerable: !0,
configurable: !0,
writable: !0
}), obj[key];
}
try {
define({}, "");
} catch (err) {
define = function (obj, key, value) {
return obj[key] = value;
};
}
function wrap(innerFn, outerFn, self, tryLocsList) {
var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
generator = Object.create(protoGenerator.prototype),
context = new Context(tryLocsList || []);
return defineProperty(generator, "_invoke", {
value: makeInvokeMethod(innerFn, self, context)
}), generator;
}
function tryCatch(fn, obj, arg) {
try {
return {
type: "normal",
arg: fn.call(obj, arg)
};
} catch (err) {
return {
type: "throw",
arg: err
};
}
}
exports.wrap = wrap;
var ContinueSentinel = {};
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {}
var IteratorPrototype = {};
define(IteratorPrototype, iteratorSymbol, function () {
return this;
});
var getProto = Object.getPrototypeOf,
NativeIteratorPrototype = getProto && getProto(getProto(values([])));
NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
function defineIteratorMethods(prototype) {
["next", "throw", "return"].forEach(function (method) {
define(prototype, method, function (arg) {
return this._invoke(method, arg);
});
});
}
function AsyncIterator(generator, PromiseImpl) {
function invoke(method, arg, resolve, reject) {
var record = tryCatch(generator[method], generator, arg);
if ("throw" !== record.type) {
var result = record.arg,
value = result.value;
return value && "object" == typeof value && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
invoke("next", value, resolve, reject);
}, function (err) {
invoke("throw", err, resolve, reject);
}) : PromiseImpl.resolve(value).then(function (unwrapped) {
result.value = unwrapped, resolve(result);
}, function (error) {
return invoke("throw", error, resolve, reject);
});
}
reject(record.arg);
}
var previousPromise;
defineProperty(this, "_invoke", {
value: function (method, arg) {
function callInvokeWithMethodAndArg() {
return new PromiseImpl(function (resolve, reject) {
invoke(method, arg, resolve, reject);
});
}
return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
}
});
}
function makeInvokeMethod(innerFn, self, context) {
var state = "suspendedStart";
return function (method, arg) {
if ("executing" === state) throw new Error("Generator is already running");
if ("completed" === state) {
if ("throw" === method) throw arg;
return doneResult();
}
for (context.method = method, context.arg = arg;;) {
var delegate = context.delegate;
if (delegate) {
var delegateResult = maybeInvokeDelegate(delegate, context);
if (delegateResult) {
if (delegateResult === ContinueSentinel) continue;
return delegateResult;
}
}
if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
if ("suspendedStart" === state) throw state = "completed", context.arg;
context.dispatchException(context.arg);
} else "return" === context.method && context.abrupt("return", context.arg);
state = "executing";
var record = tryCatch(innerFn, self, context);
if ("normal" === record.type) {
if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
return {
value: record.arg,
done: context.done
};
}
"throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
}
};
}
function maybeInvokeDelegate(delegate, context) {
var methodName = context.method,
method = delegate.iterator[methodName];
if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel;
var record = tryCatch(method, delegate.iterator, context.arg);
if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
var info = record.arg;
return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel);
}
function pushTryEntry(locs) {
var entry = {
tryLoc: locs[0]
};
1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
}
function resetTryEntry(entry) {
var record = entry.completion || {};
record.type = "normal", delete record.arg, entry.completion = record;
}
function Context(tryLocsList) {
this.tryEntries = [{
tryLoc: "root"
}], tryLocsList.forEach(pushTryEntry, this), this.reset(!0);
}
function values(iterable) {
if (iterable) {
var iteratorMethod = iterable[iteratorSymbol];
if (iteratorMethod) return iteratorMethod.call(iterable);
if ("function" == typeof iterable.next) return iterable;
if (!isNaN(iterable.length)) {
var i = -1,
next = function next() {
for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;
return next.value = undefined, next.done = !0, next;
};
return next.next = next;
}
}
return {
next: doneResult
};
}
function doneResult() {
return {
value: undefined,
done: !0
};
}
return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", {
value: GeneratorFunctionPrototype,
configurable: !0
}), defineProperty(GeneratorFunctionPrototype, "constructor", {
value: GeneratorFunction,
configurable: !0
}), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
var ctor = "function" == typeof genFun && genFun.constructor;
return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
}, exports.mark = function (genFun) {
return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun;
}, exports.awrap = function (arg) {
return {
__await: arg
};
}, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
return this;
}), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
void 0 === PromiseImpl && (PromiseImpl = Promise);
var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
return result.done ? result.value : iter.next();
});
}, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
return this;
}), define(Gp, "toString", function () {
return "[object Generator]";
}), exports.keys = function (val) {
var object = Object(val),
keys = [];
for (var key in object) keys.push(key);
return keys.reverse(), function next() {
for (; keys.length;) {
var key = keys.pop();
if (key in object) return next.value = key, next.done = !1, next;
}
return next.done = !0, next;
};
}, exports.values = values, Context.prototype = {
constructor: Context,
reset: function (skipTempReset) {
if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined);
},
stop: function () {
this.done = !0;
var rootRecord = this.tryEntries[0].completion;
if ("throw" === rootRecord.type) throw rootRecord.arg;
return this.rval;
},
dispatchException: function (exception) {
if (this.done) throw exception;
var context = this;
function handle(loc, caught) {
return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
}
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i],
record = entry.completion;
if ("root" === entry.tryLoc) return handle("end");
if (entry.tryLoc <= this.prev) {
var hasCatch = hasOwn.call(entry, "catchLoc"),
hasFinally = hasOwn.call(entry, "finallyLoc");
if (hasCatch && hasFinally) {
if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
} else if (hasCatch) {
if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
} else {
if (!hasFinally) throw new Error("try statement without catch or finally");
if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
}
}
}
},
abrupt: function (type, arg) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
var finallyEntry = entry;
break;
}
}
finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
var record = finallyEntry ? finallyEntry.completion : {};
return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
},
complete: function (record, afterLoc) {
if ("throw" === record.type) throw record.arg;
return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel;
},
finish: function (finallyLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
}
},
catch: function (tryLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc === tryLoc) {
var record = entry.completion;
if ("throw" === record.type) {
var thrown = record.arg;
resetTryEntry(entry);
}
return thrown;
}
}
throw new Error("illegal catch attempt");
},
delegateYield: function (iterable, resultName, nextLoc) {
return this.delegate = {
iterator: values(iterable),
resultName: resultName,
nextLoc: nextLoc
}, "next" === this.method && (this.arg = undefined), ContinueSentinel;
}
}, exports;
}
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
_setPrototypeOf(subClass, superClass);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
/**
* Common utilities
* @module glMatrix
*/
var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
if (!Math.hypot) Math.hypot = function () {
var y = 0,
i = arguments.length;
while (i--) {
y += arguments[i] * arguments[i];
}
return Math.sqrt(y);
};
/**
* 4x4 Matrix
Format: column-major, when typed out it looks like row-major
The matrices are being post multiplied.
* @module mat4
*/
/**
* Creates a new identity mat4
*
* @returns {mat4} a new 4x4 matrix
*/
function create() {
var out = new ARRAY_TYPE(16);
if (ARRAY_TYPE != Float32Array) {
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
}
out[0] = 1;
out[5] = 1;
out[10] = 1;
out[15] = 1;
return out;
}
/**
* Copy the values from one mat4 to another
*
* @param {mat4} out the receiving matrix
* @param {ReadonlyMat4} a the source matrix
* @returns {mat4} out
*/
function copy(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;
}
/**
* Inverts a mat4
*
* @param {mat4} out the receiving matrix
* @param {ReadonlyMat4} a the source matrix
* @returns {mat4} out
*/
function invert(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;
}
/**
* Multiplies two mat4s
*
* @param {mat4} out the receiving matrix
* @param {ReadonlyMat4} a the first operand
* @param {ReadonlyMat4} b the second operand
* @returns {mat4} out
*/
function multiply(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 {ReadonlyMat4} a the matrix to translate
* @param {ReadonlyVec3} v vector to translate by
* @returns {mat4} out
*/
function translate(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;
}
/**
* 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 {ReadonlyVec3} v Scaling vector
* @returns {mat4} out
*/
function fromScaling(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;
}
/**
* 3 Dimensional Vector
* @module vec3
*/
/**
* Creates a new, empty vec3
*
* @returns {vec3} a new 3D vector
*/
function create$1() {
var out = new ARRAY_TYPE(3);
if (ARRAY_TYPE != Float32Array) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
}
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(out, x, y, z) {
out[0] = x;
out[1] = y;
out[2] = z;
return out;
}
/**
* Transforms the vec3 with a mat4.
* 4th vector component is implicitly '1'
*
* @param {vec3} out the receiving vector
* @param {ReadonlyVec3} a the vector to transform
* @param {ReadonlyMat4} 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;
}
/**
* 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$1();
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;
};
}();
/**
* 2 Dimensional Vector
* @module vec2
*/
/**
* Creates a new, empty vec2
*
* @returns {vec2} a new 2D vector
*/
function create$2() {
var out = new ARRAY_TYPE(2);
if (ARRAY_TYPE != Float32Array) {
out[0] = 0;
out[1] = 0;
}
return out;
}
/**
* Normalize a vec2
*
* @param {vec2} out the receiving vector
* @param {ReadonlyVec2} a vector to normalize
* @returns {vec2} out
*/
function normalize(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 {ReadonlyVec2} a the first operand
* @param {ReadonlyVec2} 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];
}
/**
* Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
*
* @param {ReadonlyVec2} a The first vector.
* @param {ReadonlyVec2} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
function exactEquals(a, b) {
return a[0] === b[0] && a[1] === b[1];
}
/**
* 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$1 = function () {
var vec = create$2();
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;
};
}();
function rotateVector(x, y, rad) {
var X = x * Math.cos(rad) - y * Math.sin(rad);
var Y = x * Math.sin(rad) + y * Math.cos(rad);
return { x: X, y: Y };
}
/**
* Converts A (arc-to) segments to C (cubic-bezier-to).
*
* For more information of where this math came from visit:
* http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
*/
function arcToCubic(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, recursive) {
var x1 = X1;
var y1 = Y1;
var rx = RX;
var ry = RY;
var x2 = X2;
var y2 = Y2;
// for more information of where this Math came from visit:
// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
var d120 = (Math.PI * 120) / 180;
var rad = (Math.PI / 180) * (+angle || 0);
/** @type {number[]} */
var res = [];
var xy;
var f1;
var f2;
var cx;
var cy;
if (!recursive) {
xy = rotateVector(x1, y1, -rad);
x1 = xy.x;
y1 = xy.y;
xy = rotateVector(x2, y2, -rad);
x2 = xy.x;
y2 = xy.y;
var x = (x1 - x2) / 2;
var y = (y1 - y2) / 2;
var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
if (h > 1) {
h = Math.sqrt(h);
rx *= h;
ry *= h;
}
var rx2 = rx * rx;
var ry2 = ry * ry;
var k = (LAF === SF ? -1 : 1) *
Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)));
cx = (k * rx * y) / ry + (x1 + x2) / 2;
cy = (k * -ry * x) / rx + (y1 + y2) / 2;
// eslint-disable-next-line no-bitwise -- Impossible to satisfy no-bitwise
f1 = Math.asin(((((y1 - cy) / ry) * Math.pow(10, 9)) >> 0) / Math.pow(10, 9));
// eslint-disable-next-line no-bitwise -- Impossible to satisfy no-bitwise
f2 = Math.asin(((((y2 - cy) / ry) * Math.pow(10, 9)) >> 0) / Math.pow(10, 9));
f1 = x1 < cx ? Math.PI - f1 : f1;
f2 = x2 < cx ? Math.PI - f2 : f2;
if (f1 < 0)
f1 = Math.PI * 2 + f1;
if (f2 < 0)
f2 = Math.PI * 2 + f2;
if (SF && f1 > f2) {
f1 -= Math.PI * 2;
}
if (!SF && f2 > f1) {
f2 -= Math.PI * 2;
}
}
else {
f1 = recursive[0], f2 = recursive[1], cx = recursive[2], cy = recursive[3];
}
var df = f2 - f1;
if (Math.abs(df) > d120) {
var f2old = f2;
var x2old = x2;
var y2old = y2;
f2 = f1 + d120 * (SF && f2 > f1 ? 1 : -1);
x2 = cx + rx * Math.cos(f2);
y2 = cy + ry * Math.sin(f2);
res = arcToCubic(x2, y2, rx, ry, angle, 0, SF, x2old, y2old, [f2, f2old, cx, cy]);
}
df = f2 - f1;
var c1 = Math.cos(f1);
var s1 = Math.sin(f1);
var c2 = Math.cos(f2);
var s2 = Math.sin(f2);
var t = Math.tan(df / 4);
var hx = (4 / 3) * rx * t;
var hy = (4 / 3) * ry * t;
var m1 = [x1, y1];
var m2 = [x1 + hx * s1, y1 - hy * c1];
var m3 = [x2 + hx * s2, y2 - hy * c2];
var m4 = [x2, y2];
m2[0] = 2 * m1[0] - m2[0];
m2[1] = 2 * m1[1] - m2[1];
if (recursive) {
return m2.concat(m3, m4, res);
// return [...m2, ...m3, ...m4, ...res];
}
res = m2.concat(m3, m4, res);
// res = [...m2, ...m3, ...m4, ...res];
var newres = [];
for (var i = 0, ii = res.length; i < ii; i += 1) {
newres[i] = i % 2 ? rotateVector(res[i - 1], res[i], rad).y : rotateVector(res[i], res[i + 1], rad).x;
}
return newres;
}
// const TAU = Math.PI * 2;
// const mapToEllipse = (
// { x, y }: { x: number; y: number },
// rx: number,
// ry: number,
// cosphi: number,
// sinphi: number,
// centerx: number,
// centery: number,
// ) => {
// x *= rx;
// y *= ry;
// const xp = cosphi * x - sinphi * y;
// const yp = sinphi * x + cosphi * y;
// return {
// x: xp + centerx,
// y: yp + centery,
// };
// };
// const approxUnitArc = (ang1: number, ang2: number) => {
// // If 90 degree circular arc, use a constant
// // as derived from http://spencermortensen.com/articles/bezier-circle
// const a =
// ang2 === 1.5707963267948966
// ? 0.551915024494
// : ang2 === -1.5707963267948966
// ? -0.551915024494
// : (4 / 3) * Math.tan(ang2 / 4);
// const x1 = Math.cos(ang1);
// const y1 = Math.sin(ang1);
// const x2 = Math.cos(ang1 + ang2);
// const y2 = Math.sin(ang1 + ang2);
// return [
// {
// x: x1 - y1 * a,
// y: y1 + x1 * a,
// },
// {
// x: x2 + y2 * a,
// y: y2 - x2 * a,
// },
// {
// x: x2,
// y: y2,
// },
// ];
// };
// const vectorAngle = (ux: number, uy: number, vx: number, vy: number) => {
// const sign = ux * vy - uy * vx < 0 ? -1 : 1;
// let dot = ux * vx + uy * vy;
// if (dot > 1) {
// dot = 1;
// }
// if (dot < -1) {
// dot = -1;
// }
// return sign * Math.acos(dot);
// };
// const getArcCenter = (
// px: any,
// py: any,
// cx: any,
// cy: any,
// rx: number,
// ry: number,
// largeArcFlag: number,
// sweepFlag: number,
// sinphi: number,
// cosphi: number,
// pxp: number,
// pyp: number,
// ) => {
// const rxsq = Math.pow(rx, 2);
// const rysq = Math.pow(ry, 2);
// const pxpsq = Math.pow(pxp, 2);
// const pypsq = Math.pow(pyp, 2);
// let radicant = rxsq * rysq - rxsq * pypsq - rysq * pxpsq;
// if (radicant < 0) {
// radicant = 0;
// }
// radicant /= rxsq * pypsq + rysq * pxpsq;
// radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1);
// const centerxp = ((radicant * rx) / ry) * pyp;
// const centeryp = ((radicant * -ry) / rx) * pxp;
// const centerx = cosphi * centerxp - sinphi * centeryp + (px + cx) / 2;
// const centery = sinphi * centerxp + cosphi * centeryp + (py + cy) / 2;
// const vx1 = (pxp - centerxp) / rx;
// const vy1 = (pyp - centeryp) / ry;
// const vx2 = (-pxp - centerxp) / rx;
// const vy2 = (-pyp - centeryp) / ry;
// const ang1 = vectorAngle(1, 0, vx1, vy1);
// let ang2 = vectorAngle(vx1, vy1, vx2, vy2);
// if (sweepFlag === 0 && ang2 > 0) {
// ang2 -= TAU;
// }
// if (sweepFlag === 1 && ang2 < 0) {
// ang2 += TAU;
// }
// return [centerx, centery, ang1, ang2];
// };
// const arcToBezier = ({ px, py, cx, cy, rx, ry, xAxisRotation = 0, largeArcFlag = 0, sweepFlag = 0 }) => {
// const curves = [];
// if (rx === 0 || ry === 0) {
// return [{ x1: 0, y1: 0, x2: 0, y2: 0, x: cx, y: cy }];
// }
// const sinphi = Math.sin((xAxisRotation * TAU) / 360);
// const cosphi = Math.cos((xAxisRotation * TAU) / 360);
// const pxp = (cosphi * (px - cx)) / 2 + (sinphi * (py - cy)) / 2;
// const pyp = (-sinphi * (px - cx)) / 2 + (cosphi * (py - cy)) / 2;
// if (pxp === 0 && pyp === 0) {
// return [{ x1: 0, y1: 0, x2: 0, y2: 0, x: cx, y: cy }];
// }
// rx = Math.abs(rx);
// ry = Math.abs(ry);
// const lambda = Math.pow(pxp, 2) / Math.pow(rx, 2) + Math.pow(pyp, 2) / Math.pow(ry, 2);
// if (lambda > 1) {
// rx *= Math.sqrt(lambda);
// ry *= Math.sqrt(lambda);
// }
// let [centerx, centery, ang1, ang2] = getArcCenter(
// px,
// py,
// cx,
// cy,
// rx,
// ry,
// largeArcFlag,
// sweepFlag,
// sinphi,
// cosphi,
// pxp,
// pyp,
// );
// // If 'ang2' == 90.0000000001, then `ratio` will evaluate to
// // 1.0000000001. This causes `segments` to be greater than one, which is an
// // unecessary split, and adds extra points to the bezier curve. To alleviate
// // this issue, we round to 1.0 when the ratio is close to 1.0.
// let ratio = Math.abs(ang2) / (TAU / 4);
// if (Math.abs(1.0 - ratio) < 0.0000001) {
// ratio = 1.0;
// }
// const segments = Math.max(Math.ceil(ratio), 1);
// ang2 /= segments;
// for (let i = 0; i < segments; i++) {
// curves.push(approxUnitArc(ang1, ang2));
// ang1 += ang2;
// }
// return curves.map((curve) => {
// const { x: x1, y: y1 } = mapToEllipse(curve[0], rx, ry, cosphi, sinphi, centerx, centery);
// const { x: x2, y: y2 } = mapToEllipse(curve[1], rx, ry, cosphi, sinphi, centerx, centery);
// const { x, y } = mapToEllipse(curve[2], rx, ry, cosphi, sinphi, centerx, centery);
// return { x1, y1, x2, y2, x, y };
// });
// };
// export function arcToCubic(
// x1: number,
// y1: number,
// rx: number,
// ry: number,
// angle: number,
// LAF: number,
// SF: number,
// x2: number,
// y2: number,
// ) {
// const curves = arcToBezier({
// px: x1,
// py: y1,
// cx: x2,
// cy: y2,
// rx,
// ry,
// xAxisRotation: angle,
// largeArcFlag: LAF,
// sweepFlag: SF,
// });
// return curves.reduce((prev, cur) => {
// const { x1, y1, x2, y2, x, y } = cur;
// prev.push(x1, y1, x2, y2, x, y);
// return prev;
// }, [] as number[]);
// }
// isFinite,
var isNil = function (value) {
/**
* isNil(null) => true
* isNil() => true
*/
return value === null || value === undefined;
};
var toString = {}.toString;
var isType = function (value, type) { return toString.call(value) === '[object ' + type + ']'; };
var isString = (function (str) {
return isType(str, 'String');
});
var clamp = function (a, min, max) {
if (a < min) {
return min;
}
else if (a > max) {
return max;
}
return a;
};
/**
* 判断是否数字
* @return {Boolean} 是否数字
*/
var isNumber = function (value) {
return isType(value, 'Number');
};
function _inheritsLoose$1(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
_setPrototypeOf$1(subClass, superClass);
}
function _setPrototypeOf$1(o, p) {
_setPrototypeOf$1 = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$1(o, p);
}
function generatePath(context, parsedStyle) {
var r = parsedStyle.r;
context.arc(r, r, r, 0, Math.PI * 2, false);
}
function generatePath$1(context, parsedStyle) {
var rxInPixels = parsedStyle.rx,
ryInPixels = parsedStyle.ry;
var rx = rxInPixels;
var ry = ryInPixels;
// @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/ellipse
if (context.ellipse) {
context.ellipse(rx, ry, rx, ry, 0, 0, Math.PI * 2, false);
} else {
// 如果不支持,则使用圆来绘制,进行变形
var r = rx > ry ? rx : ry;
var scaleX = rx > ry ? 1 : rx / ry;
var scaleY = rx > ry ? ry / rx : 1;
context.save();
context.scale(scaleX, scaleY);
context.arc(0, 0, r, 0, Math.PI * 2);
}
}
function generatePath$2(context, parsedStyle) {
var x1 = parsedStyle.x1,
y1 = parsedStyle.y1,
x2 = parsedStyle.x2,
y2 = parsedStyle.y2,
_parsedStyle$defX = parsedStyle.defX,
defX = _parsedStyle$defX === void 0 ? 0 : _parsedStyle$defX,
_parsedStyle$defY = parsedStyle.defY,
defY = _parsedStyle$defY === void 0 ? 0 : _parsedStyle$defY,
markerStart = parsedStyle.markerStart,
markerEnd = parsedStyle.markerEnd,
markerStartOffset = parsedStyle.markerStartOffset,
markerEndOffset = parsedStyle.markerEndOffset;
var startOffsetX = 0;
var startOffsetY = 0;
var endOffsetX = 0;
var endOffsetY = 0;
var rad = 0;
var x;
var y;
if (markerStart && gLite.isDisplayObject(markerStart) && markerStartOffset) {
x = x2 - x1;
y = y2 - y1;
rad = Math.atan2(y, x);
startOffsetX = Math.cos(rad) * (markerStartOffset || 0);
startOffsetY = Math.sin(rad) * (markerStartOffset || 0);
}
if (markerEnd && gLite.isDisplayObject(markerEnd) && markerEndOffset) {
x = x1 - x2;
y = y1 - y2;
rad = Math.atan2(y, x);
endOffsetX = Math.cos(rad) * (markerEndOffset || 0);
endOffsetY = Math.sin(rad) * (markerEndOffset || 0);
}
context.moveTo(x1 - defX + startOffsetX, y1 - defY + startOffsetY);
context.lineTo(x2 - defX + endOffsetX, y2 - defY + endOffsetY);
}
function generatePath$3(context, parsedStyle) {
var _parsedStyle$defX = parsedStyle.defX,
defX = _parsedStyle$defX === void 0 ? 0 : _parsedStyle$defX,
_parsedStyle$defY = parsedStyle.defY,
defY = _parsedStyle$defY === void 0 ? 0 : _parsedStyle$defY,
markerStart = parsedStyle.markerStart,
markerEnd = parsedStyle.markerEnd,
markerStartOffset = parsedStyle.markerStartOffset,
markerEndOffset = parsedStyle.markerEndOffset;
var _parsedStyle$path = parsedStyle.path,
absolutePath = _parsedStyle$path.absolutePath,
segments = _parsedStyle$path.segments;
var startOffsetX = 0;
var startOffsetY = 0;
var endOffsetX = 0;
var endOffsetY = 0;
var rad = 0;
var x;
var y;
if (markerStart && gLite.isDisplayObject(markerStart) && markerStartOffset) {
var _markerStart$parentNo = markerStart.parentNode.getStartTangent(),
p1 = _markerStart$parentNo[0],
p2 = _markerStart$parentNo[1];
x = p1[0] - p2[0];
y = p1[1] - p2[1];
rad = Math.atan2(y, x);
startOffsetX = Math.cos(rad) * (markerStartOffset || 0);
startOffsetY = Math.sin(rad) * (markerStartOffset || 0);
}
if (markerEnd && gLite.isDisplayObject(markerEnd) && markerEndOffset) {
var _markerEnd$parentNode = markerEnd.parentNode.getEndTangent(),
_p = _markerEnd$parentNode[0],
_p2 = _markerEnd$parentNode[1];
x = _p[0] - _p2[0];
y = _p[1] - _p2[1];
rad = Math.atan2(y, x);
endOffsetX = Math.cos(rad) * (markerEndOffset || 0);
endOffsetY = Math.sin(rad) * (markerEndOffset || 0);
}
for (var i = 0; i < absolutePath.length; i++) {
var params = absolutePath[i];
var command = params[0];
var nextSegment = absolutePath[i + 1];
var useStartOffset = i === 0 && (startOffsetX !== 0 || startOffsetY !== 0);
var useEndOffset = (i === absolutePath.length - 1 || nextSegment && (nextSegment[0] === 'M' || nextSegment[0] === 'Z')) && endOffsetX !== 0 && endOffsetY !== 0;
switch (command) {
case 'M':
// Use start marker offset
if (useStartOffset) {
context.moveTo(params[1] - defX + startOffsetX, params[2] - defY + startOffsetY);
context.lineTo(params[1] - defX, params[2] - defY);
} else {
context.moveTo(params[1] - defX, params[2] - defY);
}
break;
case 'L':
if (useEndOffset) {
context.lineTo(params[1] - defX + endOffsetX, params[2] - defY + endOffsetY);
} else {
context.lineTo(params[1] - defX, params[2] - defY);
}
break;
case 'Q':
context.quadraticCurveTo(params[1] - defX, params[2] - defY, params[3] - defX, params[4] - defY);
if (useEndOffset) {
context.lineTo(params[3] - defX + endOffsetX, params[4] - defY + endOffsetY);
}
break;
case 'C':
context.bezierCurveTo(params[1] - defX, params[2] - defY, params[3] - defX, params[4] - defY, params[5] - defX, params[6] - defY);
if (useEndOffset) {
context.lineTo(params[5] - defX + endOffsetX, params[6] - defY + endOffsetY);
}
break;
case 'A':
{
var arcParams = segments[i].arcParams;
var cx = arcParams.cx,
cy = arcParams.cy,
rx = arcParams.rx,
ry = arcParams.ry,
startAngle = arcParams.startAngle,
endAngle = arcParams.endAngle,
xRotation = arcParams.xRotation,
sweepFlag = arcParams.sweepFlag;
// @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/ellipse
if (context.ellipse) {
context.ellipse(cx - defX, cy - defY, rx, ry, xRotation, startAngle, endAngle, !!(1 - sweepFlag));
} else {
// @see https://stackoverflow.com/a/47494351
var r = rx > ry ? rx : ry;
var scaleX = rx > ry ? 1 : rx / ry;
var scaleY = rx > ry ? ry / rx : 1;
context.translate(cx - defX, cy - defY);
context.rotate(xRotation);
context.scale(scaleX, scaleY);
context.arc(0, 0, r, startAngle, endAngle, !!(1 - sweepFlag));
context.scale(1 / scaleX, 1 / scaleY);
context.rotate(-xRotation);
context.translate(-(cx - defX), -(cy - defY));
}
if (useEndOffset) {
context.lineTo(params[6] - defX + endOffsetX, params[7] - defY + endOffsetY);
}
break;
}
case 'Z':
context.closePath();
break;
}
}
}
function generatePath$4(context, parsedStyle) {
var _parsedStyle$defX = parsedStyle.defX,
defX = _parsedStyle$defX === void 0 ? 0 : _parsedStyle$defX,
_parsedStyle$defY = parsedStyle.defY,
defY = _parsedStyle$defY === void 0 ? 0 : _parsedStyle$defY,
markerStart = parsedStyle.markerStart,
markerEnd = parsedStyle.markerEnd,
markerStartOffset = parsedStyle.markerStartOffset,
markerEndOffset = parsedStyle.markerEndOffset;
var points = parsedStyle.points.points;
var length = points.length;
var x1 = points[0][0] - defX;
var y1 = points[0][1] - defY;
var x2 = points[length - 1][0] - defX;
var y2 = points[length - 1][1] - defY;
var startOffsetX = 0;
var startOffsetY = 0;
var endOffsetX = 0;
var endOffsetY = 0;
var rad = 0;
var x;
var y;
if (markerStart && gLite.isDisplayObject(markerStart) && markerStartOffset) {
x = points[1][0] - points[0][0];
y = points[1][1] - points[0][1];
rad = Math.atan2(y, x);
startOffsetX = Math.cos(rad) * (markerStartOffset || 0);
startOffsetY = Math.sin(rad) * (markerStartOffset || 0);
}
if (markerEnd && gLite.isDisplayObject(markerEnd) && markerEndOffset) {
x = points[length - 1][0] - points[0][0];
y = points[length - 1][1] - points[0][1];
rad = Math.atan2(y, x);
endOffsetX = Math.cos(rad) * (markerEndOffset || 0);
endOffsetY = Math.sin(rad) * (markerEndOffset || 0);
}
context.moveTo(x1 + (startOffsetX || endOffsetX), y1 + (startOffsetY || endOffsetY));
for (var i = 1; i < length - 1; i++) {
var point = points[i];
context.lineTo(point[0] - defX, point[1] - defY);
}
context.lineTo(x2, y2);
}
function generatePath$5(context, parsedStyle) {
var _parsedStyle$defX = parsedStyle.defX,
defX = _parsedStyle$defX === void 0 ? 0 : _parsedStyle$defX,
_parsedStyle$defY = parsedStyle.defY,
defY = _parsedStyle$defY === void 0 ? 0 : _parsedStyle$defY,
markerStart = parsedStyle.markerStart,
markerEnd = parsedStyle.markerEnd,
markerStartOffset = parsedStyle.markerStartOffset,
markerEndOffset = parsedStyle.markerEndOffset;
var points = parsedStyle.points.points;
var length = points.length;
var x1 = points[0][0] - defX;
var y1 = points[0][1] - defY;
var x2 = points[length - 1][0] - defX;
var y2 = points[length - 1][1] - defY;
var startOffsetX = 0;
var startOffsetY = 0;
var endOffsetX = 0;
var endOffsetY = 0;
var rad = 0;
var x;
var y;
if (markerStart && gLite.isDisplayObject(markerStart) && markerStartOffset) {
x = points[1][0] - points[0][0];
y = points[1][1] - points[0][1];
rad = Math.atan2(y, x);
startOffsetX = Math.cos(rad) * (markerStartOffset || 0);
startOffsetY = Math.sin(rad) * (markerStartOffset || 0);
}
if (markerEnd && gLite.isDisplayObject(markerEnd) && markerEndOffset) {
x = points[length - 2][0] - points[length - 1][0];
y = points[length - 2][1] - points[length - 1][1];
rad = Math.atan2(y, x);
endOffsetX = Math.cos(rad) * (markerEndOffset || 0);
endOffsetY = Math.sin(rad) * (markerEndOffset || 0);
}
context.moveTo(x1 + startOffsetX, y1 + startOffsetY);
for (var i = 1; i < length - 1; i++) {
var point = points[i];
context.lineTo(point[0] - defX, point[1] - defY);
}
context.lineTo(x2 + endOffsetX, y2 + endOffsetY);
}
function generatePath$6(context, parsedStyle) {
var radius = parsedStyle.radius,
width = parsedStyle.width,
height = parsedStyle.height;
var w = width;
var h = height;
var hasRadius = radius && radius.some(function (r) {
return r !== 0;
});
if (!hasRadius) {
// Canvas support negative width/height of rect
context.rect(0, 0, w, h);
} else {
var signX = width > 0 ? 1 : -1;
var signY = height > 0 ? 1 : -1;
var sweepFlag = signX + signY === 0;
var _radius$map = radius.map(function (r) {
return clamp(r, 0, Math.min(Math.abs(w) / 2, Math.abs(h) / 2));
}),
tlr = _radius$map[0],
trr = _radius$map[1],
brr = _radius$map[2],
blr = _radius$map[3];
context.moveTo(signX * tlr, 0);
context.lineTo(w - signX * trr, 0);
if (trr !== 0) {
context.arc(w - signX * trr, signY * trr, trr, -signY * Math.PI / 2, signX > 0 ? 0 : Math.PI, sweepFlag);
}
context.lineTo(w, h - signY * brr);
if (brr !== 0) {
context.arc(w - signX * brr, h - signY * brr, brr, signX > 0 ? 0 : Math.PI, signY > 0 ? Math.PI / 2 : 1.5 * Math.PI, sweepFlag);
}
context.lineTo(signX * blr, h);
if (blr !== 0) {
context.arc(signX * blr, h - signY * blr, blr, signY > 0 ? Math.PI / 2 : -Math.PI / 2, signX > 0 ? Math.PI : 0, sweepFlag);
}
context.lineTo(0, signY * tlr);
if (tlr !== 0) {
context.arc(signX * tlr, signY * tlr, tlr, signX > 0 ? Math.PI : 0, signY > 0 ? Math.PI * 1.5 : Math.PI / 2, sweepFlag);
}
}
}
var Plugin = /*#__PURE__*/function (_AbstractRendererPlug) {
_inheritsLoose$1(Plugin, _AbstractRendererPlug);
function Plugin() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _AbstractRendererPlug.call.apply(_AbstractRendererPlug, [this].concat(args)) || this;
_this.name = 'canvas-path-generator';
return _this;
}
var _proto = Plugin.prototype;
_proto.init = function init() {
var _pathGeneratorFactory;
var pathGeneratorFactory = (_pathGeneratorFactory = {}, _pathGeneratorFactory[gLite.Shape.CIRCLE] = generatePath, _pathGeneratorFactory[gLite.Shape.ELLIPSE] = generatePath$1, _pathGeneratorFactory[gLite.Shape.RECT] = generatePath$6, _pathGeneratorFactory[gLite.Shape.LINE] = generatePath$2, _pathGeneratorFactory[gLite.Shape.POLYLINE] = generatePath$5, _pathGeneratorFactory[gLite.Shape.POLYGON] = generatePath$4, _pathGeneratorFactory[gLite.Shape.PATH] = generatePath$3, _pathGeneratorFactory[gLite.Shape.TEXT] = undefined, _pathGeneratorFactory[gLite.Shape.GROUP] = undefined, _pathGeneratorFactory[gLite.Shape.IMAGE] = undefined, _pathGeneratorFactory[gLite.Shape.HTML] = undefined, _pathGeneratorFactory[gLite.Shape.MESH] = undefined, _pathGeneratorFactory);
// @ts-ignore
this.context.pathGeneratorFactory = pathGeneratorFactory;
};
_proto.destroy = function destroy() {
// @ts-ignore
delete this.context.pathGeneratorFactory;
};
return Plugin;
}(gLite.AbstractRendererPlugin);
var index_esm = /*#__PURE__*/Object.freeze({
__proto__: null,
Plugin: Plugin
});
function _regeneratorRuntime$1() {
_regeneratorRuntime$1 = function _regeneratorRuntime() {
return exports;
};
var exports = {},
Op = Object.prototype,
hasOwn = Op.hasOwnProperty,
defineProperty = Object.defineProperty || function (obj, key, desc) {
obj[key] = desc.value;
},
$Symbol = "function" == typeof Symbol ? Symbol : {},
iteratorSymbol = $Symbol.iterator || "@@iterator",
asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
function define(obj, key, value) {
return Object.defineProperty(obj, key, {
value: value,
enumerable: !0,
configurable: !0,
writable: !0
}), obj[key];
}
try {
define({}, "");
} catch (err) {
define = function define(obj, key, value) {
return obj[key] = value;
};
}
function wrap(innerFn, outerFn, self, tryLocsList) {
var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
generator = Object.create(protoGenerator.prototype),
context = new Context(tryLocsList || []);
return defineProperty(generator, "_invoke", {
value: makeInvokeMethod(innerFn, self, context)
}), generator;
}
function tryCatch(fn, obj, arg) {
try {
return {
type: "normal",
arg: fn.call(obj, arg)
};
} catch (err) {
return {
type: "throw",
arg: err
};
}
}
exports.wrap = wrap;
var ContinueSentinel = {};
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {}
var IteratorPrototype = {};
define(IteratorPrototype, iteratorSymbol, function () {
return this;
});
var getProto = Object.getPrototypeOf,
NativeIteratorPrototype = getProto && getProto(getProto(values([])));
NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
function defineIteratorMethods(prototype) {
["next", "throw", "return"].forEach(function (method) {
define(prototype, method, function (arg) {
return this._invoke(method, arg);
});
});
}
function AsyncIterator(generator, PromiseImpl) {
function invoke(method, arg, resolve, reject) {
var record = tryCatch(generator[method], generator, arg);
if ("throw" !== record.type) {
var result = record.arg,
value = result.value;
return value && "object" == typeof value && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
invoke("next", value, resolve, reject);
}, function (err) {
invoke("throw", err, resolve, reject);
}) : PromiseImpl.resolve(value).then(function (unwrapped) {
result.value = unwrapped, resolve(result);
}, function (error) {
return invoke("throw", error, resolve, reject);
});
}
reject(record.arg);
}
var previousPromise;
defineProperty(this, "_invoke", {
value: function value(method, arg) {
function callInvokeWithMethodAndArg() {
return new PromiseImpl(function (resolve, reject) {
invoke(method, arg, resolve, reject);
});
}
return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
}
});
}
function makeInvokeMethod(innerFn, self, context) {
var state = "suspendedStart";
return function (method, arg) {
if ("executing" === state) throw new Error("Generator is already running");
if ("completed" === state) {
if ("throw" === method) throw arg;
return doneResult();
}
for (context.method = method, context.arg = arg;;) {
var delegate = context.delegate;
if (delegate) {
var delegateResult = maybeInvokeDelegate(delegate, context);
if (delegateResult) {
if (delegateResult === ContinueSentinel) continue;
return delegateResult;
}
}
if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
if ("suspendedStart" === state) throw state = "completed", context.arg;
context.dispatchException(context.arg);
} else "return" === context.method && context.abrupt("return", context.arg);
state = "executing";
var record = tryCatch(innerFn, self, context);
if ("normal" === record.type) {
if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
return {
value: record.arg,
done: context.done
};
}
"throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
}
};
}
function maybeInvokeDelegate(delegate, context) {
var methodName = context.method,
method = delegate.iterator[methodName];
if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel;
var record = tryCatch(method, delegate.iterator, context.arg);
if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
var info = record.arg;
return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel);
}
function pushTryEntry(locs) {
var entry = {
tryLoc: locs[0]
};
1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
}
function resetTryEntry(entry) {
var record = entry.completion || {};
record.type = "normal", delete record.arg, entry.completion = record;
}
function Context(tryLocsList) {
this.tryEntries = [{
tryLoc: "root"
}], tryLocsList.forEach(pushTryEntry, this), this.reset(!0);
}
function values(iterable) {
if (iterable) {
var iteratorMethod = iterable[iteratorSymbol];
if (iteratorMethod) return iteratorMethod.call(iterable);
if ("function" == typeof iterable.next) return iterable;
if (!isNaN(iterable.length)) {
var i = -1,
next = function next() {
for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;
return next.value = undefined, next.done = !0, next;
};
return next.next = next;
}
}
return {
next: doneResult
};
}
function doneResult() {
return {
value: undefined,
done: !0
};
}
return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", {
value: GeneratorFunctionPrototype,
configurable: !0
}), defineProperty(GeneratorFunctionPrototype, "constructor", {
value: GeneratorFunction,
configurable: !0
}), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
var ctor = "function" == typeof genFun && genFun.constructor;
return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
}, exports.mark = function (genFun) {
return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun;
}, exports.awrap = function (arg) {
return {
__await: arg
};
}, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
return this;
}), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
void 0 === PromiseImpl && (PromiseImpl = Promise);
var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
return result.done ? result.value : iter.next();
});
}, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
return this;
}), define(Gp, "toString", function () {
return "[object Generator]";
}), exports.keys = function (val) {
var object = Object(val),
keys = [];
for (var key in object) keys.push(key);
return keys.reverse(), function next() {
for (; keys.length;) {
var key = keys.pop();
if (key in object) return next.value = key, next.done = !1, next;
}
return next.done = !0, next;
};
}, exports.values = values, Context.prototype = {
constructor: Context,
reset: function reset(skipTempReset) {
if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined);
},
stop: function stop() {
this.done = !0;
var rootRecord = this.tryEntries[0].completion;
if ("throw" === rootRecord.type) throw rootRecord.arg;
return this.rval;
},
dispatchException: function dispatchException(exception) {
if (this.done) throw exception;
var context = this;
function handle(loc, caught) {
return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
}
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i],
record = entry.completion;
if ("root" === entry.tryLoc) return handle("end");
if (entry.tryLoc <= this.prev) {
var hasCatch = hasOwn.call(entry, "catchLoc"),
hasFinally = hasOwn.call(entry, "finallyLoc");
if (hasCatch && hasFinally) {
if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
} else if (hasCatch) {
if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
} else {
if (!hasFinally) throw new Error("try statement without catch or finally");
if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
}
}
}
},
abrupt: function abrupt(type, arg) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
var finallyEntry = entry;
break;
}
}
finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
var record = finallyEntry ? finallyEntry.completion : {};
return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
},
complete: function complete(record, afterLoc) {
if ("throw" === record.type) throw record.arg;
return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel;
},
finish: function finish(finallyLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
}
},
catch: function _catch(tryLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc === tryLoc) {
var record = entry.completion;
if ("throw" === record.type) {
var thrown = record.arg;
resetTryEntry(entry);
}
return thrown;
}
}
throw new Error("illegal catch attempt");
},
delegateYield: function delegateYield(iterable, resultName, nextLoc) {
return this.delegate = {
iterator: values(iterable),
resultName: resultName,
nextLoc: nextLoc
}, "next" === this.method && (this.arg = undefined), ContinueSentinel;
}
}, exports;
}
function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator$1(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
function _inheritsLoose$2(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
_setPrototypeOf$2(subClass, superClass);
}
function _setPrototypeOf$2(o, p) {
_setPrototypeOf$2 = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$2(o, p);
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _createForOfIteratorHelperLoose(o, allowArrayLike) {
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
if (it) return (it = it.call(o)).next.bind(it);
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it) o = it;
var i = 0;
return function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var tmpVec3a = create$1();
var tmpVec3b = create$1();
var tmpVec3c = create$1();
var tmpMat4 = create();
/**
* pick shape(s) with Mouse/Touch event
*
* 1. find AABB with r-tree
* 2. do math calculation with geometry in an accurate way
*/
var CanvasPickerPlugin = /*#__PURE__*/function () {
function CanvasPickerPlugin() {
var _this = this;
this.context = void 0;
this.runtime = void 0;
this.isHit = function (displayObject, position, worldTransform, isClipPath) {
// use picker for current shape's type
var pick = _this.context.pointInPathPickerFactory[displayObject.nodeName];
if (pick) {
// invert with world matrix
var invertWorldMat = invert(tmpMat4, worldTransform);
// transform client position to local space, do picking in local space
var localPosition = transformMat4(tmpVec3b, set(tmpVec3c, position[0], position[1], 0), invertWorldMat);
// account for anchor
var _displayObject$getGeo = displayObject.getGeometryBounds(),
halfExtents = _displayObject$getGeo.halfExtents;
var anchor = displayObject.parsedStyle.anchor;
localPosition[0] += (anchor && anchor[0] || 0) * halfExtents[0] * 2;
localPosition[1] += (anchor && anchor[1] || 0) * halfExtents[1] * 2;
if (pick(displayObject, new gLite.Point(localPosition[0], localPosition[1]), isClipPath, _this.isPointInPath, _this.context, _this.runtime)) {
return true;
}
}
return false;
};
/**
* use native picking method
* @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/isPointInPath
*/
this.isPointInPath = function (displayObject, position) {
var context = _this.runtime.offscreenCanvas.getOrCreateContext(_this.context.config.offscreenCanvas);
var generatePath = _this.context.pathGeneratorFactory[displayObject.nodeName];
if (generatePath) {
context.beginPath();
generatePath(context, displayObject.parsedStyle);
context.closePath();
}
return context.isPointInPath(position.x, position.y);
};
}
var _proto = CanvasPickerPlugin.prototype;
_proto.apply = function apply(context, runtime) {
var _renderingContext$roo,
_this2 = this;
var renderingService = context.renderingService,
renderingContext = context.renderingContext;
this.context = context;
this.runtime = runtime;
var document = (_renderingContext$roo = renderingContext.root) === null || _renderingContext$roo === void 0 ? void 0 : _renderingContext$roo.ownerDocument;
renderingService.hooks.pick.tapPromise(CanvasPickerPlugin.tag, /*#__PURE__*/function () {
var _ref = _asyncToGenerator$1( /*#__PURE__*/_regeneratorRuntime$1().mark(function _callee(result) {
return _regeneratorRuntime$1().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
return _context.abrupt("return", _this2.pick(document, result));
case 1:
case "end":
return _context.stop();
}
}, _callee);
}));
return function (_x) {
return _ref.apply(this, arguments);
};
}());
renderingService.hooks.pickSync.tap(CanvasPickerPlugin.tag, function (result) {
return _this2.pick(document, result);
});
};
_proto.pick = function pick(document, result) {
var topmost = result.topmost,
_result$position = result.position,
x = _result$position.x,
y = _result$position.y;
// position in world space
var position = set(tmpVec3a, x, y, 0);
// query by AABB first with spatial index(r-tree)
var hitTestList = document.elementsFromBBox(position[0], position[1], position[0], position[1]);
// test with clip path & origin shape
// @see https://github.com/antvis/g/issues/1064
var pickedDisplayObjects = [];
for (var _iterator = _createForOfIteratorHelperLoose(hitTestList), _step; !(_step = _iterator()).done;) {
var displayObject = _step.value;
var worldTransform = displayObject.getWorldTransform();
var isHitOriginShape = this.isHit(displayObject, position, worldTransform, false);
if (isHitOriginShape) {
// should look up in the ancestor node
var clipped = gLite.findClosestClipPathTarget(displayObject);
if (clipped) {
var clipPath = clipped.parsedStyle.clipPath;
var isHitClipPath = this.isHit(clipPath, position, clipPath.getWorldTransform(), true);
if (isHitClipPath) {
if (topmost) {
result.picked = [displayObject];
return result;
} else {
pickedDisplayObjects.push(displayObject);
}
}
} else {
if (topmost) {
result.picked = [displayObject];
return result;
} else {
pickedDisplayObjects.push(displayObject);
}
}
}
}
result.picked = pickedDisplayObjects;
return result;
};
return CanvasPickerPlugin;
}();
CanvasPickerPlugin.tag = 'CanvasPicker';
/**
* 两点之间的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 距离
*/
function distance(x1, y1, x2, y2) {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
function isNumberEqual(v1, v2) {
return Math.abs(v1 - v2) < 0.001;
}
function getBBoxByArray(xArr, yArr) {
var minX = Math.min.apply(Math, xArr);
var minY = Math.min.apply(Math, yArr);
var maxX = Math.max.apply(Math, xArr);
var maxY = Math.max.apply(Math, yArr);
return {
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY
};
}
function piMod(angle) {
return (angle + Math.PI * 2) % (Math.PI * 2);
}
var line = {
/**
* 计算线段的包围盒
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {object} 包围盒对象
*/
box: function box(x1, y1, x2, y2) {
return getBBoxByArray([x1, x2], [y1, y2]);
},
/**
* 线段的长度
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 距离
*/
length: function length(x1, y1, x2, y2) {
return distance(x1, y1, x2, y2);
},
/**
* 根据比例获取点
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} t 指定比例
* @return {object} 包含 x, y 的点
*/
pointAt: function pointAt(x1, y1, x2, y2, t) {
return {
x: (1 - t) * x1 + t * x2,
y: (1 - t) * y1 + t * y2
};
},
/**
* 点到线段的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} x 测试点 x
* @param {number} y 测试点 y
* @return {number} 距离
*/
pointDistance: function pointDistance(x1, y1, x2, y2, x, y) {
// 投影距离 x1, y1 的向量,假设 p, p1, p2 三个点,投影点为 a
// p1a = p1p.p1p2/|p1p2| * (p1p 的单位向量)
var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
if (cross < 0) {
return distance(x1, y1, x, y);
}
var lengthSquare = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
if (cross > lengthSquare) {
return distance(x2, y2, x, y);
}
return this.pointToLine(x1, y1, x2, y2, x, y);
},
/**
* 点到直线的距离,而不是点到线段的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} x 测试点 x
* @param {number} y 测试点 y
* @return {number} 距离
*/
pointToLine: function pointToLine(x1, y1, x2, y2, x, y) {
var d = [x2 - x1, y2 - y1];
// 如果端点相等,则判定点到点的距离
if (exactEquals(d, [0, 0])) {
return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
}
var u = [-d[1], d[0]];
normalize(u, u);
var a = [x - x1, y - y1];
return Math.abs(dot(a, u));
},
/**
* 线段的角度
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 导数
*/
tangentAngle: function tangentAngle(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
};
var EPSILON = 0.0001;
/**
* 使用牛顿切割法求最近的点
* @param {number[]} xArr 点的 x 数组
* @param {number[]} yArr 点的 y 数组
* @param {number} x 指定的点 x
* @param {number} y 指定的点 y
* @param {Function} tCallback 差值函数
*/
function nearestPoint(xArr, yArr, x, y, tCallback, length) {
var t = -1;
var d = Infinity;
var v0 = [x, y];
var segNum = 20;
if (length && length > 200) {
segNum = length / 10;
}
var increaseRate = 1 / segNum;
var interval = increaseRate / 10;
for (var i = 0; i <= segNum; i++) {
var _t = i * increaseRate;
var v1 = [tCallback.apply(void 0, xArr.concat([_t])), tCallback.apply(void 0, yArr.concat([_t]))];
var d1 = distance(v0[0], v0[1], v1[0], v1[1]);
if (d1 < d) {
t = _t;
d = d1;
}
}
// 提前终止
if (t === 0) {
return {
x: xArr[0],
y: yArr[0]
};
}
if (t === 1) {
var count = xArr.length;
return {
x: xArr[count - 1],
y: yArr[count - 1]
};
}
d = Infinity;
for (var _i = 0; _i < 32; _i++) {
if (interval < EPSILON) {
break;
}
var prev = t - interval;
var next = t + interval;
var _v = [tCallback.apply(void 0, xArr.concat([prev])), tCallback.apply(void 0, yArr.concat([prev]))];
var _d = distance(v0[0], v0[1], _v[0], _v[1]);
if (prev >= 0 && _d < d) {
t = prev;
d = _d;
} else {
var v2 = [tCallback.apply(void 0, xArr.concat([next])), tCallback.apply(void 0, yArr.concat([next]))];
var d2 = distance(v0[0], v0[1], v2[0], v2[1]);
if (next <= 1 && d2 < d) {
t = next;
d = d2;
} else {
interval *= 0.5;
}
}
}
return {
x: tCallback.apply(void 0, xArr.concat([t])),
y: tCallback.apply(void 0, yArr.concat([t]))
};
}
// 近似求解 https://community.khronos.org/t/3d-cubic-bezier-segment-length/62363/2
function snapLength(xArr, yArr) {
var totalLength = 0;
var count = xArr.length;
for (var i = 0; i < count; i++) {
var x = xArr[i];
var y = yArr[i];
var nextX = xArr[(i + 1) % count];
var nextY = yArr[(i + 1) % count];
totalLength += distance(x, y, nextX, nextY);
}
return totalLength / 2;
}
// 差值公式
function quadraticAt(p0, p1, p2, t) {
var onet = 1 - t;
return onet * onet * p0 + 2 * t * onet * p1 + t * t * p2;
}
// 求极值
function extrema(p0, p1, p2) {
var a = p0 + p2 - 2 * p1;
if (isNumberEqual(a, 0)) {
return [0.5];
}
var rst = (p0 - p1) / a;
if (rst <= 1 && rst >= 0) {
return [rst];
}
return [];
}
function derivativeAt(p0, p1, p2, t) {
return 2 * (1 - t) * (p1 - p0) + 2 * t * (p2 - p1);
}
// 分割贝塞尔曲线
function divideQuadratic(x1, y1, x2, y2, x3, y3, t) {
// 划分点
var xt = quadraticAt(x1, x2, x3, t);
var yt = quadraticAt(y1, y2, y3, t);
// 分割的第一条曲线的控制点
var controlPoint1 = line.pointAt(x1, y1, x2, y2, t);
// 分割的第二条曲线的控制点
var controlPoint2 = line.pointAt(x2, y2, x3, y3, t);
return [[x1, y1, controlPoint1.x, controlPoint1.y, xt, yt], [xt, yt, controlPoint2.x, controlPoint2.y, x3, y3]];
}
// 使用迭代法取贝塞尔曲线的长度
function quadraticLength(x1, y1, x2, y2, x3, y3, iterationCount) {
if (iterationCount === 0) {
return (distance(x1, y1, x2, y2) + distance(x2, y2, x3, y3) + distance(x1, y1, x3, y3)) / 2;
}
var quadratics = divideQuadratic(x1, y1, x2, y2, x3, y3, 0.5);
var left = quadratics[0];
var right = quadratics[1];
left.push(iterationCount - 1);
right.push(iterationCount - 1);
return quadraticLength.apply(void 0, left) + quadraticLength.apply(void 0, right);
}
var quadratic = {
box: function box(x1, y1, x2, y2, x3, y3) {
var xExtrema = extrema(x1, x2, x3)[0];
var yExtrema = extrema(y1, y2, y3)[0];
// 控制点不加入 box 的计算
var xArr = [x1, x3];
var yArr = [y1, y3];
if (xExtrema !== undefined) {
xArr.push(quadraticAt(x1, x2, x3, xExtrema));
}
if (yExtrema !== undefined) {
yArr.push(quadraticAt(y1, y2, y3, yExtrema));
}
return getBBoxByArray(xArr, yArr);
},
length: function length(x1, y1, x2, y2, x3, y3) {
return quadraticLength(x1, y1, x2, y2, x3, y3, 3);
},
nearestPoint: function nearestPoint$1(x1, y1, x2, y2, x3, y3, x0, y0) {
return nearestPoint([x1, x2, x3], [y1, y2, y3], x0, y0, quadraticAt);
},
pointDistance: function pointDistance(x1, y1, x2, y2, x3, y3, x0, y0) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0);
return distance(point.x, point.y, x0, y0);
},
interpolationAt: quadraticAt,
pointAt: function pointAt(x1, y1, x2, y2, x3, y3, t) {
return {
x: quadraticAt(x1, x2, x3, t),
y: quadraticAt(y1, y2, y3, t)
};
},
divide: function divide(x1, y1, x2, y2, x3, y3, t) {
return divideQuadratic(x1, y1, x2, y2, x3, y3, t);
},
tangentAngle: function tangentAngle(x1, y1, x2, y2, x3, y3, t) {
var dx = derivativeAt(x1, x2, x3, t);
var dy = derivativeAt(y1, y2, y3, t);
var angle = Math.atan2(dy, dx);
return piMod(angle);
}
};
function cubicAt(p0, p1, p2, p3, t) {
var onet = 1 - t; // t * t * t 的性能大概是 Math.pow(t, 3) 的三倍
return onet * onet * onet * p0 + 3 * p1 * t * onet * onet + 3 * p2 * t * t * onet + p3 * t * t * t;
}
function derivativeAt$1(p0, p1, p2, p3, t) {
var onet = 1 - t;
return 3 * (onet * onet * (p1 - p0) + 2 * onet * t * (p2 - p1) + t * t * (p3 - p2));
}
function extrema$1(p0, p1, p2, p3) {
var a = -3 * p0 + 9 * p1 - 9 * p2 + 3 * p3;
var b = 6 * p0 - 12 * p1 + 6 * p2;
var c = 3 * p1 - 3 * p0;
var extremas = [];
var t1;
var t2;
var discSqrt;
if (isNumberEqual(a, 0)) {
if (!isNumberEqual(b, 0)) {
t1 = -c / b;
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
}
} else {
var disc = b * b - 4 * a * c;
if (isNumberEqual(disc, 0)) {
extremas.push(-b / (2 * a));
} else if (disc > 0) {
discSqrt = Math.sqrt(disc);
t1 = (-b + discSqrt) / (2 * a);
t2 = (-b - discSqrt) / (2 * a);
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
if (t2 >= 0 && t2 <= 1) {
extremas.push(t2);
}
}
}
return extremas;
}
// 分割贝塞尔曲线
function divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t) {
// 划分点
var xt = cubicAt(x1, x2, x3, x4, t);
var yt = cubicAt(y1, y2, y3, y4, t);
// 计算两点之间的差值点
var c1 = line.pointAt(x1, y1, x2, y2, t);
var c2 = line.pointAt(x2, y2, x3, y3, t);
var c3 = line.pointAt(x3, y3, x4, y4, t);
var c12 = line.pointAt(c1.x, c1.y, c2.x, c2.y, t);
var c23 = line.pointAt(c2.x, c2.y, c3.x, c3.y, t);
return [[x1, y1, c1.x, c1.y, c12.x, c12.y, xt, yt], [xt, yt, c23.x, c23.y, c3.x, c3.y, x4, y4]];
}
// 使用迭代法取贝塞尔曲线的长度,二阶和三阶分开写,更清晰和便于调试
function cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, iterationCount) {
if (iterationCount === 0) {
return snapLength([x1, x2, x3, x4], [y1, y2, y3, y4]);
}
var cubics = divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, 0.5);
var left = [].concat(cubics[0], [iterationCount - 1]);
var right = [].concat(cubics[1], [iterationCount - 1]);
return cubicLength.apply(void 0, left) + cubicLength.apply(void 0, right);
}
var cubic = {
extrema: extrema$1,
box: function box(x1, y1, x2, y2, x3, y3, x4, y4) {
var xArr = [x1, x4];
var yArr = [y1, y4];
var xExtrema = extrema$1(x1, x2, x3, x4);
var yExtrema = extrema$1(y1, y2, y3, y4);
for (var i = 0; i < xExtrema.length; i++) {
xArr.push(cubicAt(x1, x2, x3, x4, xExtrema[i]));
}
for (var _i = 0; _i < yExtrema.length; _i++) {
yArr.push(cubicAt(y1, y2, y3, y4, yExtrema[_i]));
}
return getBBoxByArray(xArr, yArr);
},
length: function length(x1, y1, x2, y2, x3, y3, x4, y4) {
// 迭代三次,划分成 8 段求长度
return cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, 3);
},
nearestPoint: function nearestPoint$1(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
return nearestPoint([x1, x2, x3, x4], [y1, y2, y3, y4], x0, y0, cubicAt, length);
},
pointDistance: function pointDistance(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length);
return distance(point.x, point.y, x0, y0);
},
interpolationAt: cubicAt,
pointAt: function pointAt(x1, y1, x2, y2, x3, y3, x4, y4, t) {
return {
x: cubicAt(x1, x2, x3, x4, t),
y: cubicAt(y1, y2, y3, y4, t)
};
},
divide: function divide(x1, y1, x2, y2, x3, y3, x4, y4, t) {
return divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t);
},
tangentAngle: function tangentAngle(x1, y1, x2, y2, x3, y3, x4, y4, t) {
var dx = derivativeAt$1(x1, x2, x3, x4, t);
var dy = derivativeAt$1(y1, y2, y3, y4, t);
return piMod(Math.atan2(dy, dx));
}
};
function distance$1(x1, y1, x2, y2) {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
function inBox(minX, minY, width, height, x, y) {
return x >= minX && x <= minX + width && y >= minY && y <= minY + height;
}
function inRect(minX, minY, width, height, lineWidth, x, y) {
var halfWidth = lineWidth / 2;
// 将四个边看做矩形来检测,比边的检测算法要快
return inBox(minX - halfWidth, minY - halfWidth, width, lineWidth, x, y) ||
// 上边
inBox(minX + width - halfWidth, minY - halfWidth, lineWidth, height, x, y) ||
// 右边
inBox(minX + halfWidth, minY + height - halfWidth, width, lineWidth, x, y) ||
// 下边
inBox(minX - halfWidth, minY + halfWidth, lineWidth, height, x, y); // 左边
}
function inArc(cx, cy, r, startAngle, endAngle, lineWidth, x, y) {
var angle = (Math.atan2(y - cy, x - cx) + Math.PI * 2) % (Math.PI * 2); // 转换到 0 - 2 * Math.PI 之间
// if (angle < startAngle || angle > endAngle) {
// return false;
// }
var point = {
x: cx + r * Math.cos(angle),
y: cy + r * Math.sin(angle)
};
return distance$1(point.x, point.y, x, y) <= lineWidth / 2;
}
function inLine(x1, y1, x2, y2, lineWidth, x, y) {
var minX = Math.min(x1, x2);
var maxX = Math.max(x1, x2);
var minY = Math.min(y1, y2);
var maxY = Math.max(y1, y2);
var halfWidth = lineWidth / 2;
// 因为目前的方案是计算点到直线的距离,而有可能会在延长线上,所以要先判断是否在包围盒内
// 这种方案会在水平或者竖直的情况下载线的延长线上有半 lineWidth 的误差
if (!(x >= minX - halfWidth && x <= maxX + halfWidth && y >= minY - halfWidth && y <= maxY + halfWidth)) {
return false;
}
// 因为已经计算了包围盒,所以仅需要计算到直线的距离即可,可以显著提升性能
return line.pointToLine(x1, y1, x2, y2, x, y) <= lineWidth / 2;
}
function inPolyline(points, lineWidth, x, y, isClose) {
var count = points.length;
if (count < 2) {
return false;
}
for (var i = 0; i < count - 1; i++) {
var x1 = points[i][0];
var y1 = points[i][1];
var x2 = points[i + 1][0];
var y2 = points[i + 1][1];
if (inLine(x1, y1, x2, y2, lineWidth, x, y)) {
return true;
}
}
// 如果封闭,则计算起始点和结束点的边
if (isClose) {
var first = points[0];
var last = points[count - 1];
if (inLine(first[0], first[1], last[0], last[1], lineWidth, x, y)) {
return true;
}
}
return false;
}
// 多边形的射线检测,参考:https://blog.csdn.net/WilliamSun0122/article/details/77994526
var tolerance = 1e-6;
// 三态函数,判断两个double在eps精度下的大小关系
function dcmp(x) {
if (Math.abs(x) < tolerance) {
return 0;
}
return x < 0 ? -1 : 1;
}
// 判断点Q是否在p1和p2的线段上
function onSegment(p1, p2, q) {
if ((q[0] - p1[0]) * (p2[1] - p1[1]) === (p2[0] - p1[0]) * (q[1] - p1[1]) && Math.min(p1[0], p2[0]) <= q[0] && q[0] <= Math.max(p1[0], p2[0]) && Math.min(p1[1], p2[1]) <= q[1] && q[1] <= Math.max(p1[1], p2[1])) {
return true;
}
return false;
}
// 判断点P在多边形内-射线法
function inPolygon(points, x, y) {
var isHit = false;
var n = points.length;
if (n <= 2) {
// svg 中点小于 3 个时,不显示,也无法被拾取
return false;
}
for (var i = 0; i < n; i++) {
var p1 = points[i];
var p2 = points[(i + 1) % n];
if (onSegment(p1, p2, [x, y])) {
// 点在多边形一条边上
return true;
}
// 前一个判断min(p1[1],p2[1])