/** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Copyright (C) 2018 Michael Czechowski * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { Injectable } from '@angular/core'; import * as Random from 'd3-random'; export class NlsMathService { /** * Calculate distance between to points with coordinates. * @param {?} a * @param {?} b * @return {?} */ Δ(a, b) { return Math.pow(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2), 0.5); } /** * @param {?} point * @param {?} matrix * @return {?} */ getClosestCenter(point, matrix) { if (this.Δ(point, matrix.start) < this.Δ(point, matrix.end)) { return matrix.start; } else { return matrix.end; } } /** * @param {?} point * @param {?} matrix * @return {?} */ getFarestCenter(point, matrix) { if (this.Δ(point, matrix.start) > this.Δ(point, matrix.end)) { return matrix.start; } else { return matrix.end; } } /** * @param {?} matrix * @param {?} overlap * @return {?} */ randomPoint(matrix, overlap) { /** @type {?} */ const x = { min: matrix.center.x - matrix.width * overlap, max: matrix.center.x + matrix.width * overlap }; /** @type {?} */ const y = { min: matrix.center.y - matrix.height * overlap, max: matrix.center.y + matrix.height * overlap }; return { x: Random.randomUniform(x.min, x.max)(), y: Random.randomUniform(y.min, y.max)() }; } /** * @param {?} width * @param {?} height * @return {?} */ centerOfArea(width, height) { return { x: width * 0.5, y: height * 0.5 }; } /** * @param {?} p1 * @param {?} p2 * @return {?} */ centerOfPoints(p1, p2) { return { x: (p1.x + p2.x) * 0.5, y: (p1.y + p2.y) * 0.5 }; } /** * @param {?} curve * @return {?} */ centerOfCurve(curve) { /** @type {?} */ const genMedian = this.medianPoint(curve); /** @type {?} */ const p1 = genMedian.next().value; /** @type {?} */ const p2 = genMedian.next().value; /** @type {?} */ const radians = this.angleRadians(p1, p2); return Object.assign(this.centerOfPoints(p1, p2), { ascent: radians }); } /** * @param {?} curve * @return {?} */ medianOfCurve(curve) { /** @type {?} */ const genMedian = this.medianPoint(curve); /** @type {?} */ const p1 = genMedian.next().value; /** @type {?} */ const p2 = genMedian.next().value; /** @type {?} */ const p3 = genMedian.next().value; /** @type {?} */ const radians = this.angleRadians(p2, p3); // const radians = Math.round(Math.random() * 10000) / 1000; // @todo if nodes are less than 5 error occures return Object.assign(p1, { ascent: radians }); } /** * @param {?} p1 * @param {?} p2 * @return {?} */ angleRadians(p1, p2) { return Math.atan2(p2.y - p1.y, p2.x - p1.x); } /** * @param {?} p1 * @param {?} p2 * @return {?} */ angleDegree(p1, p2) { return this.angleRadians(p1, p2) * 180 / Math.PI; } /** * @param {?} list * @return {?} */ medianIndex(list) { return Math.floor(list.length * 0.5); } /** * @param {?} points * @return {?} */ *medianPoint(points) { /** @type {?} */ let index; /** @type {?} */ const list = points.slice(); while (list) { index = this.medianIndex(points); yield list[index]; list.splice(index, 1); } } /** * Generator for sine bounce * * @param {?=} amplitude default to 1 indicates the amplitude in positive as well * in negative range * @param {?=} decimals amount of decimal places * @param {?=} start 0 indicates to initiate with positive numbers, 1 indicates to * start with negative numbers first * @return {?} */ *bounce(amplitude = 1, decimals = 1, start = 0) { /** @type {?} */ const power = Math.pow(10, decimals); /** @type {?} */ const step = 2 / (power); /** @type {?} */ let index = 0; while (true) { /** @type {?} */ const radians = Math.PI * step * index + start; yield Math.round((Math.sin(radians) * amplitude) * power) / power; index++; } } /** * @param {?=} startPositive * @return {?} */ *flipSign(startPositive = true) { /** @type {?} */ let sign = startPositive ? 1 : -1; while (true) { yield sign = sign * (-1); } } } NlsMathService.decorators = [ { type: Injectable }, ]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmxzLWd1aWxsb2NoZS8iLCJzb3VyY2VzIjpbIm5scy9zZXJ2aWNlcy9tYXRoLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWdCQSxPQUFPLEVBQVUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRW5ELE9BQU8sS0FBSyxNQUFNLE1BQU0sV0FBVyxDQUFDO0FBTXBDLE1BQU07Ozs7Ozs7SUFPRyxDQUFDLENBQUMsQ0FBUSxFQUFFLENBQVE7UUFDekIsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7Ozs7Ozs7SUFHakUsZ0JBQWdCLENBQUMsS0FBWSxFQUFFLE1BQVc7UUFDL0MsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDNUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7U0FDckI7UUFBQyxJQUFJLENBQUMsQ0FBQztZQUNOLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDO1NBQ25COzs7Ozs7O0lBR0ksZUFBZSxDQUFDLEtBQVksRUFBRSxNQUFXO1FBQzlDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtB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T0FBTyxJQUFJLEVBQUUsQ0FBQzs7WUFDWixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksR0FBRyxLQUFLLEdBQUcsS0FBSyxDQUFDO1lBQy9DLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsU0FBUyxDQUFDLEdBQUcsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDO1lBRWxFLEtBQUssRUFBRSxDQUFDO1NBQ1Q7Ozs7OztLQUdLLFFBQVEsQ0FBQyxnQkFBeUIsSUFBSTs7UUFDNUMsSUFBSSxJQUFJLEdBQUcsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWxDLE9BQU8sSUFBSSxFQUFFLENBQUM7WUFDWixNQUFNLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQzFCOzs7O1lBdElKLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoQykgMjAxOCBNaWNoYWVsIEN6ZWNob3dza2kgPG1haWxAZGFpbHlzaC5pdD5cbiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gKiB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZVxuICogU29mdHdhcmUgRm91bmRhdGlvbjsgdmVyc2lvbiAyLlxuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yXG4gKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3JcbiAqIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoXG4gKiB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgSW5jLiwgNTFcbiAqIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgMDIxMTAtMTMwMSwgVVNBLlxuICovXG5cbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0ICogYXMgU2VsZWN0aW9uIGZyb20gJ2QzLXNlbGVjdGlvbic7XG5pbXBvcnQgKiBhcyBSYW5kb20gZnJvbSAnZDMtcmFuZG9tJztcblxuaW1wb3J0IHsgUG9pbnQgfSBmcm9tICcuLy4uL21vZGVscy9wb2ludC5tb2RlbCc7XG5pbXBvcnQgeyBHcmFwaCB9IGZyb20gJy4vLi4vbW9kZWxzL2dyYXBoLm1vZGVsJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5sc01hdGhTZXJ2aWNlIHtcblxuICAvKipcbiAgICogQ2FsY3VsYXRlIGRpc3RhbmNlIGJldHdlZW4gdG8gcG9pbnRzIHdpdGggY29vcmRpbmF0ZXMuXG4gICAqIEBwYXJhbSBhXG4gICAqIEBwYXJhbSBiXG4gICAqL1xuICBwdWJsaWMgzpQoYTogUG9pbnQsIGI6IFBvaW50KSB7XG4gICAgcmV0dXJuIE1hdGgucG93KE1hdGgucG93KGEueCAtIGIueCwgMikgKyBNYXRoLnBvdyhhLnkgLSBiLnksIDIpLCAwLjUpO1xuICB9XG5cbiAgcHVibGljIGdldENsb3Nlc3RDZW50ZXIocG9pbnQ6IFBvaW50LCBtYXRyaXg6IGFueSkge1xuICAgIGlmICh0aGlzLs6UKHBvaW50LCBtYXRyaXguc3RhcnQpIDwgdGhpcy7OlChwb2ludCwgbWF0cml4LmVuZCkpIHtcbiAgICAgIHJldHVybiBtYXRyaXguc3RhcnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBtYXRyaXguZW5kO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRGYXJlc3RDZW50ZXIocG9pbnQ6IFBvaW50LCBtYXRyaXg6IGFueSkge1xuICAgIGlmICh0aGlzLs6UKHBvaW50LCBtYXRyaXguc3RhcnQpID4gdGhpcy7OlChwb2ludCwgbWF0cml4LmVuZCkpIHtcbiAgICAgIHJldHVybiBtYXRyaXguc3RhcnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBtYXRyaXguZW5kO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyByYW5kb21Qb2ludChtYXRyaXg6IGFueSwgb3ZlcmxhcDogbnVtYmVyKSB7XG4gICAgY29uc3QgeCA9IHtcbiAgICAgIG1pbjogbWF0cml4LmNlbnRlci54IC0gbWF0cml4LndpZHRoICogb3ZlcmxhcCxcbiAgICAgIG1heDogbWF0cml4LmNlbnRlci54ICsgbWF0cml4LndpZHRoICogb3ZlcmxhcFxuICAgIH07XG4gICAgY29uc3QgeSA9IHtcbiAgICAgIG1pbjogbWF0cml4LmNlbnRlci55IC0gbWF0cml4LmhlaWdodCAqIG92ZXJsYXAsXG4gICAgICBtYXg6IG1hdHJpeC5jZW50ZXIueSArIG1hdHJpeC5oZWlnaHQgKiBvdmVybGFwXG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICB4OiBSYW5kb20ucmFuZG9tVW5pZm9ybSh4Lm1pbiwgeC5tYXgpKCksXG4gICAgICB5OiBSYW5kb20ucmFuZG9tVW5pZm9ybSh5Lm1pbiwgeS5tYXgpKClcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGNlbnRlck9mQXJlYSh3aWR0aCwgaGVpZ2h0KTogUG9pbnQge1xuICAgIHJldHVybiB7XG4gICAgICB4OiB3aWR0aCAqIDAuNSxcbiAgICAgIHk6IGhlaWdodCAqIDAuNVxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgY2VudGVyT2ZQb2ludHMocDE6IFBvaW50LCBwMjogUG9pbnQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgeDogKHAxLnggKyBwMi54KSAqIDAuNSxcbiAgICAgIHk6IChwMS55ICsgcDIueSkgKiAwLjVcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGNlbnRlck9mQ3VydmUoY3VydmU6IFBvaW50W10pIHtcbiAgICBjb25zdCBnZW5NZWRpYW4gPSB0aGlzLm1lZGlhblBvaW50KGN1cnZlKTtcbiAgICBjb25zdCBwMSA9IGdlbk1lZGlhbi5uZXh0KCkudmFsdWU7XG4gICAgY29uc3QgcDIgPSBnZW5NZWRpYW4ubmV4dCgpLnZhbHVlO1xuICAgIGNvbnN0IHJhZGlhbnMgPSB0aGlzLmFuZ2xlUmFkaWFucyhwMSwgcDIpO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24odGhpcy5jZW50ZXJPZlBvaW50cyhwMSwgcDIpLCB7IGFzY2VudDogcmFkaWFucyB9KTtcbiAgfVxuXG4gIHB1YmxpYyBtZWRpYW5PZkN1cnZlKGN1cnZlOiBQb2ludFtdKSB7XG4gICAgY29uc3QgZ2VuTWVkaWFuID0gdGhpcy5tZWRpYW5Qb2ludChjdXJ2ZSk7XG4gICAgY29uc3QgcDEgPSBnZW5NZWRpYW4ubmV4dCgpLnZhbHVlO1xuICAgIGNvbnN0IHAyID0gZ2VuTWVkaWFuLm5leHQoKS52YWx1ZTtcbiAgICBjb25zdCBwMyA9IGdlbk1lZGlhbi5uZXh0KCkudmFsdWU7XG4gICAgY29uc3QgcmFkaWFucyA9IHRoaXMuYW5nbGVSYWRpYW5zKHAyLCBwMyk7XG4gICAgLy8gY29uc3QgcmFkaWFucyA9IE1hdGgucm91bmQoTWF0aC5yYW5kb20oKSAqIDEwMDAwKSAvIDEwMDA7XG4gICAgLy8gQHRvZG8gaWYgbm9kZXMgYXJlIGxlc3MgdGhhbiA1IGVycm9yIG9jY3VyZXNcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihwMSwgeyBhc2NlbnQ6IHJhZGlhbnMgfSk7XG4gIH1cblxuICBwdWJsaWMgYW5nbGVSYWRpYW5zKHAxOiBQb2ludCwgcDI6IFBvaW50KSB7XG4gICAgcmV0dXJuIE1hdGguYXRhbjIocDIueSAtIHAxLnksIHAyLnggLSBwMS54KTtcbiAgfVxuXG4gIHB1YmxpYyBhbmdsZURlZ3JlZShwMTogUG9pbnQsIHAyOiBQb2ludCkge1xuICAgIHJldHVybiB0aGlzLmFuZ2xlUmFkaWFucyhwMSwgcDIpICogMTgwIC8gTWF0aC5QSTtcbiAgfVxuXG4gIHB1YmxpYyBtZWRpYW5JbmRleChsaXN0OiBhbnkpOiBudW1iZXIge1xuICAgIHJldHVybiBNYXRoLmZsb29yKGxpc3QubGVuZ3RoICogMC41KTtcbiAgfVxuXG4gIHB1YmxpYyAqbWVkaWFuUG9pbnQocG9pbnRzOiBQb2ludFtdKSB7XG4gICAgbGV0IGluZGV4OiBudW1iZXI7XG4gICAgY29uc3QgbGlzdDogUG9pbnRbXSA9IHBvaW50cy5zbGljZSgpO1xuXG4gICAgd2hpbGUgKGxpc3QpIHtcbiAgICAgIGluZGV4ID0gdGhpcy5tZWRpYW5JbmRleChwb2ludHMpO1xuICAgICAgeWllbGQgbGlzdFtpbmRleF07XG5cbiAgICAgIGxpc3Quc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdG9yIGZvciBzaW5lIGJvdW5jZVxuICAgKlxuICAgKiBAcGFyYW0gc3RhcnQgMCBpbmRpY2F0ZXMgdG8gaW5pdGlhdGUgd2l0aCBwb3NpdGl2ZSBudW1iZXJzLCAxIGluZGljYXRlcyB0b1xuICAgKiBzdGFydCB3aXRoIG5lZ2F0aXZlIG51bWJlcnMgZmlyc3RcbiAgICogQHBhcmFtIGFtcGxpdHVkZSBkZWZhdWx0IHRvIDEgaW5kaWNhdGVzIHRoZSBhbXBsaXR1ZGUgaW4gcG9zaXRpdmUgYXMgd2VsbFxuICAgKiBpbiBuZWdhdGl2ZSByYW5nZVxuICAgKiBAcGFyYW0gZGVjaW1hbHMgYW1vdW50IG9mIGRlY2ltYWwgcGxhY2VzXG4gICAqL1xuXG4gIHB1YmxpYyAqYm91bmNlKFxuICAgIGFtcGxpdHVkZTogbnVtYmVyID0gMSxcbiAgICBkZWNpbWFsczogbnVtYmVyID0gMSxcbiAgICBzdGFydDogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBwb3dlciA9IE1hdGgucG93KDEwLCBkZWNpbWFscyk7XG4gICAgY29uc3Qgc3RlcCA9IDIgLyAocG93ZXIpO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgcmFkaWFucyA9IE1hdGguUEkgKiBzdGVwICogaW5kZXggKyBzdGFydDtcbiAgICAgIHlpZWxkIE1hdGgucm91bmQoKE1hdGguc2luKHJhZGlhbnMpICogYW1wbGl0dWRlKSAqIHBvd2VyKSAvIHBvd2VyO1xuXG4gICAgICBpbmRleCsrO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyAqZmxpcFNpZ24oc3RhcnRQb3NpdGl2ZTogYm9vbGVhbiA9IHRydWUpIHtcbiAgICBsZXQgc2lnbiA9IHN0YXJ0UG9zaXRpdmUgPyAxIDogLTE7XG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgeWllbGQgc2lnbiA9IHNpZ24gKiAoLTEpO1xuICAgIH1cbiAgfVxufVxuIl19