js-angusj-clipper
Version:
Polygon and line clipping and offsetting library for Javascript / Typescript - a port of Angus Johnson's clipper to WebAssembly / Asm.JS
297 lines • 35.5 kB
JavaScript
;
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.scalePaths = exports.scalePath = exports.simplifyPolygons = exports.simplifyPolygon = exports.reversePaths = exports.reversePath = exports.polyTreeToPaths = exports.pointInPolygon = exports.orientation = exports.openPathsFromPolyTree = exports.minkowskiSumPaths = exports.minkowskiSumPath = exports.minkowskiDiff = exports.closedPathsFromPolyTree = exports.cleanPolygons = exports.cleanPolygon = exports.area = void 0;
var enums_1 = require("./enums");
var nativeEnumConversion_1 = require("./native/nativeEnumConversion");
var PathsToNativePaths_1 = require("./native/PathsToNativePaths");
var PathToNativePath_1 = require("./native/PathToNativePath");
function tryDelete() {
var e_1, _a;
var objs = [];
for (var _i = 0; _i < arguments.length; _i++) {
objs[_i] = arguments[_i];
}
try {
for (var objs_1 = __values(objs), objs_1_1 = objs_1.next(); !objs_1_1.done; objs_1_1 = objs_1.next()) {
var obj = objs_1_1.value;
if (!obj.isDeleted()) {
obj.delete();
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (objs_1_1 && !objs_1_1.done && (_a = objs_1.return)) _a.call(objs_1);
}
finally { if (e_1) throw e_1.error; }
}
}
function area(path) {
// we use JS since copying structures is slower than actually doing it
var cnt = path.length;
if (cnt < 3) {
return 0;
}
var a = 0;
for (var i = 0, j = cnt - 1; i < cnt; ++i) {
a += (path[j].x + path[i].x) * (path[j].y - path[i].y);
j = i;
}
return -a * 0.5;
}
exports.area = area;
function cleanPolygon(nativeLib, path, distance) {
if (distance === void 0) { distance = 1.1415; }
var nativePath = (0, PathToNativePath_1.pathToNativePath)(nativeLib, path);
try {
nativeLib.cleanPolygon(nativePath, distance);
return (0, PathToNativePath_1.nativePathToPath)(nativeLib, nativePath, true); // frees nativePath
}
finally {
tryDelete(nativePath);
}
}
exports.cleanPolygon = cleanPolygon;
function cleanPolygons(nativeLib, paths, distance) {
if (distance === void 0) { distance = 1.1415; }
var nativePaths = (0, PathsToNativePaths_1.pathsToNativePaths)(nativeLib, paths);
try {
nativeLib.cleanPolygons(nativePaths, distance);
return (0, PathsToNativePaths_1.nativePathsToPaths)(nativeLib, nativePaths, true); // frees nativePath
}
finally {
tryDelete(nativePaths);
}
}
exports.cleanPolygons = cleanPolygons;
function addPolyNodeToPaths(polynode, nt, paths) {
var match = true;
switch (nt) {
case 1 /* NodeType.Open */:
return;
case 2 /* NodeType.Closed */:
match = !polynode.isOpen;
break;
default:
break;
}
if (polynode.contour.length > 0 && match) {
paths.push(polynode.contour);
}
for (var ii = 0, max = polynode.childs.length; ii < max; ii++) {
var pn = polynode.childs[ii];
addPolyNodeToPaths(pn, nt, paths);
}
}
function closedPathsFromPolyTree(polyTree) {
// we do this in JS since copying path is more expensive than just doing it
var result = [];
// result.Capacity = polytree.Total;
addPolyNodeToPaths(polyTree, 2 /* NodeType.Closed */, result);
return result;
}
exports.closedPathsFromPolyTree = closedPathsFromPolyTree;
function minkowskiDiff(nativeLib, poly1, poly2) {
var nativePath1 = (0, PathToNativePath_1.pathToNativePath)(nativeLib, poly1);
var nativePath2 = (0, PathToNativePath_1.pathToNativePath)(nativeLib, poly2);
var outNativePaths = new nativeLib.Paths();
try {
nativeLib.minkowskiDiff(nativePath1, nativePath2, outNativePaths);
tryDelete(nativePath1, nativePath2);
return (0, PathsToNativePaths_1.nativePathsToPaths)(nativeLib, outNativePaths, true); // frees outNativePaths
}
finally {
tryDelete(nativePath1, nativePath2, outNativePaths);
}
}
exports.minkowskiDiff = minkowskiDiff;
function minkowskiSumPath(nativeLib, pattern, path, pathIsClosed) {
var patternNativePath = (0, PathToNativePath_1.pathToNativePath)(nativeLib, pattern);
var nativePath = (0, PathToNativePath_1.pathToNativePath)(nativeLib, path);
var outNativePaths = new nativeLib.Paths();
try {
nativeLib.minkowskiSumPath(patternNativePath, nativePath, outNativePaths, pathIsClosed);
tryDelete(patternNativePath, nativePath);
return (0, PathsToNativePaths_1.nativePathsToPaths)(nativeLib, outNativePaths, true); // frees outNativePaths
}
finally {
tryDelete(patternNativePath, nativePath, outNativePaths);
}
}
exports.minkowskiSumPath = minkowskiSumPath;
function minkowskiSumPaths(nativeLib, pattern, paths, pathIsClosed) {
// TODO: im not sure if for this method we can reuse the input/output path
var patternNativePath = (0, PathToNativePath_1.pathToNativePath)(nativeLib, pattern);
var nativePaths = (0, PathsToNativePaths_1.pathsToNativePaths)(nativeLib, paths);
try {
nativeLib.minkowskiSumPaths(patternNativePath, nativePaths, nativePaths, pathIsClosed);
tryDelete(patternNativePath);
return (0, PathsToNativePaths_1.nativePathsToPaths)(nativeLib, nativePaths, true); // frees nativePaths
}
finally {
tryDelete(patternNativePath, nativePaths);
}
}
exports.minkowskiSumPaths = minkowskiSumPaths;
function openPathsFromPolyTree(polyTree) {
// we do this in JS since copying path is more expensive than just doing it
var result = [];
var len = polyTree.childs.length;
result.length = len;
var resultLength = 0;
for (var i = 0; i < len; i++) {
if (polyTree.childs[i].isOpen) {
result[resultLength++] = polyTree.childs[i].contour;
}
}
result.length = resultLength;
return result;
}
exports.openPathsFromPolyTree = openPathsFromPolyTree;
function orientation(path) {
return area(path) >= 0;
}
exports.orientation = orientation;
function pointInPolygon(point, path) {
// we do this in JS since copying path is more expensive than just doing it
// returns 0 if false, +1 if true, -1 if pt ON polygon boundary
// See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos
// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
var result = 0;
var cnt = path.length;
if (cnt < 3) {
return 0;
}
var ip = path[0];
for (var i = 1; i <= cnt; ++i) {
var ipNext = i === cnt ? path[0] : path[i];
if (ipNext.y === point.y) {
if (ipNext.x === point.x || (ip.y === point.y && ipNext.x > point.x === ip.x < point.x)) {
return -1;
}
}
if (ip.y < point.y !== ipNext.y < point.y) {
if (ip.x >= point.x) {
if (ipNext.x > point.x) {
result = 1 - result;
}
else {
var d = (ip.x - point.x) * (ipNext.y - point.y) - (ipNext.x - point.x) * (ip.y - point.y);
if (d === 0) {
return -1;
}
else if (d > 0 === ipNext.y > ip.y) {
result = 1 - result;
}
}
}
else {
if (ipNext.x > point.x) {
var d = (ip.x - point.x) * (ipNext.y - point.y) - (ipNext.x - point.x) * (ip.y - point.y);
if (d === 0) {
return -1;
}
else if (d > 0 === ipNext.y > ip.y) {
result = 1 - result;
}
}
}
}
ip = ipNext;
}
return result;
}
exports.pointInPolygon = pointInPolygon;
function polyTreeToPaths(polyTree) {
// we do this in JS since copying path is more expensive than just doing it
var result = [];
// result.Capacity = polytree.total;
addPolyNodeToPaths(polyTree, 0 /* NodeType.Any */, result);
return result;
}
exports.polyTreeToPaths = polyTreeToPaths;
function reversePath(path) {
// we use JS since copying structures is slower than actually doing it
path.reverse();
}
exports.reversePath = reversePath;
function reversePaths(paths) {
// we use JS since copying structures is slower than actually doing it
for (var i = 0, max = paths.length; i < max; i++) {
reversePath(paths[i]);
}
}
exports.reversePaths = reversePaths;
function simplifyPolygon(nativeLib, path, fillType) {
if (fillType === void 0) { fillType = enums_1.PolyFillType.EvenOdd; }
var nativePath = (0, PathToNativePath_1.pathToNativePath)(nativeLib, path);
var outNativePaths = new nativeLib.Paths();
try {
nativeLib.simplifyPolygon(nativePath, outNativePaths, (0, nativeEnumConversion_1.polyFillTypeToNative)(nativeLib, fillType));
tryDelete(nativePath);
return (0, PathsToNativePaths_1.nativePathsToPaths)(nativeLib, outNativePaths, true); // frees outNativePaths
}
finally {
tryDelete(nativePath, outNativePaths);
}
}
exports.simplifyPolygon = simplifyPolygon;
function simplifyPolygons(nativeLib, paths, fillType) {
if (fillType === void 0) { fillType = enums_1.PolyFillType.EvenOdd; }
var nativePaths = (0, PathsToNativePaths_1.pathsToNativePaths)(nativeLib, paths);
try {
nativeLib.simplifyPolygonsOverwrite(nativePaths, (0, nativeEnumConversion_1.polyFillTypeToNative)(nativeLib, fillType));
return (0, PathsToNativePaths_1.nativePathsToPaths)(nativeLib, nativePaths, true); // frees nativePaths
}
finally {
tryDelete(nativePaths);
}
}
exports.simplifyPolygons = simplifyPolygons;
function scalePath(path, scale) {
var len = path.length;
var sol = [];
sol.length = path.length;
for (var i = 0; i < len; i++) {
var p = path[i];
sol[i] = {
x: Math.round(p.x * scale),
y: Math.round(p.y * scale),
};
}
return sol;
}
exports.scalePath = scalePath;
/**
* Scales all inner paths by multiplying all its coordinates by a number and then rounding them.
*
* @param paths - Paths to scale
* @param scale - Scale multiplier
* @return {Paths} - The scaled paths
*/
function scalePaths(paths, scale) {
if (scale === 0) {
return [];
}
var len = paths.length;
var sol = [];
sol.length = len;
for (var i = 0; i < len; i++) {
sol[i] = scalePath(paths[i], scale);
}
return sol;
}
exports.scalePaths = scalePaths;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuY3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Z1bmN0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQUFBLGlDQUE2RDtBQUk3RCxzRUFBcUU7QUFDckUsa0VBQXFGO0FBQ3JGLDhEQUErRTtBQU0vRSxTQUFTLFNBQVM7O0lBQUMsY0FBMEI7U0FBMUIsVUFBMEIsRUFBMUIscUJBQTBCLEVBQTFCLElBQTBCO1FBQTFCLHlCQUEwQjs7O1FBQzNDLEtBQWtCLElBQUEsU0FBQSxTQUFBLElBQUksQ0FBQSwwQkFBQSw0Q0FBRTtZQUFuQixJQUFNLEdBQUcsaUJBQUE7WUFDWixJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxFQUFFO2dCQUNwQixHQUFHLENBQUMsTUFBTSxFQUFFLENBQUM7YUFDZDtTQUNGOzs7Ozs7Ozs7QUFDSCxDQUFDO0FBRUQsU0FBZ0IsSUFBSSxDQUFDLElBQWtCO0lBQ3JDLHNFQUFzRTtJQUN0RSxJQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3hCLElBQUksR0FBRyxHQUFHLENBQUMsRUFBRTtRQUNYLE9BQU8sQ0FBQyxDQUFDO0tBQ1Y7SUFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDVixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLEVBQUUsQ0FBQyxFQUFFO1FBQ3pDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkQsQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUNQO0lB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LENBQUMsR0FBRyxLQUFLLENBQUM7WUFDMUIsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUM7U0FDM0IsQ0FBQztLQUNIO0lBRUQsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBZkQsOEJBZUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFnQixVQUFVLENBQUMsS0FBb0IsRUFBRSxLQUFhO0lBQzVELElBQUksS0FBSyxLQUFLLENBQUMsRUFBRTtRQUNmLE9BQU8sRUFBRSxDQUFDO0tBQ1g7SUFFRCxJQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO0lBRXpCLElBQU0sR0FBRyxHQUFVLEVBQUUsQ0FBQztJQUN0QixHQUFHLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQztJQUVqQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQzVCLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0tBQ3JDO0lBRUQsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBZkQsZ0NBZUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQb2ludEluUG9seWdvblJlc3VsdCwgUG9seUZpbGxUeXBlIH0gZnJvbSBcIi4vZW51bXNcIjtcbmltcG9ydCB7IEludFBvaW50IH0gZnJvbSBcIi4vSW50UG9pbnRcIjtcbmltcG9ydCB7IE5hdGl2ZUNsaXBwZXJMaWJJbnN0YW5jZSB9IGZyb20gXCIuL25hdGl2ZS9OYXRpdmVDbGlwcGVyTGliSW5zdGFuY2VcIjtcbmltcG9ydCB7IE5hdGl2ZURlbGV0YWJsZSB9IGZyb20gXCIuL25hdGl2ZS9OYXRpdmVEZWxldGFibGVcIjtcbmltcG9ydCB7IHBvbHlGaWxsVHlwZVRvTmF0aXZlIH0gZnJvbSBcIi4vbmF0aXZlL25hdGl2ZUVudW1Db252ZXJzaW9uXCI7XG5pbXBvcnQgeyBuYXRpdmVQYXRoc1RvUGF0aHMsIHBhdGhzVG9OYXRpdmVQYXRocyB9IGZyb20gXCIuL25hdGl2ZS9QYXRoc1RvTmF0aXZlUGF0aHNcIjtcbmltcG9ydCB7IG5hdGl2ZVBhdGhUb1BhdGgsIHBhdGhUb05hdGl2ZVBhdGggfSBmcm9tIFwiLi9uYXRpdmUvUGF0aFRvTmF0aXZlUGF0aFwiO1xuaW1wb3J0IHsgUGF0aCwgUmVhZG9ubHlQYXRoIH0gZnJvbSBcIi4vUGF0aFwiO1xuaW1wb3J0IHsgUGF0aHMsIFJlYWRvbmx5UGF0aHMgfSBmcm9tIFwiLi9QYXRoc1wiO1xuaW1wb3J0IHsgUG9seU5vZGUgfSBmcm9tIFwiLi9Qb2x5Tm9kZVwiO1xuaW1wb3J0IHsgUG9seVRyZWUgfSBmcm9tIFwiLi9Qb2x5VHJlZVwiO1xuXG5mdW5jdGlvbiB0cnlEZWxldGUoLi4ub2JqczogTmF0aXZlRGVsZXRhYmxlW10pIHtcbiAgZm9yIChjb25zdCBvYmogb2Ygb2Jqcykge1xuICAgIGlmICghb2JqLmlzRGVsZXRlZCgpKSB7XG4gICAgICBvYmouZGVsZXRlKCk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcmVhKHBhdGg6IFJlYWRvbmx5UGF0aCk6IG51bWJlciB7XG4gIC8vIHdlIHVzZSBKUyBzaW5jZSBjb3B5aW5nIHN0cnVjdHVyZXMgaXMgc2xvd2VyIHRoYW4gYWN0dWFsbHkgZG9pbmcgaXRcbiAgY29uc3QgY250ID0gcGF0aC5sZW5ndGg7XG4gIGlmIChjbnQgPCAzKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgbGV0IGEgPSAwO1xuICBmb3IgKGxldCBpID0gMCwgaiA9IGNudCAtIDE7IGkgPCBjbnQ7ICsraSkge1xuICAgIGEgKz0gKHBhdGhbal0ueCArIHBhdGhbaV0ueCkgKiAocGF0aFtqXS55IC0gcGF0aFtpXS55KTtcbiAgICBqID0gaTtcbiAgfVxuICByZXR1cm4gLWEgKiAwLjU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjbGVhblBvbHlnb24oXG4gIG5hdGl2ZUxpYjogTmF0aXZlQ2xpcHBlckxpYkluc3RhbmNlLFxuICBwYXRoOiBSZWFkb25seVBhdGgsXG4gIGRpc3RhbmNlID0gMS4xNDE1XG4pOiBQYXRoIHtcbiAgY29uc3QgbmF0aXZlUGF0aCA9IHBhdGhUb05hdGl2ZVBhdGgobmF0aXZlTGliLCBwYXRoKTtcbiAgdHJ5IHtcbiAgICBuYXRpdmVMaWIuY2xlYW5Qb2x5Z29uKG5hdGl2ZVBhdGgsIGRpc3RhbmNlKTtcbiAgICByZXR1cm4gbmF0aXZlUGF0aFRvUGF0aChuYXRpdmVMaWIsIG5hdGl2ZVBhdGgsIHRydWUpOyAvLyBmcmVlcyBuYXRpdmVQYXRoXG4gIH0gZmluYWxseSB7XG4gICAgdHJ5RGVsZXRlKG5hdGl2ZVBhdGgpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjbGVhblBvbHlnb25zKFxuICBuYXRpdmVMaWI6IE5hdGl2ZUNsaXBwZXJMaWJJbnN0YW5jZSxcbiAgcGF0aHM6IFJlYWRvbmx5UGF0aHMsXG4gIGRpc3RhbmNlID0gMS4xNDE1XG4pOiBQYXRocyB7XG4gIGNvbnN0IG5hdGl2ZVBhdGhzID0gcGF0aHNUb05hdGl2ZVBhdGhzKG5hdGl2ZUxpYiwgcGF0aHMpO1xuICB0cnkge1xuICAgIG5hdGl2ZUxpYi5jbGVhblBvbHlnb25zKG5hdGl2ZVBhdGhzLCBkaXN0YW5jZSk7XG4gICAgcmV0dXJuIG5hdGl2ZVBhdGhzVG9QYXRocyhuYXRpdmVMaWIsIG5hdGl2ZVBhdGhzLCB0cnVlKTsgLy8gZnJlZXMgbmF0aXZlUGF0aFxuICB9IGZpbmFsbHkge1xuICAgIHRyeURlbGV0ZShuYXRpdmVQYXRocyk7XG4gIH1cbn1cblxuY29uc3QgZW51bSBOb2RlVHlwZSB7XG4gIEFueSxcbiAgT3BlbixcbiAgQ2xvc2VkLFxufVxuXG5mdW5jdGlvbiBhZGRQb2x5Tm9kZVRvUGF0aHMocG9seW5vZGU6IFBvbHlOb2RlLCBudDogTm9kZVR5cGUsIHBhdGhzOiBSZWFkb25seVBhdGhbXSk6IHZvaWQge1xuICBsZXQgbWF0Y2ggPSB0cnVlO1xuICBzd2l0Y2ggKG50KSB7XG4gICAgY2FzZSBOb2RlVHlwZS5PcGVuOlxuICAgICAgcmV0dXJuO1xuICAgIGNhc2UgTm9kZVR5cGUuQ2xvc2VkOlxuICAgICAgbWF0Y2ggPSAhcG9seW5vZGUuaXNPcGVuO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIGJyZWFrO1xuICB9XG5cbiAgaWYgKHBvbHlub2RlLmNvbnRvdXIubGVuZ3RoID4gMCAmJiBtYXRjaCkge1xuICAgIHBhdGhzLnB1c2gocG9seW5vZGUuY29udG91cik7XG4gIH1cbiAgZm9yIChsZXQgaWkgPSAwLCBtYXggPSBwb2x5bm9kZS5jaGlsZHMubGVuZ3RoOyBpaSA8IG1heDsgaWkrKykge1xuICAgIGNvbnN0IHBuID0gcG9seW5vZGUuY2hpbGRzW2lpXTtcbiAgICBhZGRQb2x5Tm9kZVRvUGF0aHMocG4sIG50LCBwYXRocyk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNsb3NlZFBhdGhzRnJvbVBvbHlUcmVlKHBvbHlUcmVlOiBQb2x5VHJlZSk6IFBhdGhzIHtcbiAgLy8gd2UgZG8gdGhpcyBpbiBKUyBzaW5jZSBjb3B5aW5nIHBhdGggaXMgbW9yZSBleHBlbnNpdmUgdGhhbiBqdXN0IGRvaW5nIGl0XG5cbiAgY29uc3QgcmVzdWx0OiBQYXRocyA9IFtdO1xuICAvLyByZXN1bHQuQ2FwYWNpdHkgPSBwb2x5dHJlZS5Ub3RhbDtcbiAgYWRkUG9seU5vZGVUb1BhdGhzKHBvbHlUcmVlLCBOb2RlVHlwZS5DbG9zZWQsIHJlc3VsdCk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtaW5rb3dza2lEaWZmKFxuICBuYXRpdmVMaWI6IE5hdGl2ZUNsaXBwZXJMaWJJbnN0YW5jZSxcbiAgcG9seTE6IFJlYWRvbmx5UGF0aCxcbiAgcG9seTI6IFJlYWRvbmx5UGF0aFxuKTogUGF0aHMge1xuICBjb25zdCBuYXRpdmVQYXRoMSA9IHBhdGhUb05hdGl2ZVBhdGgobmF0aXZlTGliLCBwb2x5MSk7XG4gIGNvbnN0IG5hdGl2ZVBhdGgyID0gcGF0aFRvTmF0aXZlUGF0aChuYXRpdmVMaWIsIHBvbHkyKTtcbiAgY29uc3Qgb3V0TmF0aXZlUGF0aHMgPSBuZXcgbmF0aXZlTGliLlBhdGhzKCk7XG5cbiAgdHJ5IHtcbiAgICBuYXRpdmVMaWIubWlua293c2tpRGlmZihuYXRpdmVQYXRoMSwgbmF0aXZlUGF0aDIsIG91dE5hdGl2ZVBhdGhzKTtcbiAgICB0cnlEZWxldGUobmF0aXZlUGF0aDEsIG5hdGl2ZVBhdGgyKTtcbiAgICByZXR1cm4gbmF0aXZlUGF0aHNUb1BhdGhzKG5hdGl2ZUxpYiwgb3V0TmF0aXZlUGF0aHMsIHRydWUpOyAvLyBmcmVlcyBvdXROYXRpdmVQYXRoc1xuICB9IGZpbmFsbHkge1xuICAgIHRyeURlbGV0ZShuYXRpdmVQYXRoMSwgbmF0aXZlUGF0aDIsIG91dE5hdGl2ZVBhdGhzKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbWlua293c2tpU3VtUGF0aChcbiAgbmF0aXZlTGliOiBOYXRpdmVDbGlwcGVyTGliSW5zdGFuY2UsXG4gIHBhdHRlcm46IFJlYWRvbmx5UGF0aCxcbiAgcGF0aDogUmVhZG9ubHlQYXRoLFxuICBwYXRoSXNDbG9zZWQ6IGJvb2xlYW5cbik6IFBhdGhzIHtcbiAgY29uc3QgcGF0dGVybk5hdGl2ZVBhdGggPSBwYXRoVG9OYXRpdmVQYXRoKG5hdGl2ZUxpYiwgcGF0dGVybik7XG4gIGNvbnN0IG5hdGl2ZVBhdGggPSBwYXRoVG9OYXRpdmVQYXRoKG5hdGl2ZUxpYiwgcGF0aCk7XG4gIGNvbnN0IG91dE5hdGl2ZVBhdGhzID0gbmV3IG5hdGl2ZUxpYi5QYXRocygpO1xuXG4gIHRyeSB7XG4gICAgbmF0aXZlTGliLm1pbmtvd3NraVN1bVBhdGgocGF0dGVybk5hdGl2ZVBhdGgsIG5hdGl2ZVBhdGgsIG91dE5hdGl2ZVBhdGhzLCBwYXRoSXNDbG9zZWQpO1xuICAgIHRyeURlbGV0ZShwYXR0ZXJuTmF0aXZlUGF0aCwgbmF0aXZlUGF0aCk7XG4gICAgcmV0dXJuIG5hdGl2ZVBhdGhzVG9QYXRocyhuYXRpdmVMaWIsIG91dE5hdGl2ZVBhdGhzLCB0cnVlKTsgLy8gZnJlZXMgb3V0TmF0aXZlUGF0aHNcbiAgfSBmaW5hbGx5IHtcbiAgICB0cnlEZWxldGUocGF0dGVybk5hdGl2ZVBhdGgsIG5hdGl2ZVBhdGgsIG91dE5hdGl2ZVBhdGhzKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbWlua293c2tpU3VtUGF0aHMoXG4gIG5hdGl2ZUxpYjogTmF0aXZlQ2xpcHBlckxpYkluc3RhbmNlLFxuICBwYXR0ZXJuOiBSZWFkb25seVBhdGgsXG4gIHBhdGhzOiBSZWFkb25seVBhdGhzLFxuICBwYXRoSXNDbG9zZWQ6IGJvb2xlYW5cbik6IFBhdGhzIHtcbiAgLy8gVE9ETzogaW0gbm90IHN1cmUgaWYgZm9yIHRoaXMgbWV0aG9kIHdlIGNhbiByZXVzZSB0aGUgaW5wdXQvb3V0cHV0IHBhdGhcblxuICBjb25zdCBwYXR0ZXJuTmF0aXZlUGF0aCA9IHBhdGhUb05hdGl2ZVBhdGgobmF0aXZlTGliLCBwYXR0ZXJuKTtcbiAgY29uc3QgbmF0aXZlUGF0aHMgPSBwYXRoc1RvTmF0aXZlUGF0aHMobmF0aXZlTGliLCBwYXRocyk7XG5cbiAgdHJ5IHtcbiAgICBuYXRpdmVMaWIubWlua293c2tpU3VtUGF0aHMocGF0dGVybk5hdGl2ZVBhdGgsIG5hdGl2ZVBhdGhzLCBuYXRpdmVQYXRocywgcGF0aElzQ2xvc2VkKTtcbiAgICB0cnlEZWxldGUocGF0dGVybk5hdGl2ZVBhdGgpO1xuICAgIHJldHVybiBuYXRpdmVQYXRoc1RvUGF0aHMobmF0aXZlTGliLCBuYXRpdmVQYXRocywgdHJ1ZSk7IC8vIGZyZWVzIG5hdGl2ZVBhdGhzXG4gIH0gZmluYWxseSB7XG4gICAgdHJ5RGVsZXRlKHBhdHRlcm5OYXRpdmVQYXRoLCBuYXRpdmVQYXRocyk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9wZW5QYXRoc0Zyb21Qb2x5VHJlZShwb2x5VHJlZTogUG9seVRyZWUpOiBSZWFkb25seVBhdGhbXSB7XG4gIC8vIHdlIGRvIHRoaXMgaW4gSlMgc2luY2UgY29weWluZyBwYXRoIGlzIG1vcmUgZXhwZW5zaXZlIHRoYW4ganVzdCBkb2luZyBpdFxuXG4gIGNvbnN0IHJlc3VsdCA9IFtdO1xuICBjb25zdCBsZW4gPSBwb2x5VHJlZS5jaGlsZHMubGVuZ3RoO1xuICByZXN1bHQubGVuZ3RoID0gbGVuO1xuICBsZXQgcmVzdWx0TGVuZ3RoID0gMDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgIGlmIChwb2x5VHJlZS5jaGlsZHNbaV0uaXNPcGVuKSB7XG4gICAgICByZXN1bHRbcmVzdWx0TGVuZ3RoKytdID0gcG9seVRyZWUuY2hpbGRzW2ldLmNvbnRvdXI7XG4gICAgfVxuICB9XG4gIHJlc3VsdC5sZW5ndGggPSByZXN1bHRMZW5ndGg7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvcmllbnRhdGlvbihwYXRoOiBSZWFkb25seVBhdGgpOiBib29sZWFuIHtcbiAgcmV0dXJuIGFyZWEocGF0aCkgPj0gMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBvaW50SW5Qb2x5Z29uKFxuICBwb2ludDogUmVhZG9ubHk8SW50UG9pbnQ+LFxuICBwYXRoOiBSZWFkb25seVBhdGhcbik6IFBvaW50SW5Qb2x5Z29uUmVzdWx0IHtcbiAgLy8gd2UgZG8gdGhpcyBpbiBKUyBzaW5jZSBjb3B5aW5nIHBhdGggaXMgbW9yZSBleHBlbnNpdmUgdGhhbiBqdXN0IGRvaW5nIGl0XG5cbiAgLy8gcmV0dXJucyAwIGlmIGZhbHNlLCArMSBpZiB0cnVlLCAtMSBpZiBwdCBPTiBwb2x5Z29uIGJvdW5kYXJ5XG4gIC8vIFNlZSBcIlRoZSBQb2ludCBpbiBQb2x5Z29uIFByb2JsZW0gZm9yIEFyYml0cmFyeSBQb2x5Z29uc1wiIGJ5IEhvcm1hbm4gJiBBZ2F0aG9zXG4gIC8vIGh0dHA6Ly9jaXRlc2VlcnguaXN0LnBzdS5lZHUvdmlld2RvYy9kb3dubG9hZD9kb2k9MTAuMS4xLjg4LjU0OTgmcmVwPXJlcDEmdHlwZT1wZGZcbiAgbGV0IHJlc3VsdCA9IDA7XG4gIGNvbnN0IGNudCA9IHBhdGgubGVuZ3RoO1xuICBpZiAoY250IDwgMykge1xuICAgIHJldHVybiAwO1xuICB9XG4gIGxldCBpcCA9IHBhdGhbMF07XG4gIGZvciAobGV0IGkgPSAxOyBpIDw9IGNudDsgKytpKSB7XG4gICAgY29uc3QgaXBOZXh0ID0gaSA9PT0gY250ID8gcGF0aFswXSA6IHBhdGhbaV07XG4gICAgaWYgKGlwTmV4dC55ID09PSBwb2ludC55KSB7XG4gICAgICBpZiAoaXBOZXh0LnggPT09IHBvaW50LnggfHwgKGlwLnkgPT09IHBvaW50LnkgJiYgaXBOZXh0LnggPiBwb2ludC54ID09PSBpcC54IDwgcG9pbnQueCkpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoaXAueSA8IHBvaW50LnkgIT09IGlwTmV4dC55IDwgcG9pbnQueSkge1xuICAgICAgaWYgKGlwLnggPj0gcG9pbnQueCkge1xuICAgICAgICBpZiAoaXBOZXh0LnggPiBwb2ludC54KSB7XG4gICAgICAgICAgcmVzdWx0ID0gMSAtIHJlc3VsdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBkID1cbiAgICAgICAgICAgIChpcC54IC0gcG9pbnQueCkgKiAoaXBOZXh0LnkgLSBwb2ludC55KSAtIChpcE5leHQueCAtIHBvaW50LngpICogKGlwLnkgLSBwb2ludC55KTtcbiAgICAgICAgICBpZiAoZCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgIH0gZWxzZSBpZiAoZCA+IDAgPT09IGlwTmV4dC55ID4gaXAueSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gMSAtIHJlc3VsdDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChpcE5leHQueCA+IHBvaW50LngpIHtcbiAgICAgICAgICBjb25zdCBkID1cbiAgICAgICAgICAgIChpcC54IC0gcG9pbnQueCkgKiAoaXBOZXh0LnkgLSBwb2ludC55KSAtIChpcE5leHQueCAtIHBvaW50LngpICogKGlwLnkgLSBwb2ludC55KTtcbiAgICAgICAgICBpZiAoZCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgIH0gZWxzZSBpZiAoZCA+IDAgPT09IGlwTmV4dC55ID4gaXAueSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gMSAtIHJlc3VsdDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaXAgPSBpcE5leHQ7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBvbHlUcmVlVG9QYXRocyhwb2x5VHJlZTogUG9seVRyZWUpOiBQYXRocyB7XG4gIC8vIHdlIGRvIHRoaXMgaW4gSlMgc2luY2UgY29weWluZyBwYXRoIGlzIG1vcmUgZXhwZW5zaXZlIHRoYW4ganVzdCBkb2luZyBpdFxuXG4gIGNvbnN0IHJlc3VsdDogUGF0aHMgPSBbXTtcbiAgLy8gcmVzdWx0LkNhcGFjaXR5ID0gcG9seXRyZWUudG90YWw7XG4gIGFkZFBvbHlOb2RlVG9QYXRocyhwb2x5VHJlZSwgTm9kZVR5cGUuQW55LCByZXN1bHQpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmV2ZXJzZVBhdGgocGF0aDogUGF0aCk6IHZvaWQge1xuICAvLyB3ZSB1c2UgSlMgc2luY2UgY29weWluZyBzdHJ1Y3R1cmVzIGlzIHNsb3dlciB0aGFuIGFjdHVhbGx5IGRvaW5nIGl0XG4gIHBhdGgucmV2ZXJzZSgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmV2ZXJzZVBhdGhzKHBhdGhzOiBQYXRocyk6IHZvaWQge1xuICAvLyB3ZSB1c2UgSlMgc2luY2UgY29weWluZyBzdHJ1Y3R1cmVzIGlzIHNsb3dlciB0aGFuIGFjdHVhbGx5IGRvaW5nIGl0XG4gIGZvciAobGV0IGkgPSAwLCBtYXggPSBwYXRocy5sZW5ndGg7IGkgPCBtYXg7IGkrKykge1xuICAgIHJldmVyc2VQYXRoKHBhdGhzW2ldKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2ltcGxpZnlQb2x5Z29uKFxuICBuYXRpdmVMaWI6IE5hdGl2ZUNsaXBwZXJMaWJJbnN0YW5jZSxcbiAgcGF0aDogUmVhZG9ubHlQYXRoLFxuICBmaWxsVHlwZTogUG9seUZpbGxUeXBlID0gUG9seUZpbGxUeXBlLkV2ZW5PZGRcbik6IFBhdGhzIHtcbiAgY29uc3QgbmF0aXZlUGF0aCA9IHBhdGhUb05hdGl2ZVBhdGgobmF0aXZlTGliLCBwYXRoKTtcbiAgY29uc3Qgb3V0TmF0aXZlUGF0aHMgPSBuZXcgbmF0aXZlTGliLlBhdGhzKCk7XG4gIHRyeSB7XG4gICAgbmF0aXZlTGliLnNpbXBsaWZ5UG9seWdvbihcbiAgICAgIG5hdGl2ZVBhdGgsXG4gICAgICBvdXROYXRpdmVQYXRocyxcbiAgICAgIHBvbHlGaWxsVHlwZVRvTmF0aXZlKG5hdGl2ZUxpYiwgZmlsbFR5cGUpXG4gICAgKTtcbiAgICB0cnlEZWxldGUobmF0aXZlUGF0aCk7XG4gICAgcmV0dXJuIG5hdGl2ZVBhdGhzVG9QYXRocyhuYXRpdmVMaWIsIG91dE5hdGl2ZVBhdGhzLCB0cnVlKTsgLy8gZnJlZXMgb3V0TmF0aXZlUGF0aHNcbiAgfSBmaW5hbGx5IHtcbiAgICB0cnlEZWxldGUobmF0aXZlUGF0aCwgb3V0TmF0aXZlUGF0aHMpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzaW1wbGlmeVBvbHlnb25zKFxuICBuYXRpdmVMaWI6IE5hdGl2ZUNsaXBwZXJMaWJJbnN0YW5jZSxcbiAgcGF0aHM6IFJlYWRvbmx5UGF0aHMsXG4gIGZpbGxUeXBlOiBQb2x5RmlsbFR5cGUgPSBQb2x5RmlsbFR5cGUuRXZlbk9kZFxuKTogUGF0aHMge1xuICBjb25zdCBuYXRpdmVQYXRocyA9IHBhdGhzVG9OYXRpdmVQYXRocyhuYXRpdmVMaWIsIHBhdGhzKTtcbiAgdHJ5IHtcbiAgICBuYXRpdmVMaWIuc2ltcGxpZnlQb2x5Z29uc092ZXJ3cml0ZShuYXRpdmVQYXRocywgcG9seUZpbGxUeXBlVG9OYXRpdmUobmF0aXZlTGliLCBmaWxsVHlwZSkpO1xuICAgIHJldHVybiBuYXRpdmVQYXRoc1RvUGF0aHMobmF0aXZlTGliLCBuYXRpdmVQYXRocywgdHJ1ZSk7IC8vIGZyZWVzIG5hdGl2ZVBhdGhzXG4gIH0gZmluYWxseSB7XG4gICAgdHJ5RGVsZXRlKG5hdGl2ZVBhdGhzKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2NhbGVQYXRoKHBhdGg6IFJlYWRvbmx5UGF0aCwgc2NhbGU6IG51bWJlcik6IFBhdGgge1xuICBjb25zdCBsZW4gPSBwYXRoLmxlbmd0aDtcblxuICBjb25zdCBzb2w6IFBhdGggPSBbXTtcbiAgc29sLmxlbmd0aCA9IHBhdGgubGVuZ3RoO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICBjb25zdCBwID0gcGF0aFtpXTtcbiAgICBzb2xbaV0gPSB7XG4gICAgICB4OiBNYXRoLnJvdW5kKHAueCAqIHNjYWxlKSxcbiAgICAgIHk6IE1hdGgucm91bmQocC55ICogc2NhbGUpLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4gc29sO1xufVxuXG4vKipcbiAqIFNjYWxlcyBhbGwgaW5uZXIgcGF0aHMgYnkgbXVsdGlwbHlpbmcgYWxsIGl0cyBjb29yZGluYXRlcyBieSBhIG51bWJlciBhbmQgdGhlbiByb3VuZGluZyB0aGVtLlxuICpcbiAqIEBwYXJhbSBwYXRocyAtIFBhdGhzIHRvIHNjYWxlXG4gKiBAcGFyYW0gc2NhbGUgLSBTY2FsZSBtdWx0aXBsaWVyXG4gKiBAcmV0dXJuIHtQYXRoc30gLSBUaGUgc2NhbGVkIHBhdGhzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzY2FsZVBhdGhzKHBhdGhzOiBSZWFkb25seVBhdGhzLCBzY2FsZTogbnVtYmVyKTogUGF0aHMge1xuICBpZiAoc2NhbGUgPT09IDApIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBsZW4gPSBwYXRocy5sZW5ndGg7XG5cbiAgY29uc3Qgc29sOiBQYXRocyA9IFtdO1xuICBzb2wubGVuZ3RoID0gbGVuO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICBzb2xbaV0gPSBzY2FsZVBhdGgocGF0aHNbaV0sIHNjYWxlKTtcbiAgfVxuXG4gIHJldHVybiBzb2w7XG59XG4iXX0=