UNPKG

@foblex/2d

Version:

An Angular library for 2D geometric computations, providing classes and utilities for manipulating points, lines, vectors, rectangles, arcs, and transformations.

180 lines 26.7 kB
import { PointExtensions } from './point'; import { Arc } from './arc'; import { Line } from './line'; import { ShapeParser } from './shape-parser'; import { VectorExtensions } from './vector'; /** * The GetIntersections class is designed to find intersection points between * line segments and various geometric shapes. Currently, it supports rectangles, * circles, and ellipses. In the future, support for additional shapes will be added. */ export class GetIntersections { /** * Finds the guaranteed intersection points between a line segment and a rounded rectangle. * @param from - Starting point of the line segment. * @param to - Ending point of the line segment. * @param rect - The rect to check for intersections. * @returns An array of intersection points. */ static getRoundedRectIntersections(from, to, rect) { const segments = ShapeParser.parseRoundedRect(rect); for (const segment of segments) { if (segment instanceof Arc) { const intersections = this.intersectArcWithLine(segment, from, to); if (intersections.length > 0) { return intersections; } } else if (segment instanceof Line) { const intersection = this.intersectLineSegments(from, to, segment.point1, segment.point2); if (intersection) { return [intersection]; } } } return []; } /** * Finds the intersection points between a line segment and an SVG path. * @param path - The SVG path to check for intersections. * @param rect - The rect to check for intersections. * @returns An array of intersection points. */ static getRoundedRectIntersectionsWithSVGPath(path, rect) { const pathLength = path.getTotalLength(); const points = []; for (let i = 0; i <= pathLength; i += 1) { const point = path.getPointAtLength(i); points.push({ x: point.x, y: point.y }); } for (let i = 1; i < points.length; i++) { const intersections = this.getRoundedRectIntersections(points[i - 1], points[i], rect); if (intersections.length > 0) { return intersections; } } return []; } /** * Finds the intersection points between an arc and a line segment. * @param arc - The arc to check for intersections. * @param from - Starting point of the line segment. * @param to - Ending point of the line segment. * @returns An array of intersection points. */ static intersectArcWithLine(arc, from, to) { return this.filterPointsWithinArc(this.findEllipseLineIntersections(arc.center, arc.radiusX, arc.radiusY, from, to), arc); } /** * Finds the intersection point between two line segments. * @param p1 - Starting point of the first line segment. * @param p2 - Ending point of the first line segment. * @param p3 - Starting point of the second line segment. * @param p4 - Ending point of the second line segment. * @returns The intersection point or null if there is no intersection. */ static intersectLineSegments(p1, p2, p3, p4) { const s1_x = p2.x - p1.x; const s1_y = p2.y - p1.y; const s2_x = p4.x - p3.x; const s2_y = p4.y - p3.y; const s = (-s1_y * (p1.x - p3.x) + s1_x * (p1.y - p3.y)) / (-s2_x * s1_y + s1_x * s2_y); const t = (s2_x * (p1.y - p3.y) - s2_y * (p1.x - p3.x)) / (-s2_x * s1_y + s1_x * s2_y); if (s >= 0 && s <= 1 && t >= 0 && t <= 1) { return { x: p1.x + (t * s1_x), y: p1.y + (t * s1_y) }; } return null; } /** * Filters intersection points to retain only those within the given arc. * @param points - The points to filter. * @param arc - The arc to check against. * @returns An array of points within the arc. */ static filterPointsWithinArc(points, arc) { let { center, startAngle, endAngle } = arc; if (points.length === 0) { return points; } if (endAngle < startAngle) { [startAngle, endAngle] = [endAngle, startAngle]; } if (startAngle < 0 || endAngle < 0) { startAngle += 2.0 * Math.PI; endAngle += 2.0 * Math.PI; } const filteredPoints = []; for (const point of points) { let angle = this.normalizeAngle(VectorExtensions.angle(VectorExtensions.initialize(1, 0), VectorExtensions.initialize(point.x - center.x, point.y - center.y))); if (angle < startAngle) { angle += 2.0 * Math.PI; } if (startAngle <= angle && angle <= endAngle) { filteredPoints.push(point); } } return filteredPoints; } /** * Normalizes an angle to be within the range 0 to 2π. * @param radians - The angle in radians. * @returns The normalized angle. */ static normalizeAngle(radians) { const normal = radians % (2.0 * Math.PI); return normal < 0.0 ? (normal + (2.0 * Math.PI)) : normal; } /** * Finds the intersection points between an ellipse and a line segment. * @param center - Center of the ellipse. * @param radiusX - X radius of the ellipse. * @param radiusY - Y radius of the ellipse. * @param pointA - Starting point of the line segment. * @param pointB - Ending point of the line segment. * @returns An array of intersection points. */ static findEllipseLineIntersections(center, radiusX, radiusY, pointA, pointB) { const origin = VectorExtensions.initialize(pointA.x, pointA.y); const direction = VectorExtensions.fromPoints(pointA, pointB); const ellipseCenter = VectorExtensions.initialize(center.x, center.y); const diff = VectorExtensions.subtract(origin, ellipseCenter); const scaledDir = VectorExtensions.initialize(direction.x / (radiusX * radiusX), direction.y / (radiusY * radiusY)); const scaledDiff = VectorExtensions.initialize(diff.x / (radiusX * radiusX), diff.y / (radiusY * radiusY)); const a = VectorExtensions.dotProduct(direction, scaledDir); const b = VectorExtensions.dotProduct(direction, scaledDiff); const c = VectorExtensions.dotProduct(diff, scaledDiff) - 1.0; const discriminant = b * b - a * c; return discriminant < 0 ? [] : this.calculateIntersectionPoints(discriminant, a, b, pointA, pointB); } /** * Calculates the intersection points based on the discriminant. * @param discriminant - The discriminant value. * @param a - Coefficient 'a' in the quadratic equation. * @param b - Coefficient 'b' in the quadratic equation. * @param pointA - Starting point of the line segment. * @param pointB - Ending point of the line segment. * @returns An array of intersection points. */ static calculateIntersectionPoints(discriminant, a, b, pointA, pointB) { const points = []; if (discriminant > 0) { const root = Math.sqrt(discriminant); const t1 = (-b - root) / a; const t2 = (-b + root) / a; if (t1 >= 0 && t1 <= 1) { points.push(PointExtensions.interpolatePoints(pointA, pointB, t1)); } if (t2 >= 0 && t2 <= 1) { points.push(PointExtensions.interpolatePoints(pointA, pointB, t2)); } } else { const t = -b / a; if (t >= 0 && t <= 1) { points.push(PointExtensions.interpolatePoints(pointA, pointB, t)); } } return points; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LWludGVyc2VjdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9wcm9qZWN0cy9mb2JsZXgyZC9zcmMvZ2V0LWludGVyc2VjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFVLGVBQWUsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUVsRCxPQUFPLEVBQUUsR0FBRyxFQUFRLE1BQU0sT0FBTyxDQUFDO0FBQ2xDLE9BQU8sRUFBUyxJQUFJLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDckMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUc1Qzs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLGdCQUFnQjtJQUUzQjs7Ozs7O09BTUc7SUFDSSxNQUFNLENBQUMsMkJBQTJCLENBQUMsSUFBWSxFQUFFLEVBQVUsRUFBRSxJQUFrQjtRQUNwRixNQUFNLFFBQVEsR0FBbUIsV0FBVyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXBFLEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFO1lBQzlCLElBQUksT0FBTyxZQUFZLEdBQUcsRUFBRTtnQkFDMUIsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ25FLElBQUksYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7b0JBQzVCLE9BQU8sYUFBYSxDQUFDO2lCQUN0QjthQUNGO2lCQUFNLElBQUksT0FBTyxZQUFZLElBQUksRUFBRTtnQkFDbEMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQzFGLElBQUksWUFBWSxF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LElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNyQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMzQixNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUUzQixJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRTtnQkFDdEIsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsaUJBQWlCLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO2FBQ3BFO1lBQ0QsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUU7Z0JBQ3RCLE1BQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQzthQUNwRTtTQUNGO2FBQU07WUFDTCxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ3BCLE1BQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUNuRTtTQUNGO1FBRUQsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSVBvaW50LCBQb2ludEV4dGVuc2lvbnMgfSBmcm9tICcuL3BvaW50JztcbmltcG9ydCB7IElSb3VuZGVkUmVjdCB9IGZyb20gJy4vcm91bmRlZC1yZWN0JztcbmltcG9ydCB7IEFyYywgSUFyYyB9IGZyb20gJy4vYXJjJztcbmltcG9ydCB7IElMaW5lLCBMaW5lIH0gZnJvbSAnLi9saW5lJztcbmltcG9ydCB7IFNoYXBlUGFyc2VyIH0gZnJvbSAnLi9zaGFwZS1wYXJzZXInO1xuaW1wb3J0IHsgVmVjdG9yRXh0ZW5zaW9ucyB9IGZyb20gJy4vdmVjdG9yJztcblxuXG4vKipcbiAqIFRoZSBHZXRJbnRlcnNlY3Rpb25zIGNsYXNzIGlzIGRlc2lnbmVkIHRvIGZpbmQgaW50ZXJzZWN0aW9uIHBvaW50cyBiZXR3ZWVuXG4gKiBsaW5lIHNlZ21lbnRzIGFuZCB2YXJpb3VzIGdlb21ldHJpYyBzaGFwZXMuIEN1cnJlbnRseSwgaXQgc3VwcG9ydHMgcmVjdGFuZ2xlcyxcbiAqIGNpcmNsZXMsIGFuZCBlbGxpcHNlcy4gSW4gdGhlIGZ1dHVyZSwgc3VwcG9ydCBmb3IgYWRkaXRpb25hbCBzaGFwZXMgd2lsbCBiZSBhZGRlZC5cbiAqL1xuZXhwb3J0IGNsYXNzIEdldEludGVyc2VjdGlvbnMge1xuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgZ3VhcmFudGVlZCBpbnRlcnNlY3Rpb24gcG9pbnRzIGJldHdlZW4gYSBsaW5lIHNlZ21lbnQgYW5kIGEgcm91bmRlZCByZWN0YW5nbGUuXG4gICAqIEBwYXJhbSBmcm9tIC0gU3RhcnRpbmcgcG9pbnQgb2YgdGhlIGxpbmUgc2VnbWVudC5cbiAgICogQHBhcmFtIHRvIC0gRW5kaW5nIHBvaW50IG9mIHRoZSBsaW5lIHNlZ21lbnQuXG4gICAqIEBwYXJhbSByZWN0IC0gVGhlIHJlY3QgdG8gY2hlY2sgZm9yIGludGVyc2VjdGlvbnMuXG4gICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIGludGVyc2VjdGlvbiBwb2ludHMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGdldFJvdW5kZWRSZWN0SW50ZXJzZWN0aW9ucyhmcm9tOiBJUG9pbnQsIHRvOiBJUG9pbnQsIHJlY3Q6IElSb3VuZGVkUmVjdCk6IElQb2ludFtdIHtcbiAgICBjb25zdCBzZWdtZW50czogKEFyYyB8IExpbmUpW10gPSBTaGFwZVBhcnNlci5wYXJzZVJvdW5kZWRSZWN0KHJlY3QpO1xuXG4gICAgZm9yIChjb25zdCBzZWdtZW50IG9mIHNlZ21lbnRzKSB7XG4gICAgICBpZiAoc2VnbWVudCBpbnN0YW5jZW9mIEFyYykge1xuICAgICAgICBjb25zdCBpbnRlcnNlY3Rpb25zID0gdGhpcy5pbnRlcnNlY3RBcmNXaXRoTGluZShzZWdtZW50LCBmcm9tLCB0byk7XG4gICAgICAgIGlmIChpbnRlcnNlY3Rpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICByZXR1cm4gaW50ZXJzZWN0aW9ucztcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChzZWdtZW50IGluc3RhbmNlb2YgTGluZSkge1xuICAgICAgICBjb25zdCBpbnRlcnNlY3Rpb24gPSB0aGlzLmludGVyc2VjdExpbmVTZWdtZW50cyhmcm9tLCB0bywgc2VnbWVudC5wb2ludDEsIHNlZ21lbnQucG9pbnQyKTtcbiAgICAgICAgaWYgKGludGVyc2VjdGlvbikge1xuICAgICAgICAgIHJldHVybiBbIGludGVyc2VjdGlvbiBdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIHRoZSBpbnRlcnNlY3Rpb24gcG9pbnRzIGJldHdlZW4gYSBsaW5lIHNlZ21lbnQgYW5kIGFuIFNWRyBwYXRoLlxuICAgKiBAcGFyYW0gcGF0aCAtIFRoZSBTVkcgcGF0aCB0byBjaGVjayBmb3IgaW50ZXJzZWN0aW9ucy5cbiAgICogQHBhcmFtIHJlY3QgLSBUaGUgcmVjdCB0byBjaGVjayBmb3IgaW50ZXJzZWN0aW9ucy5cbiAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgaW50ZXJzZWN0aW9uIHBvaW50cy5cbiAgICovXG5cbiAgcHVibGljIHN0YXRpYyBnZXRSb3VuZGVkUmVjdEludGVyc2VjdGlvbnNXaXRoU1ZHUGF0aChwYXRoOiBTVkdQYXRoRWxlbWVudCwgcmVjdDogSVJvdW5kZWRSZWN0KTogSVBvaW50W10ge1xuICAgIGNvbnN0IHBhdGhMZW5ndGggPSBwYXRoLmdldFRvdGFsTGVuZ3RoKCk7XG4gICAgY29uc3QgcG9pbnRzID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8PSBwYXRoTGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgIGNvbnN0IHBvaW50ID0gcGF0aC5nZXRQb2ludEF0TGVuZ3RoKGkpO1xuICAgICAgcG9pbnRzLnB1c2goeyB4OiBwb2ludC54LCB5OiBwb2ludC55IH0pO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBpbnRlcnNlY3Rpb25zID0gdGhpcy5nZXRSb3VuZGVkUmVjdEludGVyc2VjdGlvbnMocG9pbnRzW2kgLSAxXSwgcG9pbnRzW2ldLCByZWN0KTtcbiAgICAgIGlmIChpbnRlcnNlY3Rpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmV0dXJuIGludGVyc2VjdGlvbnM7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgaW50ZXJzZWN0aW9uIHBvaW50cyBiZXR3ZWVuIGFuIGFyYyBhbmQgYSBsaW5lIHNlZ21lbnQuXG4gICAqIEBwYXJhbSBhcmMgLSBUaGUgYXJjIHRvIGNoZWNrIGZvciBpbnRlcnNlY3Rpb25zLlxuICAgKiBAcGFyYW0gZnJvbSAtIFN0YXJ0aW5nIHBvaW50IG9mIHRoZSBsaW5lIHNlZ21lbnQuXG4gICAqIEBwYXJhbSB0byAtIEVuZGluZyBwb2ludCBvZiB0aGUgbGluZSBzZWdtZW50LlxuICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiBpbnRlcnNlY3Rpb24gcG9pbnRzLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgaW50ZXJzZWN0QXJjV2l0aExpbmUoYXJjOiBJQXJjLCBmcm9tOiBJUG9pbnQsIHRvOiBJUG9pbnQpOiBJUG9pbnRbXSB7XG4gICAgcmV0dXJuIHRoaXMuZmlsdGVyUG9pbnRzV2l0aGluQXJjKFxuICAgICAgdGhpcy5maW5kRWxsaXBzZUxpbmVJbnRlcnNlY3Rpb25zKGFyYy5jZW50ZXIsIGFyYy5yYWRpdXNYLCBhcmMucmFkaXVzWSwgZnJvbSwgdG8pLFxuICAgICAgYXJjXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgaW50ZXJzZWN0aW9uIHBvaW50IGJldHdlZW4gdHdvIGxpbmUgc2VnbWVudHMuXG4gICAqIEBwYXJhbSBwMSAtIFN0YXJ0aW5nIHBvaW50IG9mIHRoZSBmaXJzdCBsaW5lIHNlZ21lbnQuXG4gICAqIEBwYXJhbSBwMiAtIEVuZGluZyBwb2ludCBvZiB0aGUgZmlyc3QgbGluZSBzZWdtZW50LlxuICAgKiBAcGFyYW0gcDMgLSBTdGFydGluZyBwb2ludCBvZiB0aGUgc2Vjb25kIGxpbmUgc2VnbWVudC5cbiAgICogQHBhcmFtIHA0IC0gRW5kaW5nIHBvaW50IG9mIHRoZSBzZWNvbmQgbGluZSBzZWdtZW50LlxuICAgKiBAcmV0dXJucyBUaGUgaW50ZXJzZWN0aW9uIHBvaW50IG9yIG51bGwgaWYgdGhlcmUgaXMgbm8gaW50ZXJzZWN0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgaW50ZXJzZWN0TGluZVNlZ21lbnRzKHAxOiBJUG9pbnQsIHAyOiBJUG9pbnQsIHAzOiBJUG9pbnQsIHA0OiBJUG9pbnQpOiBJUG9pbnQgfCBudWxsIHtcbiAgICBjb25zdCBzMV94ID0gcDIueCAtIHAxLng7XG4gICAgY29uc3QgczFfeSA9IHAyLnkgLSBwMS55O1xuICAgIGNvbnN0IHMyX3ggPSBwNC54IC0gcDMueDtcbiAgICBjb25zdCBzMl95ID0gcDQueSAtIHAzLnk7XG5cbiAgICBjb25zdCBzID0gKC1zMV95ICogKHAxLnggLSBwMy54KSArIHMxX3ggKiAocDEueSAtIHAzLnkpKSAvICgtczJfeCAqIHMxX3kgKyBzMV94ICogczJfeSk7XG4gICAgY29uc3QgdCA9IChzMl94ICogKHAxLnkgLSBwMy55KSAtIHMyX3kgKiAocDEueCAtIHAzLngpKSAvICgtczJfeCAqIHMxX3kgKyBzMV94ICogczJfeSk7XG5cbiAgICBpZiAocyA+PSAwICYmIHMgPD0gMSAmJiB0ID49IDAgJiYgdCA8PSAxKSB7XG4gICAgICByZXR1cm4geyB4OiBwMS54ICsgKHQgKiBzMV94KSwgeTogcDEueSArICh0ICogczFfeSkgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaWx0ZXJzIGludGVyc2VjdGlvbiBwb2ludHMgdG8gcmV0YWluIG9ubHkgdGhvc2Ugd2l0aGluIHRoZSBnaXZlbiBhcmMuXG4gICAqIEBwYXJhbSBwb2ludHMgLSBUaGUgcG9pbnRzIHRvIGZpbHRlci5cbiAgICogQHBhcmFtIGFyYyAtIFRoZSBhcmMgdG8gY2hlY2sgYWdhaW5zdC5cbiAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgcG9pbnRzIHdpdGhpbiB0aGUgYXJjLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZmlsdGVyUG9pbnRzV2l0aGluQXJjKHBvaW50czogSVBvaW50W10sIGFyYzogSUFyYyk6IElQb2ludFtdIHtcbiAgICBsZXQgeyBjZW50ZXIsIHN0YXJ0QW5nbGUsIGVuZEFuZ2xlIH0gPSBhcmM7XG5cbiAgICBpZiAocG9pbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHBvaW50cztcbiAgICB9XG5cbiAgICBpZiAoZW5kQW5nbGUgPCBzdGFydEFuZ2xlKSB7XG4gICAgICBbIHN0YXJ0QW5nbGUsIGVuZEFuZ2xlIF0gPSBbIGVuZEFuZ2xlLCBzdGFydEFuZ2xlIF07XG4gICAgfVxuXG4gICAgaWYgKHN0YXJ0QW5nbGUgPCAwIHx8IGVuZEFuZ2xlIDwgMCkge1xuICAgICAgc3RhcnRBbmdsZSArPSAyLjAgKiBNYXRoLlBJO1xuICAgICAgZW5kQW5nbGUgKz0gMi4wICogTWF0aC5QSTtcbiAgICB9XG5cbiAgICBjb25zdCBmaWx0ZXJlZFBvaW50czogSVBvaW50W10gPSBbXTtcblxuICAgIGZvciAoY29uc3QgcG9pbnQgb2YgcG9pbnRzKSB7XG4gICAgICBsZXQgYW5nbGUgPSB0aGlzLm5vcm1hbGl6ZUFuZ2xlKFxuICAgICAgICBWZWN0b3JFeHRlbnNpb25zLmFuZ2xlKFxuICAgICAgICAgIFZlY3RvckV4dGVuc2lvbnMuaW5pdGlhbGl6ZSgxLCAwKSxcbiAgICAgICAgICBWZWN0b3JFeHRlbnNpb25zLmluaXRpYWxpemUocG9pbnQueCAtIGNlbnRlci54LCBwb2ludC55IC0gY2VudGVyLnkpXG4gICAgICAgIClcbiAgICAgICk7XG5cbiAgICAgIGlmIChhbmdsZSA8IHN0YXJ0QW5nbGUpIHtcbiAgICAgICAgYW5nbGUgKz0gMi4wICogTWF0aC5QSTtcbiAgICAgIH1cblxuICAgICAgaWYgKHN0YXJ0QW5nbGUgPD0gYW5nbGUgJiYgYW5nbGUgPD0gZW5kQW5nbGUpIHtcbiAgICAgICAgZmlsdGVyZWRQb2ludHMucHVzaChwb2ludCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpbHRlcmVkUG9pbnRzO1xuICB9XG5cbiAgLyoqXG4gICAqIE5vcm1hbGl6ZXMgYW4gYW5nbGUgdG8gYmUgd2l0aGluIHRoZSByYW5nZSAwIHRvIDLPgC5cbiAgICogQHBhcmFtIHJhZGlhbnMgLSBUaGUgYW5nbGUgaW4gcmFkaWFucy5cbiAgICogQHJldHVybnMgVGhlIG5vcm1hbGl6ZWQgYW5nbGUuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBub3JtYWxpemVBbmdsZShyYWRpYW5zOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IG5vcm1hbCA9IHJhZGlhbnMgJSAoMi4wICogTWF0aC5QSSk7XG4gICAgcmV0dXJuIG5vcm1hbCA8IDAuMCA/IChub3JtYWwgKyAoMi4wICogTWF0aC5QSSkpIDogbm9ybWFsO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIHRoZSBpbnRlcnNlY3Rpb24gcG9pbnRzIGJldHdlZW4gYW4gZWxsaXBzZSBhbmQgYSBsaW5lIHNlZ21lbnQuXG4gICAqIEBwYXJhbSBjZW50ZXIgLSBDZW50ZXIgb2YgdGhlIGVsbGlwc2UuXG4gICAqIEBwYXJhbSByYWRpdXNYIC0gWCByYWRpdXMgb2YgdGhlIGVsbGlwc2UuXG4gICAqIEBwYXJhbSByYWRpdXNZIC0gWSByYWRpdXMgb2YgdGhlIGVsbGlwc2UuXG4gICAqIEBwYXJhbSBwb2ludEEgLSBTdGFydGluZyBwb2ludCBvZiB0aGUgbGluZSBzZWdtZW50LlxuICAgKiBAcGFyYW0gcG9pbnRCIC0gRW5kaW5nIHBvaW50IG9mIHRoZSBsaW5lIHNlZ21lbnQuXG4gICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIGludGVyc2VjdGlvbiBwb2ludHMuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBmaW5kRWxsaXBzZUxpbmVJbnRlcnNlY3Rpb25zKGNlbnRlcjogSVBvaW50LCByYWRpdXNYOiBudW1iZXIsIHJhZGl1c1k6IG51bWJlciwgcG9pbnRBOiBJUG9pbnQsIHBvaW50QjogSVBvaW50KTogSVBvaW50W10ge1xuICAgIGNvbnN0IG9yaWdpbiA9IFZlY3RvckV4dGVuc2lvbnMuaW5pdGlhbGl6ZShwb2ludEEueCwgcG9pbnRBLnkpO1xuICAgIGNvbnN0IGRpcmVjdGlvbiA9IFZlY3RvckV4dGVuc2lvbnMuZnJvbVBvaW50cyhwb2ludEEsIHBvaW50Qik7XG4gICAgY29uc3QgZWxsaXBzZUNlbnRlciA9IFZlY3RvckV4dGVuc2lvbnMuaW5pdGlhbGl6ZShjZW50ZXIueCwgY2VudGVyLnkpO1xuICAgIGNvbnN0IGRpZmYgPSBWZWN0b3JFeHRlbnNpb25zLnN1YnRyYWN0KG9yaWdpbiwgZWxsaXBzZUNlbnRlcik7XG4gICAgY29uc3Qgc2NhbGVkRGlyID0gVmVjdG9yRXh0ZW5zaW9ucy5pbml0aWFsaXplKGRpcmVjdGlvbi54IC8gKHJhZGl1c1ggKiByYWRpdXNYKSwgZGlyZWN0aW9uLnkgLyAocmFkaXVzWSAqIHJhZGl1c1kpKTtcbiAgICBjb25zdCBzY2FsZWREaWZmID0gVmVjdG9yRXh0ZW5zaW9ucy5pbml0aWFsaXplKGRpZmYueCAvIChyYWRpdXNYICogcmFkaXVzWCksIGRpZmYueSAvIChyYWRpdXNZICogcmFkaXVzWSkpO1xuXG4gICAgY29uc3QgYSA9IFZlY3RvckV4dGVuc2lvbnMuZG90UHJvZHVjdChkaXJlY3Rpb24sIHNjYWxlZERpcik7XG4gICAgY29uc3QgYiA9IFZlY3RvckV4dGVuc2lvbnMuZG90UHJvZHVjdChkaXJlY3Rpb24sIHNjYWxlZERpZmYpO1xuICAgIGNvbnN0IGMgPSBWZWN0b3JFeHRlbnNpb25zLmRvdFByb2R1Y3QoZGlmZiwgc2NhbGVkRGlmZikgLSAxLjA7XG4gICAgY29uc3QgZGlzY3JpbWluYW50ID0gYiAqIGIgLSBhICogYztcblxuICAgIHJldHVybiBkaXNjcmltaW5hbnQgPCAwID8gW10gOiB0aGlzLmNhbGN1bGF0ZUludGVyc2VjdGlvblBvaW50cyhkaXNjcmltaW5hbnQsIGEsIGIsIHBvaW50QSwgcG9pbnRCKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGVzIHRoZSBpbnRlcnNlY3Rpb24gcG9pbnRzIGJhc2VkIG9uIHRoZSBkaXNjcmltaW5hbnQuXG4gICAqIEBwYXJhbSBkaXNjcmltaW5hbnQgLSBUaGUgZGlzY3JpbWluYW50IHZhbHVlLlxuICAgKiBAcGFyYW0gYSAtIENvZWZmaWNpZW50ICdhJyBpbiB0aGUgcXVhZHJhdGljIGVxdWF0aW9uLlxuICAgKiBAcGFyYW0gYiAtIENvZWZmaWNpZW50ICdiJyBpbiB0aGUgcXVhZHJhdGljIGVxdWF0aW9uLlxuICAgKiBAcGFyYW0gcG9pbnRBIC0gU3RhcnRpbmcgcG9pbnQgb2YgdGhlIGxpbmUgc2VnbWVudC5cbiAgICogQHBhcmFtIHBvaW50QiAtIEVuZGluZyBwb2ludCBvZiB0aGUgbGluZSBzZWdtZW50LlxuICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiBpbnRlcnNlY3Rpb24gcG9pbnRzLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgY2FsY3VsYXRlSW50ZXJzZWN0aW9uUG9pbnRzKGRpc2NyaW1pbmFudDogbnVtYmVyLCBhOiBudW1iZXIsIGI6IG51bWJlciwgcG9pbnRBOiBJUG9pbnQsIHBvaW50QjogSVBvaW50KTogSVBvaW50W10ge1xuICAgIGNvbnN0IHBvaW50czogSVBvaW50W10gPSBbXTtcblxuICAgIGlmIChkaXNjcmltaW5hbnQgPiAwKSB7XG4gICAgICBjb25zdCByb290ID0gTWF0aC5zcXJ0KGRpc2NyaW1pbmFudCk7XG4gICAgICBjb25zdCB0MSA9ICgtYiAtIHJvb3QpIC8gYTtcbiAgICAgIGNvbnN0IHQyID0gKC1iICsgcm9vdCkgLyBhO1xuXG4gICAgICBpZiAodDEgPj0gMCAmJiB0MSA8PSAxKSB7XG4gICAgICAgIHBvaW50cy5wdXNoKFBvaW50RXh0ZW5zaW9ucy5pbnRlcnBvbGF0ZVBvaW50cyhwb2ludEEsIHBvaW50QiwgdDEpKTtcbiAgICAgIH1cbiAgICAgIGlmICh0MiA+PSAwICYmIHQyIDw9IDEpIHtcbiAgICAgICAgcG9pbnRzLnB1c2goUG9pbnRFeHRlbnNpb25zLmludGVycG9sYXRlUG9pbnRzKHBvaW50QSwgcG9pbnRCLCB0MikpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB0ID0gLWIgLyBhO1xuICAgICAgaWYgKHQgPj0gMCAmJiB0IDw9IDEpIHtcbiAgICAgICAgcG9pbnRzLnB1c2goUG9pbnRFeHRlbnNpb25zLmludGVycG9sYXRlUG9pbnRzKHBvaW50QSwgcG9pbnRCLCB0KSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHBvaW50cztcbiAgfVxufVxuIl19