@eliorar/angular-cesium
Version:
Angular library for working with Cesium.
138 lines • 19.4 kB
JavaScript
import { Injectable, Optional } from '@angular/core';
import { Cartesian2, Cartesian3, Cartographic, Math as cMath, SceneTransforms } from 'cesium';
import * as geodesy from 'geodesy';
import { LatLonEllipsoidal, Utm } from 'geodesy';
import * as i0 from "@angular/core";
import * as i1 from "../cesium/cesium.service";
const LatLonVectors = geodesy['LatLonVectors']; // doesnt exists on typings
window['geodesy'] = geodesy;
/**
* Given different types of coordinates, we provide you a service converting those types to the most common other types.
* We are using the geodesy implementation of UTM conversion. see: https://github.com/chrisveness/geodesy.
*z
* @example
* import { Component, OnInit } from '@angular/core';
* import { CoordinateConverter } from 'angular2-cesium';
*
* @Component({
* selector:'my-component',
* template:'<div>{{showCartographic}}</div>',
* providers:[CoordinateConverter]
* })
* export class MyComponent implements OnInit {
* showCartographic;
*
* constructor(private coordinateConverter:CoordinateConverter){
* }
*
* ngOnInit(){
* this.showCartographic = this.coordinateConverter.degreesToCartographic(5, 5, 5);
* }
* }
*
*/
export class CoordinateConverter {
constructor(cesiumService) {
this.cesiumService = cesiumService;
}
static cartesian3ToLatLon(cartesian3, ellipsoid) {
const cart = Cartographic.fromCartesian(cartesian3, ellipsoid);
return {
lon: cMath.toDegrees(cart.longitude),
lat: cMath.toDegrees(cart.latitude),
height: cart.height
};
}
screenToCartesian3(screenPos, addMapCanvasBoundsToPos) {
if (!this.cesiumService) {
throw new Error('ANGULAR2-CESIUM - Cesium service should be provided in order' +
' to do screen position calculations');
}
else {
const screenPosition = { ...screenPos };
if (addMapCanvasBoundsToPos) {
const mapBounds = this.cesiumService.getViewer().canvas.getBoundingClientRect();
screenPosition.x += mapBounds.left;
screenPosition.y += mapBounds.top;
}
const camera = this.cesiumService.getViewer().camera;
return camera.pickEllipsoid(screenPosition);
}
}
screenToCartographic(screenPos, ellipsoid) {
return this.cartesian3ToCartographic(this.screenToCartesian3(screenPos), ellipsoid);
}
cartesian3ToCartographic(cartesian, ellipsoid) {
return Cartographic.fromCartesian(cartesian, ellipsoid);
}
degreesToCartographic(longitude, latitude, height) {
return Cartographic.fromDegrees(longitude, latitude, height);
}
radiansToCartographic(longitude, latitude, height) {
return Cartographic.fromRadians(longitude, latitude, height);
}
degreesToUTM(longitude, latitude) {
return new LatLonEllipsoidal(latitude, longitude).toUtm();
}
UTMToDegrees(zone, hemisphereType, easting, northing) {
return this.geodesyToCesiumObject(new Utm(zone, hemisphereType, easting, northing).toLatLonE());
}
geodesyToCesiumObject(geodesyRadians) {
return {
longitude: geodesyRadians.lon,
latitude: geodesyRadians.lat,
height: geodesyRadians['height'] ? geodesyRadians['height'] : 0
};
}
/**
* middle point between two points
* @param first (latitude,longitude) in radians
* @param second (latitude,longitude) in radians
*/
midPointToCartesian3(first, second) {
const toDeg = (rad) => cMath.toDegrees(rad);
const firstPoint = new LatLonVectors(toDeg(first.latitude), toDeg(first.longitude));
const secondPoint = new LatLonVectors(toDeg(second.latitude), toDeg(second.longitude));
const middlePoint = firstPoint.midpointTo(secondPoint);
return Cartesian3.fromDegrees(middlePoint.lon, middlePoint.lat);
}
middlePointByScreen(position0, position1) {
const scene = this.cesiumService.getScene();
const screenPosition1 = SceneTransforms.wgs84ToWindowCoordinates(scene, position0);
const screenPosition2 = SceneTransforms.wgs84ToWindowCoordinates(scene, position1);
const middleScreenPoint = new Cartesian2((screenPosition2.x + screenPosition1.x) / 2.0, (screenPosition2.y + screenPosition1.y) / 2.0);
return scene.pickPosition(middleScreenPoint);
}
/**
* initial bearing between two points
*
* * @return bearing in degrees
* @param first - {latitude,longitude} in radians
* @param second - {latitude,longitude} in radians
*/
bearingTo(first, second) {
const toDeg = (rad) => cMath.toDegrees(rad);
const firstPoint = new LatLonVectors(toDeg(first.latitude), toDeg(first.longitude));
const secondPoint = new LatLonVectors(toDeg(second.latitude), toDeg(second.longitude));
const bearing = firstPoint.bearingTo(secondPoint);
return bearing;
}
/**
* initial bearing between two points
*
* @return bearing in degrees
*/
bearingToCartesian(firstCartesian3, secondCartesian3) {
const firstCart = Cartographic.fromCartesian(firstCartesian3);
const secondCart = Cartographic.fromCartesian(secondCartesian3);
return this.bearingTo(firstCart, secondCart);
}
}
CoordinateConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CoordinateConverter, deps: [{ token: i1.CesiumService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
CoordinateConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CoordinateConverter });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CoordinateConverter, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.CesiumService, decorators: [{
type: Optional
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29vcmRpbmF0ZS1jb252ZXJ0ZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItY2VzaXVtL3NyYy9saWIvYW5ndWxhci1jZXNpdW0vc2VydmljZXMvY29vcmRpbmF0ZS1jb252ZXJ0ZXIvY29vcmRpbmF0ZS1jb252ZXJ0ZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsVUFBVSxFQUFFLFFBQVEsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsSUFBSSxJQUFJLEtBQUssRUFBRSxlQUFlLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFFNUYsT0FBTyxLQUFLLE9BQU8sTUFBTSxTQUFTLENBQUM7QUFDbkMsT0FBTyxFQUFxQixpQkFBaUIsRUFBRSxHQUFHLEVBQUMsTUFBTSxTQUFTLENBQUM7OztBQUVuRSxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQywyQkFBMkI7QUFFM0UsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLE9BQU8sQ0FBQztBQUU1Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBRUgsTUFBTSxPQUFPLG1CQUFtQjtJQUM5QixZQUFnQyxhQUE2QjtRQUE3QixrQkFBYSxHQUFiLGFBQWEsQ0FBZ0I7SUFDN0QsQ0FBQztJQUVELE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxVQUFzQixFQUFFLFNBQWU7UUFDL0QsTUFBTSxJQUFJLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxVQUFVLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDL0QsT0FBTztZQUNMLEdBQUcsRUFBRSxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDcEMsR0FBRyxFQUFFLEtBQUssQ0FBQyxTQUFTLENBQUMsSUFBSSxD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S0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDcEYsTUFBTSxXQUFXLEdBQUcsSUFBSSxhQUFhLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDdkYsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUVsRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGtCQUFrQixDQUFDLGVBQTJCLEVBQUUsZ0JBQTRCO1FBQzFFLE1BQU0sU0FBUyxHQUFHLFlBQVksQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDOUQsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRWhFLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDL0MsQ0FBQzs7Z0hBL0dVLG1CQUFtQjtvSEFBbkIsbUJBQW1COzJGQUFuQixtQkFBbUI7a0JBRC9CLFVBQVU7OzBCQUVJLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdGFibGUsIE9wdGlvbmFsfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7Q2FydGVzaWFuMiwgQ2FydGVzaWFuMywgQ2FydG9ncmFwaGljLCBNYXRoIGFzIGNNYXRoLCBTY2VuZVRyYW5zZm9ybXN9IGZyb20gJ2Nlc2l1bSc7XG5pbXBvcnQge0Nlc2l1bVNlcnZpY2V9IGZyb20gJy4uL2Nlc2l1bS9jZXNpdW0uc2VydmljZSc7XG5pbXBvcnQgKiBhcyBnZW9kZXN5IGZyb20gJ2dlb2Rlc3knO1xuaW1wb3J0IHtoZW1pc3BoZXJlLCBMYXRMb24sIExhdExvbkVsbGlwc29pZGFsLCBVdG19IGZyb20gJ2dlb2Rlc3knO1xuXG5jb25zdCBMYXRMb25WZWN0b3JzID0gZ2VvZGVzeVsnTGF0TG9uVmVjdG9ycyddOyAvLyBkb2VzbnQgZXhpc3RzIG9uIHR5cGluZ3Ncblxud2luZG93WydnZW9kZXN5J10gPSBnZW9kZXN5O1xuXG4vKipcbiAqICBHaXZlbiBkaWZmZXJlbnQgdHlwZXMgb2YgY29vcmRpbmF0ZXMsIHdlIHByb3ZpZGUgeW91IGEgc2VydmljZSBjb252ZXJ0aW5nIHRob3NlIHR5cGVzIHRvIHRoZSBtb3N0IGNvbW1vbiBvdGhlciB0eXBlcy5cbiAqICBXZSBhcmUgdXNpbmcgdGhlIGdlb2Rlc3kgaW1wbGVtZW50YXRpb24gb2YgVVRNIGNvbnZlcnNpb24uIHNlZTogaHR0cHM6Ly9naXRodWIuY29tL2NocmlzdmVuZXNzL2dlb2Rlc3kuXG4gKnpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuICogaW1wb3J0IHsgQ29vcmRpbmF0ZUNvbnZlcnRlciB9IGZyb20gJ2FuZ3VsYXIyLWNlc2l1bSc7XG4gKlxuICogQENvbXBvbmVudCh7XG4gKiBcdFx0c2VsZWN0b3I6J215LWNvbXBvbmVudCcsXG4gKiBcdFx0dGVtcGxhdGU6JzxkaXY+e3tzaG93Q2FydG9ncmFwaGljfX08L2Rpdj4nLFxuICogXHRcdHByb3ZpZGVyczpbQ29vcmRpbmF0ZUNvbnZlcnRlcl1cbiAqIH0pXG4gKiBleHBvcnQgY2xhc3MgTXlDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICogXHRcdHNob3dDYXJ0b2dyYXBoaWM7XG4gKlxuICogXHRcdGNvbnN0cnVjdG9yKHByaXZhdGUgY29vcmRpbmF0ZUNvbnZlcnRlcjpDb29yZGluYXRlQ29udmVydGVyKXtcbiAqIFx0XHR9XG4gKlxuICogXHRcdG5nT25Jbml0KCl7XG4gKiBcdFx0XHR0aGlzLnNob3dDYXJ0b2dyYXBoaWMgPSB0aGlzLmNvb3JkaW5hdGVDb252ZXJ0ZXIuZGVncmVlc1RvQ2FydG9ncmFwaGljKDUsIDUsIDUpO1xuICogIH1cbiAqIH1cbiAqXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBDb29yZGluYXRlQ29udmVydGVyIHtcbiAgY29uc3RydWN0b3IoQE9wdGlvbmFsKCkgcHJpdmF0ZSBjZXNpdW1TZXJ2aWNlPzogQ2VzaXVtU2VydmljZSkge1xuICB9XG5cbiAgc3RhdGljIGNhcnRlc2lhbjNUb0xhdExvbihjYXJ0ZXNpYW4zOiBDYXJ0ZXNpYW4zLCBlbGxpcHNvaWQ/OiBhbnkpOiB7bG9uOiBudW1iZXIsIGxhdDogbnVtYmVyOyBoZWlnaHQ6IG51bWJlcn0ge1xuICAgIGNvbnN0IGNhcnQgPSBDYXJ0b2dyYXBoaWMuZnJvbUNhcnRlc2lhbihjYXJ0ZXNpYW4zLCBlbGxpcHNvaWQpO1xuICAgIHJldHVybiB7XG4gICAgICBsb246IGNNYXRoLnRvRGVncmVlcyhjYXJ0LmxvbmdpdHVkZSksXG4gICAgICBsYXQ6IGNNYXRoLnRvRGVncmVlcyhjYXJ0LmxhdGl0dWRlKSxcbiAgICAgIGhlaWdodDogY2FydC5oZWlnaHRcbiAgICB9O1xuICB9XG5cbiAgc2NyZWVuVG9DYXJ0ZXNpYW4zKHNjcmVlblBvczogeyB4OiBudW1iZXIsIHk6IG51bWJlciB9LCBhZGRNYXBDYW52YXNCb3VuZHNUb1Bvcz86IGJvb2xlYW4pIHtcbiAgICBpZiAoIXRoaXMuY2VzaXVtU2VydmljZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBTkdVTEFSMi1DRVNJVU0gLSBDZXNpdW0gc2VydmljZSBzaG91bGQgYmUgcHJvdmlkZWQgaW4gb3JkZXInICtcbiAgICAgICAgJyB0byBkbyBzY3JlZW4gcG9zaXRpb24gY2FsY3VsYXRpb25zJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHNjcmVlblBvc2l0aW9uID0geyAuLi5zY3JlZW5Qb3MgfTtcbiAgICAgIGlmIChhZGRNYXBDYW52YXNCb3VuZHNUb1Bvcykge1xuICAgICAgICBjb25zdCBtYXBCb3VuZHMgPSB0aGlzLmNlc2l1bVNlcnZpY2UuZ2V0Vmlld2VyKCkuY2FudmFzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBzY3JlZW5Qb3NpdGlvbi54ICs9IG1hcEJvdW5kcy5sZWZ0O1xuICAgICAgICBzY3JlZW5Qb3NpdGlvbi55ICs9IG1hcEJvdW5kcy50b3A7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNhbWVyYSA9IHRoaXMuY2VzaXVtU2VydmljZS5nZXRWaWV3ZXIoKS5jYW1lcmE7XG4gICAgICByZXR1cm4gY2FtZXJhLnBpY2tFbGxpcHNvaWQoc2NyZWVuUG9zaXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIHNjcmVlblRvQ2FydG9ncmFwaGljKHNjcmVlblBvczogeyB4OiBudW1iZXIsIHk6IG51bWJlciB9LCBlbGxpcHNvaWQ/OiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5jYXJ0ZXNpYW4zVG9DYXJ0b2dyYXBoaWModGhpcy5zY3JlZW5Ub0NhcnRlc2lhbjMoc2NyZWVuUG9zKSwgZWxsaXBzb2lkKTtcbiAgfVxuXG4gIGNhcnRlc2lhbjNUb0NhcnRvZ3JhcGhpYyhjYXJ0ZXNpYW46IENhcnRlc2lhbjMsIGVsbGlwc29pZD86IGFueSkge1xuICAgIHJldHVybiBDYXJ0b2dyYXBoaWMuZnJvbUNhcnRlc2lhbihjYXJ0ZXNpYW4sIGVsbGlwc29pZCk7XG4gIH1cblxuICBkZWdyZWVzVG9DYXJ0b2dyYXBoaWMobG9uZ2l0dWRlOiBudW1iZXIsIGxhdGl0dWRlOiBudW1iZXIsIGhlaWdodD86IG51bWJlcikge1xuICAgIHJldHVybiBDYXJ0b2dyYXBoaWMuZnJvbURlZ3JlZXMobG9uZ2l0dWRlLCBsYXRpdHVkZSwgaGVpZ2h0KTtcbiAgfVxuXG4gIHJhZGlhbnNUb0NhcnRvZ3JhcGhpYyhsb25naXR1ZGU6IG51bWJlciwgbGF0aXR1ZGU6IG51bWJlciwgaGVpZ2h0PzogbnVtYmVyKSB7XG4gICAgcmV0dXJuIENhcnRvZ3JhcGhpYy5mcm9tUmFkaWFucyhsb25naXR1ZGUsIGxhdGl0dWRlLCBoZWlnaHQpO1xuICB9XG5cbiAgZGVncmVlc1RvVVRNKGxvbmdpdHVkZTogbnVtYmVyLCBsYXRpdHVkZTogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG5ldyBMYXRMb25FbGxpcHNvaWRhbChsYXRpdHVkZSwgbG9uZ2l0dWRlKS50b1V0bSgpO1xuICB9XG5cbiAgVVRNVG9EZWdyZWVzKHpvbmU6IG51bWJlciwgaGVtaXNwaGVyZVR5cGU6IGhlbWlzcGhlcmUsIGVhc3Rpbmc6IG51bWJlciwgbm9ydGhpbmc6IG51bWJlcikge1xuICAgIHJldHVybiB0aGlzLmdlb2Rlc3lUb0Nlc2l1bU9iamVjdChuZXcgVXRtKHpvbmUsIGhlbWlzcGhlcmVUeXBlLCBlYXN0aW5nLCBub3J0aGluZykudG9MYXRMb25FKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZW9kZXN5VG9DZXNpdW1PYmplY3QoZ2VvZGVzeVJhZGlhbnM6IExhdExvbikge1xuICAgIHJldHVybiB7XG4gICAgICBsb25naXR1ZGU6IGdlb2Rlc3lSYWRpYW5zLmxvbixcbiAgICAgIGxhdGl0dWRlOiBnZW9kZXN5UmFkaWFucy5sYXQsXG4gICAgICBoZWlnaHQ6IGdlb2Rlc3lSYWRpYW5zWydoZWlnaHQnXSA/IGdlb2Rlc3lSYWRpYW5zWydoZWlnaHQnXSA6IDBcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIG1pZGRsZSBwb2ludCBiZXR3ZWVuIHR3byBwb2ludHNcbiAgICogQHBhcmFtIGZpcnN0ICAobGF0aXR1ZGUsbG9uZ2l0dWRlKSBpbiByYWRpYW5zXG4gICAqIEBwYXJhbSBzZWNvbmQgKGxhdGl0dWRlLGxvbmdpdHVkZSkgaW4gcmFkaWFuc1xuICAgKi9cbiAgbWlkUG9pbnRUb0NhcnRlc2lhbjMoZmlyc3Q6IHsgbGF0aXR1ZGU6IG51bWJlciwgbG9uZ2l0dWRlOiBudW1iZXIgfSwgc2Vjb25kOiB7IGxhdGl0dWRlOiBudW1iZXIsIGxvbmdpdHVkZTogbnVtYmVyIH0pIHtcbiAgICBjb25zdCB0b0RlZyA9IChyYWQ6IG51bWJlcikgPT4gY01hdGgudG9EZWdyZWVzKHJhZCk7XG4gICAgY29uc3QgZmlyc3RQb2ludCA9IG5ldyBMYXRMb25WZWN0b3JzKHRvRGVnKGZpcnN0LmxhdGl0dWRlKSwgdG9EZWcoZmlyc3QubG9uZ2l0dWRlKSk7XG4gICAgY29uc3Qgc2Vjb25kUG9pbnQgPSBuZXcgTGF0TG9uVmVjdG9ycyh0b0RlZyhzZWNvbmQubGF0aXR1ZGUpLCB0b0RlZyhzZWNvbmQubG9uZ2l0dWRlKSk7XG4gICAgY29uc3QgbWlkZGxlUG9pbnQ6IGFueSA9IGZpcnN0UG9pbnQubWlkcG9pbnRUbyhzZWNvbmRQb2ludCk7XG5cbiAgICByZXR1cm4gQ2FydGVzaWFuMy5mcm9tRGVncmVlcyhtaWRkbGVQb2ludC5sb24sIG1pZGRsZVBvaW50LmxhdCk7XG4gIH1cblxuICBtaWRkbGVQb2ludEJ5U2NyZWVuKHBvc2l0aW9uMDogQ2FydGVzaWFuMywgcG9zaXRpb24xOiBDYXJ0ZXNpYW4zKTogQ2FydGVzaWFuMyB7XG4gICAgY29uc3Qgc2NlbmUgPSB0aGlzLmNlc2l1bVNlcnZpY2UuZ2V0U2NlbmUoKTtcbiAgICBjb25zdCBzY3JlZW5Qb3NpdGlvbjEgPSBTY2VuZVRyYW5zZm9ybXMud2dzODRUb1dpbmRvd0Nvb3JkaW5hdGVzKHNjZW5lLCBwb3NpdGlvbjApO1xuICAgIGNvbnN0IHNjcmVlblBvc2l0aW9uMiA9IFNjZW5lVHJhbnNmb3Jtcy53Z3M4NFRvV2luZG93Q29vcmRpbmF0ZXMoc2NlbmUsIHBvc2l0aW9uMSk7XG4gICAgY29uc3QgbWlkZGxlU2NyZWVuUG9pbnQgPVxuICAgICAgbmV3IENhcnRlc2lhbjIoKHNjcmVlblBvc2l0aW9uMi54ICsgc2NyZWVuUG9zaXRpb24xLngpIC8gMi4wLCAoc2NyZWVuUG9zaXRpb24yLnkgKyBzY3JlZW5Qb3NpdGlvbjEueSkgLyAyLjApO1xuICAgIHJldHVybiBzY2VuZS5waWNrUG9zaXRpb24obWlkZGxlU2NyZWVuUG9pbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIGluaXRpYWwgYmVhcmluZyBiZXR3ZWVuIHR3byBwb2ludHNcbiAgICpcbiAgICogKiBAcmV0dXJuIGJlYXJpbmcgaW4gZGVncmVlc1xuICAgKiBAcGFyYW0gZmlyc3QgLSB7bGF0aXR1ZGUsbG9uZ2l0dWRlfSBpbiByYWRpYW5zXG4gICAqIEBwYXJhbSBzZWNvbmQgLSB7bGF0aXR1ZGUsbG9uZ2l0dWRlfSBpbiByYWRpYW5zXG4gICAqL1xuICBiZWFyaW5nVG8oZmlyc3Q6IHsgbGF0aXR1ZGU6IG51bWJlciwgbG9uZ2l0dWRlOiBudW1iZXIgfSwgc2Vjb25kOiB7IGxhdGl0dWRlOiBudW1iZXIsIGxvbmdpdHVkZTogbnVtYmVyIH0pIHtcbiAgICBjb25zdCB0b0RlZyA9IChyYWQ6IG51bWJlcikgPT4gY01hdGgudG9EZWdyZWVzKHJhZCk7XG4gICAgY29uc3QgZmlyc3RQb2ludCA9IG5ldyBMYXRMb25WZWN0b3JzKHRvRGVnKGZpcnN0LmxhdGl0dWRlKSwgdG9EZWcoZmlyc3QubG9uZ2l0dWRlKSk7XG4gICAgY29uc3Qgc2Vjb25kUG9pbnQgPSBuZXcgTGF0TG9uVmVjdG9ycyh0b0RlZyhzZWNvbmQubGF0aXR1ZGUpLCB0b0RlZyhzZWNvbmQubG9uZ2l0dWRlKSk7XG4gICAgY29uc3QgYmVhcmluZyA9IGZpcnN0UG9pbnQuYmVhcmluZ1RvKHNlY29uZFBvaW50KTtcblxuICAgIHJldHVybiBiZWFyaW5nO1xuICB9XG5cbiAgLyoqXG4gICAqIGluaXRpYWwgYmVhcmluZyBiZXR3ZWVuIHR3byBwb2ludHNcbiAgICpcbiAgICogQHJldHVybiBiZWFyaW5nIGluIGRlZ3JlZXNcbiAgICovXG4gIGJlYXJpbmdUb0NhcnRlc2lhbihmaXJzdENhcnRlc2lhbjM6IENhcnRlc2lhbjMsIHNlY29uZENhcnRlc2lhbjM6IENhcnRlc2lhbjMpIHtcbiAgICBjb25zdCBmaXJzdENhcnQgPSBDYXJ0b2dyYXBoaWMuZnJvbUNhcnRlc2lhbihmaXJzdENhcnRlc2lhbjMpO1xuICAgIGNvbnN0IHNlY29uZENhcnQgPSBDYXJ0b2dyYXBoaWMuZnJvbUNhcnRlc2lhbihzZWNvbmRDYXJ0ZXNpYW4zKTtcblxuICAgIHJldHVybiB0aGlzLmJlYXJpbmdUbyhmaXJzdENhcnQsIHNlY29uZENhcnQpO1xuICB9XG59XG4iXX0=