From 602c91d8e70ecab611d20cf1a69431ecf868d832 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <piotr.gawron@uni.lu> Date: Thu, 19 Jul 2018 16:22:31 +0200 Subject: [PATCH] alias surface can show gradient data --- frontend-js/src/main/js/Functions.js | 1278 ++++++++--------- .../src/main/js/map/AbstractCustomMap.js | 2 +- .../src/main/js/map/surface/AliasSurface.js | 74 +- .../test/js/map/surface/AliasSurface-test.js | 12 +- 4 files changed, 702 insertions(+), 664 deletions(-) diff --git a/frontend-js/src/main/js/Functions.js b/frontend-js/src/main/js/Functions.js index 208e0c6aa9..94949629be 100644 --- a/frontend-js/src/main/js/Functions.js +++ b/frontend-js/src/main/js/Functions.js @@ -1,639 +1,639 @@ -"use strict"; - -var Promise = require("bluebird"); -var Point = require('./map/canvas/Point'); - -var logger = require('./logger'); - -var xss = require('xss'); - -function Functions(){ - /** - * In a browser variable we store information about browser user is currently - * using. Right now only IE is supported. - */ - this.browser = { - init: function () { - - this.name = "Unknown"; - this.version = "Unknown"; - - if (typeof navigator !== 'undefined') { - // Get the user agent string - var ua = navigator.userAgent; - this.compatibilityMode = false; - var re; - if (navigator.appName === 'Microsoft Internet Explorer') { - this.name = "IE"; - re = new RegExp("MSIE ([0-9]+[\.0-9]*)"); - if (re.exec(ua) !== undefined && re.exec(ua) !== null) { - this.version = parseFloat(RegExp.$1); - } - if (ua.indexOf("MSIE 7.0") > -1) { - this.compatibilityMode = true; - } - } else if (navigator.appName === 'Netscape') { - this.name = "Other"; - ua = navigator.userAgent; - re = new RegExp("Trident/.*rv[ :]*([0-9]{1,}[\.0-9]{0,})"); - if (re.exec(ua) !== undefined && re.exec(ua) !== null) { - this.version = parseFloat(RegExp.$1); - } - } - } - } - }; - - this.browser.init(); -} - -/** - * Bounds value between opt_min and opt_max (result will be not smaller than - * opt_min and not bigger than opt_max). - */ -Functions.prototype.bound = function (value, minVal, maxVal) { - if (minVal !== null && minVal !== undefined) { - value = Math.max(value, minVal); - } - if (maxVal !== null && maxVal !== undefined) { - value = Math.min(value, maxVal); - } - return value; -}; - -Functions.prototype.degreesToRadians = function (deg) { - return deg * (Math.PI / 180); -}; - -Functions.prototype.radiansToDegrees = function (rad) { - return rad / (Math.PI / 180); -}; - -Functions.prototype.intToColorString = function (value) { - /* jslint bitwise: true */ - var trimmedValue = (value & 0xFFFFFF); - var colorStr = trimmedValue.toString(16); - while (colorStr.length < 6) { - colorStr = "0" + colorStr; - } - return '#' + colorStr; -}; - -/** - * - * @param value - * @returns {number|undefined} - */ -Functions.prototype.getIntOrUndefined = function (value) { - if (this.isInt(value)) { - return value; - } else if (value === undefined || value === null) { - return undefined; - } else { - logger.warn("Invalid argument type: " + value); - return undefined; - } -}; - - -/** - * - * @param {string} color - * @param {number} opacity - * @returns {string} - */ -Functions.prototype.colorToRgbaString = function (color, opacity) { - if (color[0] !== '#' || color.length !== 7) { - throw new Error("Expected color in #RRGGBB format"); - } - var red = parseInt(color.substr(1, 2), 16); - var green = parseInt(color.substr(3, 2), 16); - var blue = parseInt(color.substr(5, 2), 16); - var alpha = opacity !== undefined ? opacity : 1.0; - return "rgba(" + red + "," + green + "," + blue + "," + alpha + ")"; -}; - -/** - * Returns stack trace. - * - * @returns {string} stack trace - */ -Functions.prototype.stackTrace = function () { - var err = new Error(); - return err.stack; -}; - -/** - * Returns the position of the element on html page. - * - * @param element - * element for which we want to get the position (top left corner) - * - * @return {Point} coordinates of the element - * - */ -Functions.prototype.getPosition = function (element) { - var xPosition = 0; - var yPosition = 0; - - while (element) { - xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft); - yPosition += (element.offsetTop - element.scrollTop + element.clientTop); - element = element.offsetParent; - } - return new Point(xPosition, yPosition); -}; - -/** - * Checks if the point given as a first argument belongs to a polygon defined as - * a second parameter. Both: point and polygon should use google.map.point - * class. - * - * @param {Point} point - * point which we want to check - * - * @param {Point[]} polygon - * polygon where we check the point - */ - -Functions.prototype.pointInsidePolygon = function (point, polygon) { - var x = point.x; - var y = point.y; - - var inside = false; - for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { - var xi = polygon[i].x, yi = polygon[i].y; - var xj = polygon[j].x, yj = polygon[j].y; - var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - if (intersect) { - inside = !inside; - } - } - return inside; -}; - -/** - * Returns true if parameter is integer, false otherwise. - * - * @param n - * object to check - */ -Functions.prototype.isInt = function (n) { - return Number(n) === n && n % 1 === 0; -}; - -/** - * Returns true if parameter is a DOM element, false otherwise. - * - * @param o - * object to check - */ -Functions.prototype.isDomElement = function (o) { - if (!o) { - return false; - } - return (typeof HTMLElement === "object" ? o instanceof HTMLElement : // DOM2 - o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string"); -}; - -/** - * - * @param {LayoutAlias|LayoutReaction} elementOverlay - * - * @returns {Promise<string>} - */ - -Functions.prototype.overlayToColor = function (elementOverlay) { - var self = this; - if (elementOverlay === null || elementOverlay === undefined) { - return Promise.reject("elementOverlay cannot be null!"); - } else if (elementOverlay.color !== undefined && elementOverlay.color !== null) { - return Promise.resolve(self.intToColorString(elementOverlay.color.rgb)); - } else { - var ratio = 0; - var promiseColors; - if (elementOverlay.value !== undefined && elementOverlay.value !== null) { - if (elementOverlay.value < 0) { - ratio = -elementOverlay.value; - promiseColors = [ServerConnector.getMinOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; - } else { - ratio = elementOverlay.value; - promiseColors = [ServerConnector.getMaxOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; - } - } else { - ratio = 1; - promiseColors = [ServerConnector.getSimpleOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; - } - - return Promise.all(promiseColors).then(function (colors) { - var maxColor = colors[0]; - var neutralColor = colors[1]; - - ratio = 1 - ratio; - var MAX_RED = 0xFF0000; - var MAX_GREEN = 0x00FF00; - var MAX_BLUE = 0x0000FF; - - var red = maxColor & MAX_RED; - var neutralRed = neutralColor & MAX_RED; - - red = red + (neutralRed - red) * ratio; - red = parseInt(red); - red = red & MAX_RED; - - var green = maxColor & MAX_GREEN; - var neutralGreen = neutralColor & MAX_GREEN; - green = green + (neutralGreen - green) * ratio; - green = parseInt(green); - green = green & MAX_GREEN; - - var blue = maxColor & MAX_BLUE; - var neutralBlue = neutralColor & MAX_BLUE; - blue = blue + (neutralBlue - blue) * ratio; - blue = parseInt(blue); - blue = blue & MAX_BLUE; - - var color = red | green | blue; - return self.intToColorString(color); - }); - } -}; - -Functions.prototype.getElementByName = function (element, name) { - if (element !== undefined) { - if (element.getAttribute("name") === name) { - return element; - } - var children = element.children; - for (var i = 0; i < children.length; i++) { - var child = children[i]; - var res = this.getElementByName(child, name); - if (res !== undefined) { - return res; - } - } - } - return undefined; -}; - - -/** - * - * @param {HTMLElement}element - * @param {string} name class name - * @returns {HTMLElement|undefined} - */ -Functions.prototype.getElementByClassName = function (element, name) { - if (name.indexOf(".") !== 0) { - name = "." + name; - } - return $(name, element)[0]; -}; - -/** - * - * @param {Object} params - * @param {string} params.type type of the {HTMLElement} to be created - * @param {string} [params.inputType] type of the input to be created - * @param {string} [params.className] css class of the element - * @param {string} [params.style] css styling - * @param {string} [params.value] - * @param {string|HTMLElement} [params.content] - * - * @returns {HTMLElement} - */ -Functions.prototype.createElement = function (params) { - var result = document.createElement(params.type); - if (params.id !== null && params.id !== undefined) { - result.id = params.id; - } - if (params.name !== null && params.name !== undefined) { - result.setAttribute("name", params.name); - } - if (params.className !== null && params.className !== undefined) { - result.className = params.className; - } - if (params.inputType !== null && params.inputType !== undefined) { - result.type = params.inputType; - } - if (params.content !== null && params.content !== undefined) { - if (this.isDomElement(params.content)) { - result.appendChild(params.content); - } else if (params.xss !== false) { - var content = xss(params.content); - if (content !== params.content) { - logger.warn("XSS changed content: " + params.content); - } - result.innerHTML = content; - } else { - result.innerHTML = params.content; - } - } - if (params.style !== null && params.style !== undefined) { - result.style.cssText = params.style; - } - if (params.onclick !== null && params.onclick !== undefined) { - result.onclick = params.onclick; - } - if (params.onchange !== null && params.onchange !== undefined) { - result.onchange = params.onchange; - } - if (params.href !== null && params.href !== undefined) { - result.href = params.href; - } - if (params.src !== null && params.src !== undefined) { - result.src = params.src; - } - if (params.value !== null && params.value !== undefined) { - result.value = params.value; - } - if (params.title !== null && params.title !== undefined) { - result.title = params.title; - } - if (params.index !== null && params.index !== undefined) { - result.index = params.index; - } - if (params.data !== null && params.data !== undefined) { - $(result).attr("data", params.data); - } - return result; -}; - -function sqr(x) { - return x * x; -} - -function dist2(v, w) { - return sqr(v.x - w.x) + sqr(v.y - w.y); -} - -function distToSegmentSquared(p, v, w) { - var l2 = dist2(v, w); - - if (l2 === 0) { - return dist2(p, v); - } - - var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; - - if (t < 0) { - return dist2(p, v); - } - if (t > 1) { - return dist2(p, w); - } - - return dist2(p, new Point(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y))); -} - -Functions.prototype.distance = function (p1, el2) { - if (el2 instanceof Point) { - var p2 = el2; - return Math.sqrt((Math.pow(p1.x - p2.x, 2)) + (Math.pow(p1.y - p2.y, 2))); - } else { - return Math.sqrt(distToSegmentSquared(p1, el2.start, el2.end)); - } -}; - -Functions.prototype.removeChildren = function (element) { - while (element.firstChild) { - element.removeChild(element.firstChild); - } -}; - -/** - * - * @returns {Promise} resolved after javascript is loaded - */ -Functions.prototype.loadScript = function (url) { - return new Promise(function (resolve) { - var scriptExists = false; - var scripts = document.getElementsByTagName('script'); - for (var i = scripts.length; i--;) { - if (scripts[i].src === url) - scriptExists = true; - } - if (!scriptExists) { - var head = document.getElementsByTagName('head')[0]; - var script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = url; - script.onload = function () { - resolve(); - }; - head.appendChild(script); - } else { - resolve(); - } - }); -}; - -Functions.prototype.computeMD5 = function (s) { - function L(k, d) { - return (k << d) | (k >>> (32 - d)) - } - - function K(G, k) { - var I, d, F, H, x; - F = (G & 2147483648); - H = (k & 2147483648); - I = (G & 1073741824); - d = (k & 1073741824); - x = (G & 1073741823) + (k & 1073741823); - if (I & d) { - return (x ^ 2147483648 ^ F ^ H) - } - if (I | d) { - if (x & 1073741824) { - return (x ^ 3221225472 ^ F ^ H) - } else { - return (x ^ 1073741824 ^ F ^ H) - } - } else { - return (x ^ F ^ H) - } - } - - function r(d, F, k) { - return (d & F) | ((~d) & k) - } - - function q(d, F, k) { - return (d & k) | (F & (~k)) - } - - function p(d, F, k) { - return (d ^ F ^ k) - } - - function n(d, F, k) { - return (F ^ (d | (~k))) - } - - function u(G, F, aa, Z, k, H, I) { - G = K(G, K(K(r(F, aa, Z), k), I)); - return K(L(G, H), F) - } - - function f(G, F, aa, Z, k, H, I) { - G = K(G, K(K(q(F, aa, Z), k), I)); - return K(L(G, H), F) - } - - function D(G, F, aa, Z, k, H, I) { - G = K(G, K(K(p(F, aa, Z), k), I)); - return K(L(G, H), F) - } - - function t(G, F, aa, Z, k, H, I) { - G = K(G, K(K(n(F, aa, Z), k), I)); - return K(L(G, H), F) - } - - function e(G) { - var Z; - var F = G.length; - var x = F + 8; - var k = (x - (x % 64)) / 64; - var I = (k + 1) * 16; - var aa = Array(I - 1); - var d = 0; - var H = 0; - while (H < F) { - Z = (H - (H % 4)) / 4; - d = (H % 4) * 8; - aa[Z] = (aa[Z] | (G.charCodeAt(H) << d)); - H++ - } - Z = (H - (H % 4)) / 4; - d = (H % 4) * 8; - aa[Z] = aa[Z] | (128 << d); - aa[I - 2] = F << 3; - aa[I - 1] = F >>> 29; - return aa - } - - function B(x) { - var k = "", F = "", G, d; - for (d = 0; d <= 3; d++) { - G = (x >>> (d * 8)) & 255; - F = "0" + G.toString(16); - k = k + F.substr(F.length - 2, 2) - } - return k - } - - function J(k) { - k = k.replace(/rn/g, "n"); - var d = ""; - for (var F = 0; F < k.length; F++) { - var x = k.charCodeAt(F); - if (x < 128) { - d += String.fromCharCode(x) - } else { - if ((x > 127) && (x < 2048)) { - d += String.fromCharCode((x >> 6) | 192); - d += String.fromCharCode((x & 63) | 128) - } else { - d += String.fromCharCode((x >> 12) | 224); - d += String.fromCharCode(((x >> 6) & 63) | 128); - d += String.fromCharCode((x & 63) | 128) - } - } - } - return d - } - - var C = Array(); - var P, h, E, v, g, Y, X, W, V; - var S = 7, Q = 12, N = 17, M = 22; - var A = 5, z = 9, y = 14, w = 20; - var o = 4, m = 11, l = 16, j = 23; - var U = 6, T = 10, R = 15, O = 21; - s = J(s); - C = e(s); - Y = 1732584193; - X = 4023233417; - W = 2562383102; - V = 271733878; - for (P = 0; P < C.length; P += 16) { - h = Y; - E = X; - v = W; - g = V; - Y = u(Y, X, W, V, C[P + 0], S, 3614090360); - V = u(V, Y, X, W, C[P + 1], Q, 3905402710); - W = u(W, V, Y, X, C[P + 2], N, 606105819); - X = u(X, W, V, Y, C[P + 3], M, 3250441966); - Y = u(Y, X, W, V, C[P + 4], S, 4118548399); - V = u(V, Y, X, W, C[P + 5], Q, 1200080426); - W = u(W, V, Y, X, C[P + 6], N, 2821735955); - X = u(X, W, V, Y, C[P + 7], M, 4249261313); - Y = u(Y, X, W, V, C[P + 8], S, 1770035416); - V = u(V, Y, X, W, C[P + 9], Q, 2336552879); - W = u(W, V, Y, X, C[P + 10], N, 4294925233); - X = u(X, W, V, Y, C[P + 11], M, 2304563134); - Y = u(Y, X, W, V, C[P + 12], S, 1804603682); - V = u(V, Y, X, W, C[P + 13], Q, 4254626195); - W = u(W, V, Y, X, C[P + 14], N, 2792965006); - X = u(X, W, V, Y, C[P + 15], M, 1236535329); - Y = f(Y, X, W, V, C[P + 1], A, 4129170786); - V = f(V, Y, X, W, C[P + 6], z, 3225465664); - W = f(W, V, Y, X, C[P + 11], y, 643717713); - X = f(X, W, V, Y, C[P + 0], w, 3921069994); - Y = f(Y, X, W, V, C[P + 5], A, 3593408605); - V = f(V, Y, X, W, C[P + 10], z, 38016083); - W = f(W, V, Y, X, C[P + 15], y, 3634488961); - X = f(X, W, V, Y, C[P + 4], w, 3889429448); - Y = f(Y, X, W, V, C[P + 9], A, 568446438); - V = f(V, Y, X, W, C[P + 14], z, 3275163606); - W = f(W, V, Y, X, C[P + 3], y, 4107603335); - X = f(X, W, V, Y, C[P + 8], w, 1163531501); - Y = f(Y, X, W, V, C[P + 13], A, 2850285829); - V = f(V, Y, X, W, C[P + 2], z, 4243563512); - W = f(W, V, Y, X, C[P + 7], y, 1735328473); - X = f(X, W, V, Y, C[P + 12], w, 2368359562); - Y = D(Y, X, W, V, C[P + 5], o, 4294588738); - V = D(V, Y, X, W, C[P + 8], m, 2272392833); - W = D(W, V, Y, X, C[P + 11], l, 1839030562); - X = D(X, W, V, Y, C[P + 14], j, 4259657740); - Y = D(Y, X, W, V, C[P + 1], o, 2763975236); - V = D(V, Y, X, W, C[P + 4], m, 1272893353); - W = D(W, V, Y, X, C[P + 7], l, 4139469664); - X = D(X, W, V, Y, C[P + 10], j, 3200236656); - Y = D(Y, X, W, V, C[P + 13], o, 681279174); - V = D(V, Y, X, W, C[P + 0], m, 3936430074); - W = D(W, V, Y, X, C[P + 3], l, 3572445317); - X = D(X, W, V, Y, C[P + 6], j, 76029189); - Y = D(Y, X, W, V, C[P + 9], o, 3654602809); - V = D(V, Y, X, W, C[P + 12], m, 3873151461); - W = D(W, V, Y, X, C[P + 15], l, 530742520); - X = D(X, W, V, Y, C[P + 2], j, 3299628645); - Y = t(Y, X, W, V, C[P + 0], U, 4096336452); - V = t(V, Y, X, W, C[P + 7], T, 1126891415); - W = t(W, V, Y, X, C[P + 14], R, 2878612391); - X = t(X, W, V, Y, C[P + 5], O, 4237533241); - Y = t(Y, X, W, V, C[P + 12], U, 1700485571); - V = t(V, Y, X, W, C[P + 3], T, 2399980690); - W = t(W, V, Y, X, C[P + 10], R, 4293915773); - X = t(X, W, V, Y, C[P + 1], O, 2240044497); - Y = t(Y, X, W, V, C[P + 8], U, 1873313359); - V = t(V, Y, X, W, C[P + 15], T, 4264355552); - W = t(W, V, Y, X, C[P + 6], R, 2734768916); - X = t(X, W, V, Y, C[P + 13], O, 1309151649); - Y = t(Y, X, W, V, C[P + 4], U, 4149444226); - V = t(V, Y, X, W, C[P + 11], T, 3174756917); - W = t(W, V, Y, X, C[P + 2], R, 718787259); - X = t(X, W, V, Y, C[P + 9], O, 3951481745); - Y = K(Y, h); - X = K(X, E); - W = K(W, v); - V = K(V, g) - } - var i = B(Y) + B(X) + B(W) + B(V); - return i.toLowerCase() -}; - -var singleton = new Functions(); - -module.exports = singleton; +"use strict"; + +var Promise = require("bluebird"); +var Point = require('./map/canvas/Point'); + +var logger = require('./logger'); + +var xss = require('xss'); + +function Functions() { + /** + * In a browser variable we store information about browser user is currently + * using. Right now only IE is supported. + */ + this.browser = { + init: function () { + + this.name = "Unknown"; + this.version = "Unknown"; + + if (typeof navigator !== 'undefined') { + // Get the user agent string + var ua = navigator.userAgent; + this.compatibilityMode = false; + var re; + if (navigator.appName === 'Microsoft Internet Explorer') { + this.name = "IE"; + re = new RegExp("MSIE ([0-9]+[\.0-9]*)"); + if (re.exec(ua) !== undefined && re.exec(ua) !== null) { + this.version = parseFloat(RegExp.$1); + } + if (ua.indexOf("MSIE 7.0") > -1) { + this.compatibilityMode = true; + } + } else if (navigator.appName === 'Netscape') { + this.name = "Other"; + ua = navigator.userAgent; + re = new RegExp("Trident/.*rv[ :]*([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) !== undefined && re.exec(ua) !== null) { + this.version = parseFloat(RegExp.$1); + } + } + } + } + }; + + this.browser.init(); +} + +/** + * Bounds value between opt_min and opt_max (result will be not smaller than + * opt_min and not bigger than opt_max). + */ +Functions.prototype.bound = function (value, minVal, maxVal) { + if (minVal !== null && minVal !== undefined) { + value = Math.max(value, minVal); + } + if (maxVal !== null && maxVal !== undefined) { + value = Math.min(value, maxVal); + } + return value; +}; + +Functions.prototype.degreesToRadians = function (deg) { + return deg * (Math.PI / 180); +}; + +Functions.prototype.radiansToDegrees = function (rad) { + return rad / (Math.PI / 180); +}; + +Functions.prototype.intToColorString = function (value) { + /* jslint bitwise: true */ + var trimmedValue = (value & 0xFFFFFF); + var colorStr = trimmedValue.toString(16); + while (colorStr.length < 6) { + colorStr = "0" + colorStr; + } + return '#' + colorStr; +}; + +/** + * + * @param value + * @returns {number|undefined} + */ +Functions.prototype.getIntOrUndefined = function (value) { + if (this.isInt(value)) { + return value; + } else if (value === undefined || value === null) { + return undefined; + } else { + logger.warn("Invalid argument type: " + value); + return undefined; + } +}; + + +/** + * + * @param {string} color + * @param {number} opacity + * @returns {string} + */ +Functions.prototype.colorToRgbaString = function (color, opacity) { + if (color[0] !== '#' || color.length !== 7) { + throw new Error("Expected color in #RRGGBB format, but found: " + color); + } + var red = parseInt(color.substr(1, 2), 16); + var green = parseInt(color.substr(3, 2), 16); + var blue = parseInt(color.substr(5, 2), 16); + var alpha = opacity !== undefined ? opacity : 1.0; + return "rgba(" + red + "," + green + "," + blue + "," + alpha + ")"; +}; + +/** + * Returns stack trace. + * + * @returns {string} stack trace + */ +Functions.prototype.stackTrace = function () { + var err = new Error(); + return err.stack; +}; + +/** + * Returns the position of the element on html page. + * + * @param element + * element for which we want to get the position (top left corner) + * + * @return {Point} coordinates of the element + * + */ +Functions.prototype.getPosition = function (element) { + var xPosition = 0; + var yPosition = 0; + + while (element) { + xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft); + yPosition += (element.offsetTop - element.scrollTop + element.clientTop); + element = element.offsetParent; + } + return new Point(xPosition, yPosition); +}; + +/** + * Checks if the point given as a first argument belongs to a polygon defined as + * a second parameter. Both: point and polygon should use google.map.point + * class. + * + * @param {Point} point + * point which we want to check + * + * @param {Point[]} polygon + * polygon where we check the point + */ + +Functions.prototype.pointInsidePolygon = function (point, polygon) { + var x = point.x; + var y = point.y; + + var inside = false; + for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { + var xi = polygon[i].x, yi = polygon[i].y; + var xj = polygon[j].x, yj = polygon[j].y; + var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + if (intersect) { + inside = !inside; + } + } + return inside; +}; + +/** + * Returns true if parameter is integer, false otherwise. + * + * @param n + * object to check + */ +Functions.prototype.isInt = function (n) { + return Number(n) === n && n % 1 === 0; +}; + +/** + * Returns true if parameter is a DOM element, false otherwise. + * + * @param o + * object to check + */ +Functions.prototype.isDomElement = function (o) { + if (!o) { + return false; + } + return (typeof HTMLElement === "object" ? o instanceof HTMLElement : // DOM2 + o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string"); +}; + +/** + * + * @param {LayoutAlias|LayoutReaction} elementOverlay + * + * @returns {Promise<string>} + */ + +Functions.prototype.overlayToColor = function (elementOverlay) { + var self = this; + if (elementOverlay === null || elementOverlay === undefined) { + return Promise.reject("elementOverlay cannot be null!"); + } else if (elementOverlay.color !== undefined && elementOverlay.color !== null) { + return Promise.resolve(self.intToColorString(elementOverlay.color.rgb)); + } else { + var ratio = 0; + var promiseColors; + if (elementOverlay.value !== undefined && elementOverlay.value !== null) { + if (elementOverlay.value < 0) { + ratio = -elementOverlay.value; + promiseColors = [ServerConnector.getMinOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; + } else { + ratio = elementOverlay.value; + promiseColors = [ServerConnector.getMaxOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; + } + } else { + ratio = 1; + promiseColors = [ServerConnector.getSimpleOverlayColorInt(), ServerConnector.getNeutralOverlayColorInt()]; + } + + return Promise.all(promiseColors).then(function (colors) { + var maxColor = colors[0]; + var neutralColor = colors[1]; + + ratio = 1 - ratio; + var MAX_RED = 0xFF0000; + var MAX_GREEN = 0x00FF00; + var MAX_BLUE = 0x0000FF; + + var red = maxColor & MAX_RED; + var neutralRed = neutralColor & MAX_RED; + + red = red + (neutralRed - red) * ratio; + red = parseInt(red); + red = red & MAX_RED; + + var green = maxColor & MAX_GREEN; + var neutralGreen = neutralColor & MAX_GREEN; + green = green + (neutralGreen - green) * ratio; + green = parseInt(green); + green = green & MAX_GREEN; + + var blue = maxColor & MAX_BLUE; + var neutralBlue = neutralColor & MAX_BLUE; + blue = blue + (neutralBlue - blue) * ratio; + blue = parseInt(blue); + blue = blue & MAX_BLUE; + + var color = red | green | blue; + return self.intToColorString(color); + }); + } +}; + +Functions.prototype.getElementByName = function (element, name) { + if (element !== undefined) { + if (element.getAttribute("name") === name) { + return element; + } + var children = element.children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + var res = this.getElementByName(child, name); + if (res !== undefined) { + return res; + } + } + } + return undefined; +}; + + +/** + * + * @param {HTMLElement}element + * @param {string} name class name + * @returns {HTMLElement|undefined} + */ +Functions.prototype.getElementByClassName = function (element, name) { + if (name.indexOf(".") !== 0) { + name = "." + name; + } + return $(name, element)[0]; +}; + +/** + * + * @param {Object} params + * @param {string} params.type type of the {HTMLElement} to be created + * @param {string} [params.inputType] type of the input to be created + * @param {string} [params.className] css class of the element + * @param {string} [params.style] css styling + * @param {string} [params.value] + * @param {string|HTMLElement} [params.content] + * + * @returns {HTMLElement} + */ +Functions.prototype.createElement = function (params) { + var result = document.createElement(params.type); + if (params.id !== null && params.id !== undefined) { + result.id = params.id; + } + if (params.name !== null && params.name !== undefined) { + result.setAttribute("name", params.name); + } + if (params.className !== null && params.className !== undefined) { + result.className = params.className; + } + if (params.inputType !== null && params.inputType !== undefined) { + result.type = params.inputType; + } + if (params.content !== null && params.content !== undefined) { + if (this.isDomElement(params.content)) { + result.appendChild(params.content); + } else if (params.xss !== false) { + var content = xss(params.content); + if (content !== params.content) { + logger.warn("XSS changed content: " + params.content); + } + result.innerHTML = content; + } else { + result.innerHTML = params.content; + } + } + if (params.style !== null && params.style !== undefined) { + result.style.cssText = params.style; + } + if (params.onclick !== null && params.onclick !== undefined) { + result.onclick = params.onclick; + } + if (params.onchange !== null && params.onchange !== undefined) { + result.onchange = params.onchange; + } + if (params.href !== null && params.href !== undefined) { + result.href = params.href; + } + if (params.src !== null && params.src !== undefined) { + result.src = params.src; + } + if (params.value !== null && params.value !== undefined) { + result.value = params.value; + } + if (params.title !== null && params.title !== undefined) { + result.title = params.title; + } + if (params.index !== null && params.index !== undefined) { + result.index = params.index; + } + if (params.data !== null && params.data !== undefined) { + $(result).attr("data", params.data); + } + return result; +}; + +function sqr(x) { + return x * x; +} + +function dist2(v, w) { + return sqr(v.x - w.x) + sqr(v.y - w.y); +} + +function distToSegmentSquared(p, v, w) { + var l2 = dist2(v, w); + + if (l2 === 0) { + return dist2(p, v); + } + + var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; + + if (t < 0) { + return dist2(p, v); + } + if (t > 1) { + return dist2(p, w); + } + + return dist2(p, new Point(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y))); +} + +Functions.prototype.distance = function (p1, el2) { + if (el2 instanceof Point) { + var p2 = el2; + return Math.sqrt((Math.pow(p1.x - p2.x, 2)) + (Math.pow(p1.y - p2.y, 2))); + } else { + return Math.sqrt(distToSegmentSquared(p1, el2.start, el2.end)); + } +}; + +Functions.prototype.removeChildren = function (element) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } +}; + +/** + * + * @returns {Promise} resolved after javascript is loaded + */ +Functions.prototype.loadScript = function (url) { + return new Promise(function (resolve) { + var scriptExists = false; + var scripts = document.getElementsByTagName('script'); + for (var i = scripts.length; i--;) { + if (scripts[i].src === url) + scriptExists = true; + } + if (!scriptExists) { + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = url; + script.onload = function () { + resolve(); + }; + head.appendChild(script); + } else { + resolve(); + } + }); +}; + +Functions.prototype.computeMD5 = function (s) { + function L(k, d) { + return (k << d) | (k >>> (32 - d)) + } + + function K(G, k) { + var I, d, F, H, x; + F = (G & 2147483648); + H = (k & 2147483648); + I = (G & 1073741824); + d = (k & 1073741824); + x = (G & 1073741823) + (k & 1073741823); + if (I & d) { + return (x ^ 2147483648 ^ F ^ H) + } + if (I | d) { + if (x & 1073741824) { + return (x ^ 3221225472 ^ F ^ H) + } else { + return (x ^ 1073741824 ^ F ^ H) + } + } else { + return (x ^ F ^ H) + } + } + + function r(d, F, k) { + return (d & F) | ((~d) & k) + } + + function q(d, F, k) { + return (d & k) | (F & (~k)) + } + + function p(d, F, k) { + return (d ^ F ^ k) + } + + function n(d, F, k) { + return (F ^ (d | (~k))) + } + + function u(G, F, aa, Z, k, H, I) { + G = K(G, K(K(r(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function f(G, F, aa, Z, k, H, I) { + G = K(G, K(K(q(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function D(G, F, aa, Z, k, H, I) { + G = K(G, K(K(p(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function t(G, F, aa, Z, k, H, I) { + G = K(G, K(K(n(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function e(G) { + var Z; + var F = G.length; + var x = F + 8; + var k = (x - (x % 64)) / 64; + var I = (k + 1) * 16; + var aa = Array(I - 1); + var d = 0; + var H = 0; + while (H < F) { + Z = (H - (H % 4)) / 4; + d = (H % 4) * 8; + aa[Z] = (aa[Z] | (G.charCodeAt(H) << d)); + H++ + } + Z = (H - (H % 4)) / 4; + d = (H % 4) * 8; + aa[Z] = aa[Z] | (128 << d); + aa[I - 2] = F << 3; + aa[I - 1] = F >>> 29; + return aa + } + + function B(x) { + var k = "", F = "", G, d; + for (d = 0; d <= 3; d++) { + G = (x >>> (d * 8)) & 255; + F = "0" + G.toString(16); + k = k + F.substr(F.length - 2, 2) + } + return k + } + + function J(k) { + k = k.replace(/rn/g, "n"); + var d = ""; + for (var F = 0; F < k.length; F++) { + var x = k.charCodeAt(F); + if (x < 128) { + d += String.fromCharCode(x) + } else { + if ((x > 127) && (x < 2048)) { + d += String.fromCharCode((x >> 6) | 192); + d += String.fromCharCode((x & 63) | 128) + } else { + d += String.fromCharCode((x >> 12) | 224); + d += String.fromCharCode(((x >> 6) & 63) | 128); + d += String.fromCharCode((x & 63) | 128) + } + } + } + return d + } + + var C = Array(); + var P, h, E, v, g, Y, X, W, V; + var S = 7, Q = 12, N = 17, M = 22; + var A = 5, z = 9, y = 14, w = 20; + var o = 4, m = 11, l = 16, j = 23; + var U = 6, T = 10, R = 15, O = 21; + s = J(s); + C = e(s); + Y = 1732584193; + X = 4023233417; + W = 2562383102; + V = 271733878; + for (P = 0; P < C.length; P += 16) { + h = Y; + E = X; + v = W; + g = V; + Y = u(Y, X, W, V, C[P + 0], S, 3614090360); + V = u(V, Y, X, W, C[P + 1], Q, 3905402710); + W = u(W, V, Y, X, C[P + 2], N, 606105819); + X = u(X, W, V, Y, C[P + 3], M, 3250441966); + Y = u(Y, X, W, V, C[P + 4], S, 4118548399); + V = u(V, Y, X, W, C[P + 5], Q, 1200080426); + W = u(W, V, Y, X, C[P + 6], N, 2821735955); + X = u(X, W, V, Y, C[P + 7], M, 4249261313); + Y = u(Y, X, W, V, C[P + 8], S, 1770035416); + V = u(V, Y, X, W, C[P + 9], Q, 2336552879); + W = u(W, V, Y, X, C[P + 10], N, 4294925233); + X = u(X, W, V, Y, C[P + 11], M, 2304563134); + Y = u(Y, X, W, V, C[P + 12], S, 1804603682); + V = u(V, Y, X, W, C[P + 13], Q, 4254626195); + W = u(W, V, Y, X, C[P + 14], N, 2792965006); + X = u(X, W, V, Y, C[P + 15], M, 1236535329); + Y = f(Y, X, W, V, C[P + 1], A, 4129170786); + V = f(V, Y, X, W, C[P + 6], z, 3225465664); + W = f(W, V, Y, X, C[P + 11], y, 643717713); + X = f(X, W, V, Y, C[P + 0], w, 3921069994); + Y = f(Y, X, W, V, C[P + 5], A, 3593408605); + V = f(V, Y, X, W, C[P + 10], z, 38016083); + W = f(W, V, Y, X, C[P + 15], y, 3634488961); + X = f(X, W, V, Y, C[P + 4], w, 3889429448); + Y = f(Y, X, W, V, C[P + 9], A, 568446438); + V = f(V, Y, X, W, C[P + 14], z, 3275163606); + W = f(W, V, Y, X, C[P + 3], y, 4107603335); + X = f(X, W, V, Y, C[P + 8], w, 1163531501); + Y = f(Y, X, W, V, C[P + 13], A, 2850285829); + V = f(V, Y, X, W, C[P + 2], z, 4243563512); + W = f(W, V, Y, X, C[P + 7], y, 1735328473); + X = f(X, W, V, Y, C[P + 12], w, 2368359562); + Y = D(Y, X, W, V, C[P + 5], o, 4294588738); + V = D(V, Y, X, W, C[P + 8], m, 2272392833); + W = D(W, V, Y, X, C[P + 11], l, 1839030562); + X = D(X, W, V, Y, C[P + 14], j, 4259657740); + Y = D(Y, X, W, V, C[P + 1], o, 2763975236); + V = D(V, Y, X, W, C[P + 4], m, 1272893353); + W = D(W, V, Y, X, C[P + 7], l, 4139469664); + X = D(X, W, V, Y, C[P + 10], j, 3200236656); + Y = D(Y, X, W, V, C[P + 13], o, 681279174); + V = D(V, Y, X, W, C[P + 0], m, 3936430074); + W = D(W, V, Y, X, C[P + 3], l, 3572445317); + X = D(X, W, V, Y, C[P + 6], j, 76029189); + Y = D(Y, X, W, V, C[P + 9], o, 3654602809); + V = D(V, Y, X, W, C[P + 12], m, 3873151461); + W = D(W, V, Y, X, C[P + 15], l, 530742520); + X = D(X, W, V, Y, C[P + 2], j, 3299628645); + Y = t(Y, X, W, V, C[P + 0], U, 4096336452); + V = t(V, Y, X, W, C[P + 7], T, 1126891415); + W = t(W, V, Y, X, C[P + 14], R, 2878612391); + X = t(X, W, V, Y, C[P + 5], O, 4237533241); + Y = t(Y, X, W, V, C[P + 12], U, 1700485571); + V = t(V, Y, X, W, C[P + 3], T, 2399980690); + W = t(W, V, Y, X, C[P + 10], R, 4293915773); + X = t(X, W, V, Y, C[P + 1], O, 2240044497); + Y = t(Y, X, W, V, C[P + 8], U, 1873313359); + V = t(V, Y, X, W, C[P + 15], T, 4264355552); + W = t(W, V, Y, X, C[P + 6], R, 2734768916); + X = t(X, W, V, Y, C[P + 13], O, 1309151649); + Y = t(Y, X, W, V, C[P + 4], U, 4149444226); + V = t(V, Y, X, W, C[P + 11], T, 3174756917); + W = t(W, V, Y, X, C[P + 2], R, 718787259); + X = t(X, W, V, Y, C[P + 9], O, 3951481745); + Y = K(Y, h); + X = K(X, E); + W = K(W, v); + V = K(V, g) + } + var i = B(Y) + B(X) + B(W) + B(V); + return i.toLowerCase() +}; + +var singleton = new Functions(); + +module.exports = singleton; diff --git a/frontend-js/src/main/js/map/AbstractCustomMap.js b/frontend-js/src/main/js/map/AbstractCustomMap.js index 24eb8493f1..497adbcc7a 100644 --- a/frontend-js/src/main/js/map/AbstractCustomMap.js +++ b/frontend-js/src/main/js/map/AbstractCustomMap.js @@ -420,7 +420,7 @@ AbstractCustomMap.prototype._showDataOverlayAliases = function (overlay, startX, return Promise.each(overlayAliasesOnMap, function (overlayAlias) { return self.getModel().getAliasById(overlayAlias.getId()).then(function (aliasData) { var surface = new AliasSurface({ - overlayAlias: overlayAlias, + overlayData: [overlayAlias], alias: aliasData, map: self, startX: startX, diff --git a/frontend-js/src/main/js/map/surface/AliasSurface.js b/frontend-js/src/main/js/map/surface/AliasSurface.js index 40132afbd9..39e54e9681 100644 --- a/frontend-js/src/main/js/map/surface/AliasSurface.js +++ b/frontend-js/src/main/js/map/surface/AliasSurface.js @@ -16,7 +16,7 @@ var Point = require('../canvas/Point'); * Class representing overlay of the alias on the map relevant for a specific * layout. * - * @param {LayoutAlias} [params.overlayAlias] - {@link LayoutAlias} for which overlay is created + * @param {LayoutAlias[]} [params.overlayData] - {@link LayoutAlias} for which overlay is created * @param {number} [params.startX] - this is the ratio on OX axis that should be use as a * starting point of the overlay. For instance when there are three * overlays to visualize then @@ -38,8 +38,11 @@ var Point = require('../canvas/Point'); function AliasSurface(params) { // call super constructor AbstractSurfaceElement.call(this, params); + if (params.overlayAlias !== undefined) { + throw new Error(); + } - this.setOverlayData(params.overlayAlias); + this.setOverlayData(params.overlayData); this.setStartX(params.startX); this.setEndX(params.endX); @@ -175,13 +178,43 @@ AliasSurface.prototype.setBoundsForAlias = function (startX, endX) { this.getMapCanvasObjects()[0].setBounds(bounds); }; +AliasSurface.prototype._computeColors = function () { + var self = this; + var overlayData = self.getOverlayData(); + if (overlayData === undefined || overlayData.length === 0) { + return self.getColor(); + } else { + var promises = []; + for (var i = 0; i < overlayData.length; i++) { + promises.push(functions.overlayToColor(overlayData[i])); + } + return Promise.all(promises).then(function (colors) { + var countByColor = [], color; + for (var i = 0; i < colors.length; i++) { + color = colors[i]; + if (countByColor[color] !== undefined) { + countByColor[color]++; + } else { + countByColor[color] = 1; + } + } + var result = []; + for (color in countByColor) { + if (countByColor.hasOwnProperty(color)) { + result.push({color: color, amount: countByColor[color]}); + } + } + return result; + }); + } + +}; /** * * @returns {PromiseLike<any>} */ AliasSurface.prototype.init = function () { var self = this; - var overlayData = self.getOverlayData(); var alias = self.getBioEntity(); var map = self.getCustomMap(); var startX = self.getStartX(); @@ -197,26 +230,33 @@ AliasSurface.prototype.init = function () { if (fillOpacity === undefined) { fillOpacity = result; } - if (overlayData !== undefined) { - return functions.overlayToColor(overlayData); + return self._computeColors(); + }).then(function (color) { + if (typeof color === 'string' || color instanceof String) { + self.addMapCanvasObject(map.getMapCanvas().createRectangle({ + fillOpacity: fillOpacity, + strokeColor: self.getStrokeColor(), + strokeOpacity: self.getStrokeOpacity(), + strokeWeight: self.getStrokeWeight(), + fillColor: color, + bounds: bounds + })); } else { - return self.getColor(); + self.addMapCanvasObject(map.getMapCanvas().createRectangle({ + fillOpacity: fillOpacity, + strokeColor: self.getStrokeColor(), + strokeOpacity: self.getStrokeOpacity(), + strokeWeight: self.getStrokeWeight(), + fillGradient: color, + bounds: bounds + })); } - }).then(function (color) { - self.addMapCanvasObject(map.getMapCanvas().createRectangle({ - fillOpacity: fillOpacity, - strokeColor: self.getStrokeColor(), - strokeOpacity: self.getStrokeOpacity(), - strokeWeight: self.getStrokeWeight(), - fillColor: color, - bounds: bounds - })); }); }; /** * - * @returns {LayoutAlias} + * @returns {LayoutAlias[]} */ AliasSurface.prototype.getOverlayData = function () { return this._overlayData; @@ -224,7 +264,7 @@ AliasSurface.prototype.getOverlayData = function () { /** * - * @param {LayoutAlias} overlayData + * @param {LayoutAlias[]} overlayData */ AliasSurface.prototype.setOverlayData = function (overlayData) { this._overlayData = overlayData; diff --git a/frontend-js/src/test/js/map/surface/AliasSurface-test.js b/frontend-js/src/test/js/map/surface/AliasSurface-test.js index 089c15f0cd..4c98a6eb0d 100644 --- a/frontend-js/src/test/js/map/surface/AliasSurface-test.js +++ b/frontend-js/src/test/js/map/surface/AliasSurface-test.js @@ -13,10 +13,9 @@ describe('AliasSurface', function () { it("default", function () { var map = helper.createCustomMap(); var alias = helper.createAlias(map); - var layoutAlias = helper.createLayoutAlias(alias); var result = new AliasSurface({ - overlayAlias: layoutAlias, + overlayData: [helper.createLayoutAlias(alias)], alias: alias, map: map, startX: 1, @@ -30,10 +29,9 @@ describe('AliasSurface', function () { it("no bounds", function () { var map = helper.createCustomMap(); var alias = helper.createAlias(map); - var layoutAlias = helper.createLayoutAlias(alias); var result = new AliasSurface({ - overlayAlias: layoutAlias, + overlayData: [helper.createLayoutAlias(alias)], alias: alias, map: map }); @@ -55,7 +53,7 @@ describe('AliasSurface', function () { alias = result; surface = new AliasSurface({ alias: result, - overlayAlias: helper.createLayoutAlias(result), + overlayData: [helper.createLayoutAlias(alias)], map: map }); return surface.init(); @@ -72,7 +70,7 @@ describe('AliasSurface', function () { var map = helper.createCustomMap(); var alias = helper.createAlias(map); var surface = new AliasSurface({ - overlayAlias: helper.createLayoutAlias(alias), + overlayData: [helper.createLayoutAlias(alias)], alias: alias, map: map, startX: 1, @@ -98,7 +96,7 @@ describe('AliasSurface', function () { alias = result; surface = new AliasSurface({ alias: result, - overlayAlias: helper.createLayoutAlias(result), + overlayData: [helper.createLayoutAlias(result)], map: map, onClick: function () { clicked = true; -- GitLab