UNPKG

sigma

Version:

A JavaScript library aimed at visualizing graphs of thousands of nodes and edges.

1,152 lines (1,099 loc) 52.4 kB
'use strict'; var inherits = require('./inherits-04acba6b.cjs.dev.js'); var colors = require('./colors-fe6de9d2.cjs.dev.js'); function _defineProperty(e, r, t) { return (r = inherits._toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = inherits._getPrototypeOf(t));); return t; } function _get() { return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); } function _superPropGet(t, o, e, r) { var p = _get(inherits._getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; } function getAttributeItemsCount(attr) { return attr.normalized ? 1 : attr.size; } function getAttributesItemsCount(attrs) { var res = 0; attrs.forEach(function (attr) { return res += getAttributeItemsCount(attr); }); return res; } function loadShader(type, gl, source) { var glType = type === "VERTEX" ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER; // Creating the shader var shader = gl.createShader(glType); if (shader === null) { throw new Error("loadShader: error while creating the shader"); } // Loading source gl.shaderSource(shader, source); // Compiling the shader gl.compileShader(shader); // Retrieving compilation status var successfullyCompiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); // Throwing if something went awry if (!successfullyCompiled) { var infoLog = gl.getShaderInfoLog(shader); gl.deleteShader(shader); throw new Error("loadShader: error while compiling the shader:\n".concat(infoLog, "\n").concat(source)); } return shader; } function loadVertexShader(gl, source) { return loadShader("VERTEX", gl, source); } function loadFragmentShader(gl, source) { return loadShader("FRAGMENT", gl, source); } /** * Function used to load a program. */ function loadProgram(gl, shaders) { var program = gl.createProgram(); if (program === null) { throw new Error("loadProgram: error while creating the program."); } var i, l; // Attaching the shaders for (i = 0, l = shaders.length; i < l; i++) gl.attachShader(program, shaders[i]); gl.linkProgram(program); // Checking status var successfullyLinked = gl.getProgramParameter(program, gl.LINK_STATUS); if (!successfullyLinked) { gl.deleteProgram(program); throw new Error("loadProgram: error while linking the program."); } return program; } function killProgram(_ref) { var gl = _ref.gl, buffer = _ref.buffer, program = _ref.program, vertexShader = _ref.vertexShader, fragmentShader = _ref.fragmentShader; gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader); gl.deleteProgram(program); gl.deleteBuffer(buffer); } /** * Function use to print a float for inserting in a GLSL program. */ function numberToGLSLFloat(n) { return n % 1 === 0 ? n.toFixed(1) : n.toString(); } var PICKING_PREFIX = "#define PICKING_MODE\n"; var SIZE_FACTOR_PER_ATTRIBUTE_TYPE = _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, WebGL2RenderingContext.BOOL, 1), WebGL2RenderingContext.BYTE, 1), WebGL2RenderingContext.UNSIGNED_BYTE, 1), WebGL2RenderingContext.SHORT, 2), WebGL2RenderingContext.UNSIGNED_SHORT, 2), WebGL2RenderingContext.INT, 4), WebGL2RenderingContext.UNSIGNED_INT, 4), WebGL2RenderingContext.FLOAT, 4); var AbstractProgram = /*#__PURE__*/inherits._createClass(function AbstractProgram(_gl, _pickGl, _renderer) { inherits._classCallCheck(this, AbstractProgram); }); var Program = /*#__PURE__*/function () { function Program(gl, pickingBuffer, renderer) { inherits._classCallCheck(this, Program); // GLenum _defineProperty(this, "array", new Float32Array()); _defineProperty(this, "constantArray", new Float32Array()); _defineProperty(this, "capacity", 0); _defineProperty(this, "verticesCount", 0); // Reading and caching program definition var def = this.getDefinition(); this.VERTICES = def.VERTICES; this.VERTEX_SHADER_SOURCE = def.VERTEX_SHADER_SOURCE; this.FRAGMENT_SHADER_SOURCE = def.FRAGMENT_SHADER_SOURCE; this.UNIFORMS = def.UNIFORMS; this.ATTRIBUTES = def.ATTRIBUTES; this.METHOD = def.METHOD; this.CONSTANT_ATTRIBUTES = "CONSTANT_ATTRIBUTES" in def ? def.CONSTANT_ATTRIBUTES : []; this.CONSTANT_DATA = "CONSTANT_DATA" in def ? def.CONSTANT_DATA : []; this.isInstanced = "CONSTANT_ATTRIBUTES" in def; // Computing stride this.ATTRIBUTES_ITEMS_COUNT = getAttributesItemsCount(this.ATTRIBUTES); this.STRIDE = this.VERTICES * this.ATTRIBUTES_ITEMS_COUNT; // Members this.renderer = renderer; this.normalProgram = this.getProgramInfo("normal", gl, def.VERTEX_SHADER_SOURCE, def.FRAGMENT_SHADER_SOURCE, null); this.pickProgram = pickingBuffer ? this.getProgramInfo("pick", gl, PICKING_PREFIX + def.VERTEX_SHADER_SOURCE, PICKING_PREFIX + def.FRAGMENT_SHADER_SOURCE, pickingBuffer) : null; // For instanced programs: if (this.isInstanced) { var constantAttributesItemsCount = getAttributesItemsCount(this.CONSTANT_ATTRIBUTES); if (this.CONSTANT_DATA.length !== this.VERTICES) throw new Error("Program: error while getting constant data (expected ".concat(this.VERTICES, " items, received ").concat(this.CONSTANT_DATA.length, " instead)")); this.constantArray = new Float32Array(this.CONSTANT_DATA.length * constantAttributesItemsCount); for (var i = 0; i < this.CONSTANT_DATA.length; i++) { var vector = this.CONSTANT_DATA[i]; if (vector.length !== constantAttributesItemsCount) throw new Error("Program: error while getting constant data (one vector has ".concat(vector.length, " items instead of ").concat(constantAttributesItemsCount, ")")); for (var j = 0; j < vector.length; j++) this.constantArray[i * constantAttributesItemsCount + j] = vector[j]; } this.STRIDE = this.ATTRIBUTES_ITEMS_COUNT; } } return inherits._createClass(Program, [{ key: "kill", value: function kill() { killProgram(this.normalProgram); if (this.pickProgram) { killProgram(this.pickProgram); this.pickProgram = null; } } }, { key: "getProgramInfo", value: function getProgramInfo(name, gl, vertexShaderSource, fragmentShaderSource, frameBuffer) { var def = this.getDefinition(); // WebGL buffers var buffer = gl.createBuffer(); if (buffer === null) throw new Error("Program: error while creating the WebGL buffer."); // Shaders and program var vertexShader = loadVertexShader(gl, vertexShaderSource); var fragmentShader = loadFragmentShader(gl, fragmentShaderSource); var program = loadProgram(gl, [vertexShader, fragmentShader]); // Initializing locations var uniformLocations = {}; def.UNIFORMS.forEach(function (uniformName) { var location = gl.getUniformLocation(program, uniformName); if (location) uniformLocations[uniformName] = location; }); var attributeLocations = {}; def.ATTRIBUTES.forEach(function (attr) { attributeLocations[attr.name] = gl.getAttribLocation(program, attr.name); }); // For instanced programs: var constantBuffer; if ("CONSTANT_ATTRIBUTES" in def) { def.CONSTANT_ATTRIBUTES.forEach(function (attr) { attributeLocations[attr.name] = gl.getAttribLocation(program, attr.name); }); constantBuffer = gl.createBuffer(); if (constantBuffer === null) throw new Error("Program: error while creating the WebGL constant buffer."); } return { name: name, program: program, gl: gl, frameBuffer: frameBuffer, buffer: buffer, constantBuffer: constantBuffer || {}, uniformLocations: uniformLocations, attributeLocations: attributeLocations, isPicking: name === "pick", vertexShader: vertexShader, fragmentShader: fragmentShader }; } }, { key: "bindProgram", value: function bindProgram(program) { var _this = this; var offset = 0; var gl = program.gl, buffer = program.buffer; if (!this.isInstanced) { gl.bindBuffer(gl.ARRAY_BUFFER, buffer); offset = 0; this.ATTRIBUTES.forEach(function (attr) { return offset += _this.bindAttribute(attr, program, offset); }); gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW); } else { // Handle constant data (things that remain unchanged for all items): gl.bindBuffer(gl.ARRAY_BUFFER, program.constantBuffer); offset = 0; this.CONSTANT_ATTRIBUTES.forEach(function (attr) { return offset += _this.bindAttribute(attr, program, offset, false); }); gl.bufferData(gl.ARRAY_BUFFER, this.constantArray, gl.STATIC_DRAW); // Handle "instance specific" data (things that vary for each item): gl.bindBuffer(gl.ARRAY_BUFFER, program.buffer); offset = 0; this.ATTRIBUTES.forEach(function (attr) { return offset += _this.bindAttribute(attr, program, offset, true); }); gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW); } gl.bindBuffer(gl.ARRAY_BUFFER, null); } }, { key: "unbindProgram", value: function unbindProgram(program) { var _this2 = this; if (!this.isInstanced) { this.ATTRIBUTES.forEach(function (attr) { return _this2.unbindAttribute(attr, program); }); } else { this.CONSTANT_ATTRIBUTES.forEach(function (attr) { return _this2.unbindAttribute(attr, program, false); }); this.ATTRIBUTES.forEach(function (attr) { return _this2.unbindAttribute(attr, program, true); }); } } }, { key: "bindAttribute", value: function bindAttribute(attr, program, offset, setDivisor) { var sizeFactor = SIZE_FACTOR_PER_ATTRIBUTE_TYPE[attr.type]; if (typeof sizeFactor !== "number") throw new Error("Program.bind: yet unsupported attribute type \"".concat(attr.type, "\"")); var location = program.attributeLocations[attr.name]; var gl = program.gl; if (location !== -1) { gl.enableVertexAttribArray(location); var stride = !this.isInstanced ? this.ATTRIBUTES_ITEMS_COUNT * Float32Array.BYTES_PER_ELEMENT : (setDivisor ? this.ATTRIBUTES_ITEMS_COUNT : getAttributesItemsCount(this.CONSTANT_ATTRIBUTES)) * Float32Array.BYTES_PER_ELEMENT; gl.vertexAttribPointer(location, attr.size, attr.type, attr.normalized || false, stride, offset); if (this.isInstanced && setDivisor) { if (gl instanceof WebGL2RenderingContext) { gl.vertexAttribDivisor(location, 1); } else { var ext = gl.getExtension("ANGLE_instanced_arrays"); if (ext) ext.vertexAttribDivisorANGLE(location, 1); } } } return attr.size * sizeFactor; } }, { key: "unbindAttribute", value: function unbindAttribute(attr, program, unsetDivisor) { var location = program.attributeLocations[attr.name]; var gl = program.gl; if (location !== -1) { gl.disableVertexAttribArray(location); if (this.isInstanced && unsetDivisor) { if (gl instanceof WebGL2RenderingContext) { gl.vertexAttribDivisor(location, 0); } else { var ext = gl.getExtension("ANGLE_instanced_arrays"); if (ext) ext.vertexAttribDivisorANGLE(location, 0); } } } } }, { key: "reallocate", value: function reallocate(capacity) { // If desired capacity has not changed we do nothing // NOTE: it's possible here to implement more subtle reallocation schemes // when the number of rendered items increase or decrease if (capacity === this.capacity) return; this.capacity = capacity; this.verticesCount = this.VERTICES * capacity; this.array = new Float32Array(!this.isInstanced ? this.verticesCount * this.ATTRIBUTES_ITEMS_COUNT : this.capacity * this.ATTRIBUTES_ITEMS_COUNT); } }, { key: "hasNothingToRender", value: function hasNothingToRender() { return this.verticesCount === 0; } }, { key: "renderProgram", value: function renderProgram(params, programInfo) { var gl = programInfo.gl, program = programInfo.program; // With the current fix for #1397, the alpha blending is enabled for the // picking layer: gl.enable(gl.BLEND); // Original code: // if (!isPicking) gl.enable(gl.BLEND); // else gl.disable(gl.BLEND); gl.useProgram(program); this.setUniforms(params, programInfo); this.drawWebGL(this.METHOD, programInfo); } }, { key: "render", value: function render(params) { if (this.hasNothingToRender()) return; if (this.pickProgram) { this.pickProgram.gl.viewport(0, 0, params.width * params.pixelRatio / params.downSizingRatio, params.height * params.pixelRatio / params.downSizingRatio); this.bindProgram(this.pickProgram); this.renderProgram(_objectSpread2(_objectSpread2({}, params), {}, { pixelRatio: params.pixelRatio / params.downSizingRatio }), this.pickProgram); this.unbindProgram(this.pickProgram); } this.normalProgram.gl.viewport(0, 0, params.width * params.pixelRatio, params.height * params.pixelRatio); this.bindProgram(this.normalProgram); this.renderProgram(params, this.normalProgram); this.unbindProgram(this.normalProgram); } }, { key: "drawWebGL", value: function drawWebGL(method, _ref) { var gl = _ref.gl, frameBuffer = _ref.frameBuffer; gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer); if (!this.isInstanced) { gl.drawArrays(method, 0, this.verticesCount); } else { if (gl instanceof WebGL2RenderingContext) { gl.drawArraysInstanced(method, 0, this.VERTICES, this.capacity); } else { var ext = gl.getExtension("ANGLE_instanced_arrays"); if (ext) ext.drawArraysInstancedANGLE(method, 0, this.VERTICES, this.capacity); } } } }]); }(); var AbstractNodeProgram = /*#__PURE__*/function (_AbstractProgram) { function AbstractNodeProgram() { inherits._classCallCheck(this, AbstractNodeProgram); return inherits._callSuper(this, AbstractNodeProgram, arguments); } inherits._inherits(AbstractNodeProgram, _AbstractProgram); return inherits._createClass(AbstractNodeProgram); }(AbstractProgram); var NodeProgram = /*#__PURE__*/function (_ref) { function NodeProgram() { inherits._classCallCheck(this, NodeProgram); return inherits._callSuper(this, NodeProgram, arguments); } inherits._inherits(NodeProgram, _ref); return inherits._createClass(NodeProgram, [{ key: "kill", value: function kill() { _superPropGet(NodeProgram, "kill", this, 3)([]); } }, { key: "process", value: function process(nodeIndex, offset, data) { var i = offset * this.STRIDE; // NOTE: dealing with hidden items automatically if (data.hidden) { for (var l = i + this.STRIDE; i < l; i++) { this.array[i] = 0; } return; } return this.processVisibleItem(colors.indexToColor(nodeIndex), i, data); } }]); }(Program); /** * Helper function combining two or more programs into a single compound one. * Note that this is more a quick & easy way to combine program than a really * performant option. More performant programs can be written entirely. * * @param {array} programClasses - Program classes to combine. * @param {function} drawLabel - An optional node "draw label" function. * @param {function} drawHover - An optional node "draw hover" function. * @return {function} */ function createNodeCompoundProgram(programClasses, drawLabel, drawHover) { return /*#__PURE__*/function () { function NodeCompoundProgram(gl, pickingBuffer, renderer) { inherits._classCallCheck(this, NodeCompoundProgram); _defineProperty(this, "drawLabel", drawLabel); _defineProperty(this, "drawHover", drawHover); this.programs = programClasses.map(function (Program) { return new Program(gl, pickingBuffer, renderer); }); } return inherits._createClass(NodeCompoundProgram, [{ key: "reallocate", value: function reallocate(capacity) { this.programs.forEach(function (program) { return program.reallocate(capacity); }); } }, { key: "process", value: function process(nodeIndex, offset, data) { this.programs.forEach(function (program) { return program.process(nodeIndex, offset, data); }); } }, { key: "render", value: function render(params) { this.programs.forEach(function (program) { return program.render(params); }); } }, { key: "kill", value: function kill() { this.programs.forEach(function (program) { return program.kill(); }); } }]); }(); } var AbstractEdgeProgram = /*#__PURE__*/function (_AbstractProgram) { function AbstractEdgeProgram() { inherits._classCallCheck(this, AbstractEdgeProgram); return inherits._callSuper(this, AbstractEdgeProgram, arguments); } inherits._inherits(AbstractEdgeProgram, _AbstractProgram); return inherits._createClass(AbstractEdgeProgram); }(AbstractProgram); var EdgeProgram = /*#__PURE__*/function (_ref) { function EdgeProgram() { var _this; inherits._classCallCheck(this, EdgeProgram); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = inherits._callSuper(this, EdgeProgram, [].concat(args)); _defineProperty(_this, "drawLabel", undefined); return _this; } inherits._inherits(EdgeProgram, _ref); return inherits._createClass(EdgeProgram, [{ key: "kill", value: function kill() { _superPropGet(EdgeProgram, "kill", this, 3)([]); } }, { key: "process", value: function process(edgeIndex, offset, sourceData, targetData, data) { var i = offset * this.STRIDE; // NOTE: dealing with hidden items automatically if (data.hidden || sourceData.hidden || targetData.hidden) { for (var l = i + this.STRIDE; i < l; i++) { this.array[i] = 0; } return; } return this.processVisibleItem(colors.indexToColor(edgeIndex), i, sourceData, targetData, data); } }]); }(Program); /** * Helper function combining two or more programs into a single compound one. * Note that this is more a quick & easy way to combine program than a really * performant option. More performant programs can be written entirely. * * @param {array} programClasses - Program classes to combine. * @param {function} drawLabel - An optional edge "draw label" function. * @return {function} */ function createEdgeCompoundProgram(programClasses, drawLabel) { return /*#__PURE__*/function () { function EdgeCompoundProgram(gl, pickingBuffer, renderer) { inherits._classCallCheck(this, EdgeCompoundProgram); _defineProperty(this, "drawLabel", drawLabel); this.programs = programClasses.map(function (Program) { return new Program(gl, pickingBuffer, renderer); }); } return inherits._createClass(EdgeCompoundProgram, [{ key: "reallocate", value: function reallocate(capacity) { this.programs.forEach(function (program) { return program.reallocate(capacity); }); } }, { key: "process", value: function process(edgeIndex, offset, sourceData, targetData, data) { this.programs.forEach(function (program) { return program.process(edgeIndex, offset, sourceData, targetData, data); }); } }, { key: "render", value: function render(params) { this.programs.forEach(function (program) { return program.render(params); }); } }, { key: "kill", value: function kill() { this.programs.forEach(function (program) { return program.kill(); }); } }]); }(); } function drawStraightEdgeLabel(context, edgeData, sourceData, targetData, settings) { var size = settings.edgeLabelSize, font = settings.edgeLabelFont, weight = settings.edgeLabelWeight, color = settings.edgeLabelColor.attribute ? edgeData[settings.edgeLabelColor.attribute] || settings.edgeLabelColor.color || "#000" : settings.edgeLabelColor.color; var label = edgeData.label; if (!label) return; context.fillStyle = color; context.font = "".concat(weight, " ").concat(size, "px ").concat(font); // Computing positions without considering nodes sizes: var sSize = sourceData.size; var tSize = targetData.size; var sx = sourceData.x; var sy = sourceData.y; var tx = targetData.x; var ty = targetData.y; var cx = (sx + tx) / 2; var cy = (sy + ty) / 2; var dx = tx - sx; var dy = ty - sy; var d = Math.sqrt(dx * dx + dy * dy); if (d < sSize + tSize) return; // Adding nodes sizes: sx += dx * sSize / d; sy += dy * sSize / d; tx -= dx * tSize / d; ty -= dy * tSize / d; cx = (sx + tx) / 2; cy = (sy + ty) / 2; dx = tx - sx; dy = ty - sy; d = Math.sqrt(dx * dx + dy * dy); // Handling ellipsis var textLength = context.measureText(label).width; if (textLength > d) { var ellipsis = "…"; label = label + ellipsis; textLength = context.measureText(label).width; while (textLength > d && label.length > 1) { label = label.slice(0, -2) + ellipsis; textLength = context.measureText(label).width; } if (label.length < 4) return; } var angle; if (dx > 0) { if (dy > 0) angle = Math.acos(dx / d);else angle = Math.asin(dy / d); } else { if (dy > 0) angle = Math.acos(dx / d) + Math.PI;else angle = Math.asin(dx / d) + Math.PI / 2; } context.save(); context.translate(cx, cy); context.rotate(angle); context.fillText(label, -textLength / 2, edgeData.size / 2 + size); context.restore(); } function drawDiscNodeLabel(context, data, settings) { if (!data.label) return; var size = settings.labelSize, font = settings.labelFont, weight = settings.labelWeight, color = settings.labelColor.attribute ? data[settings.labelColor.attribute] || settings.labelColor.color || "#000" : settings.labelColor.color; context.fillStyle = color; context.font = "".concat(weight, " ").concat(size, "px ").concat(font); context.fillText(data.label, data.x + data.size + 3, data.y + size / 3); } /** * Draw an hovered node. * - if there is no label => display a shadow on the node * - if the label box is bigger than node size => display a label box that contains the node with a shadow * - else node with shadow and the label box */ function drawDiscNodeHover(context, data, settings) { var size = settings.labelSize, font = settings.labelFont, weight = settings.labelWeight; context.font = "".concat(weight, " ").concat(size, "px ").concat(font); // Then we draw the label background context.fillStyle = "#FFF"; context.shadowOffsetX = 0; context.shadowOffsetY = 0; context.shadowBlur = 8; context.shadowColor = "#000"; var PADDING = 2; if (typeof data.label === "string") { var textWidth = context.measureText(data.label).width, boxWidth = Math.round(textWidth + 5), boxHeight = Math.round(size + 2 * PADDING), radius = Math.max(data.size, size / 2) + PADDING; var angleRadian = Math.asin(boxHeight / 2 / radius); var xDeltaCoord = Math.sqrt(Math.abs(Math.pow(radius, 2) - Math.pow(boxHeight / 2, 2))); context.beginPath(); context.moveTo(data.x + xDeltaCoord, data.y + boxHeight / 2); context.lineTo(data.x + radius + boxWidth, data.y + boxHeight / 2); context.lineTo(data.x + radius + boxWidth, data.y - boxHeight / 2); context.lineTo(data.x + xDeltaCoord, data.y - boxHeight / 2); context.arc(data.x, data.y, radius, angleRadian, -angleRadian); context.closePath(); context.fill(); } else { context.beginPath(); context.arc(data.x, data.y, data.size + PADDING, 0, Math.PI * 2); context.closePath(); context.fill(); } context.shadowOffsetX = 0; context.shadowOffsetY = 0; context.shadowBlur = 0; // And finally we draw the label drawDiscNodeLabel(context, data, settings); } // language=GLSL var SHADER_SOURCE$6 = /*glsl*/"\nprecision highp float;\n\nvarying vec4 v_color;\nvarying vec2 v_diffVector;\nvarying float v_radius;\n\nuniform float u_correctionRatio;\n\nconst vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);\n\nvoid main(void) {\n float border = u_correctionRatio * 2.0;\n float dist = length(v_diffVector) - v_radius + border;\n\n // No antialiasing for picking mode:\n #ifdef PICKING_MODE\n if (dist > border)\n gl_FragColor = transparent;\n else\n gl_FragColor = v_color;\n\n #else\n float t = 0.0;\n if (dist > border)\n t = 1.0;\n else if (dist > 0.0)\n t = dist / border;\n\n gl_FragColor = mix(v_color, transparent, t);\n #endif\n}\n"; var FRAGMENT_SHADER_SOURCE$2 = SHADER_SOURCE$6; // language=GLSL var SHADER_SOURCE$5 = /*glsl*/"\nattribute vec4 a_id;\nattribute vec4 a_color;\nattribute vec2 a_position;\nattribute float a_size;\nattribute float a_angle;\n\nuniform mat3 u_matrix;\nuniform float u_sizeRatio;\nuniform float u_correctionRatio;\n\nvarying vec4 v_color;\nvarying vec2 v_diffVector;\nvarying float v_radius;\nvarying float v_border;\n\nconst float bias = 255.0 / 254.0;\n\nvoid main() {\n float size = a_size * u_correctionRatio / u_sizeRatio * 4.0;\n vec2 diffVector = size * vec2(cos(a_angle), sin(a_angle));\n vec2 position = a_position + diffVector;\n gl_Position = vec4(\n (u_matrix * vec3(position, 1)).xy,\n 0,\n 1\n );\n\n v_diffVector = diffVector;\n v_radius = size / 2.0;\n\n #ifdef PICKING_MODE\n // For picking mode, we use the ID as the color:\n v_color = a_id;\n #else\n // For normal mode, we use the color:\n v_color = a_color;\n #endif\n\n v_color.a *= bias;\n}\n"; var VERTEX_SHADER_SOURCE$3 = SHADER_SOURCE$5; var _WebGLRenderingContex$3 = WebGLRenderingContext, UNSIGNED_BYTE$3 = _WebGLRenderingContex$3.UNSIGNED_BYTE, FLOAT$3 = _WebGLRenderingContex$3.FLOAT; var UNIFORMS$3 = ["u_sizeRatio", "u_correctionRatio", "u_matrix"]; var NodeCircleProgram = /*#__PURE__*/function (_NodeProgram) { function NodeCircleProgram() { inherits._classCallCheck(this, NodeCircleProgram); return inherits._callSuper(this, NodeCircleProgram, arguments); } inherits._inherits(NodeCircleProgram, _NodeProgram); return inherits._createClass(NodeCircleProgram, [{ key: "getDefinition", value: function getDefinition() { return { VERTICES: 3, VERTEX_SHADER_SOURCE: VERTEX_SHADER_SOURCE$3, FRAGMENT_SHADER_SOURCE: FRAGMENT_SHADER_SOURCE$2, METHOD: WebGLRenderingContext.TRIANGLES, UNIFORMS: UNIFORMS$3, ATTRIBUTES: [{ name: "a_position", size: 2, type: FLOAT$3 }, { name: "a_size", size: 1, type: FLOAT$3 }, { name: "a_color", size: 4, type: UNSIGNED_BYTE$3, normalized: true }, { name: "a_id", size: 4, type: UNSIGNED_BYTE$3, normalized: true }], CONSTANT_ATTRIBUTES: [{ name: "a_angle", size: 1, type: FLOAT$3 }], CONSTANT_DATA: [[NodeCircleProgram.ANGLE_1], [NodeCircleProgram.ANGLE_2], [NodeCircleProgram.ANGLE_3]] }; } }, { key: "processVisibleItem", value: function processVisibleItem(nodeIndex, startIndex, data) { var array = this.array; var color = colors.floatColor(data.color); array[startIndex++] = data.x; array[startIndex++] = data.y; array[startIndex++] = data.size; array[startIndex++] = color; array[startIndex++] = nodeIndex; } }, { key: "setUniforms", value: function setUniforms(params, _ref) { var gl = _ref.gl, uniformLocations = _ref.uniformLocations; var u_sizeRatio = uniformLocations.u_sizeRatio, u_correctionRatio = uniformLocations.u_correctionRatio, u_matrix = uniformLocations.u_matrix; gl.uniform1f(u_correctionRatio, params.correctionRatio); gl.uniform1f(u_sizeRatio, params.sizeRatio); gl.uniformMatrix3fv(u_matrix, false, params.matrix); } }]); }(NodeProgram); _defineProperty(NodeCircleProgram, "ANGLE_1", 0); _defineProperty(NodeCircleProgram, "ANGLE_2", 2 * Math.PI / 3); _defineProperty(NodeCircleProgram, "ANGLE_3", 4 * Math.PI / 3); // language=GLSL var SHADER_SOURCE$4 = /*glsl*/"\nprecision mediump float;\n\nvarying vec4 v_color;\n\nvoid main(void) {\n gl_FragColor = v_color;\n}\n"; var FRAGMENT_SHADER_SOURCE$1 = SHADER_SOURCE$4; // language=GLSL var SHADER_SOURCE$3 = /*glsl*/"\nattribute vec2 a_position;\nattribute vec2 a_normal;\nattribute float a_radius;\nattribute vec3 a_barycentric;\n\n#ifdef PICKING_MODE\nattribute vec4 a_id;\n#else\nattribute vec4 a_color;\n#endif\n\nuniform mat3 u_matrix;\nuniform float u_sizeRatio;\nuniform float u_correctionRatio;\nuniform float u_minEdgeThickness;\nuniform float u_lengthToThicknessRatio;\nuniform float u_widenessToThicknessRatio;\n\nvarying vec4 v_color;\n\nconst float bias = 255.0 / 254.0;\n\nvoid main() {\n float minThickness = u_minEdgeThickness;\n\n float normalLength = length(a_normal);\n vec2 unitNormal = a_normal / normalLength;\n\n // These first computations are taken from edge.vert.glsl and\n // edge.clamped.vert.glsl. Please read it to get better comments on what's\n // happening:\n float pixelsThickness = max(normalLength / u_sizeRatio, minThickness);\n float webGLThickness = pixelsThickness * u_correctionRatio;\n float webGLNodeRadius = a_radius * 2.0 * u_correctionRatio / u_sizeRatio;\n float webGLArrowHeadLength = webGLThickness * u_lengthToThicknessRatio * 2.0;\n float webGLArrowHeadThickness = webGLThickness * u_widenessToThicknessRatio;\n\n float da = a_barycentric.x;\n float db = a_barycentric.y;\n float dc = a_barycentric.z;\n\n vec2 delta = vec2(\n da * (webGLNodeRadius * unitNormal.y)\n + db * ((webGLNodeRadius + webGLArrowHeadLength) * unitNormal.y + webGLArrowHeadThickness * unitNormal.x)\n + dc * ((webGLNodeRadius + webGLArrowHeadLength) * unitNormal.y - webGLArrowHeadThickness * unitNormal.x),\n\n da * (-webGLNodeRadius * unitNormal.x)\n + db * (-(webGLNodeRadius + webGLArrowHeadLength) * unitNormal.x + webGLArrowHeadThickness * unitNormal.y)\n + dc * (-(webGLNodeRadius + webGLArrowHeadLength) * unitNormal.x - webGLArrowHeadThickness * unitNormal.y)\n );\n\n vec2 position = (u_matrix * vec3(a_position + delta, 1)).xy;\n\n gl_Position = vec4(position, 0, 1);\n\n #ifdef PICKING_MODE\n // For picking mode, we use the ID as the color:\n v_color = a_id;\n #else\n // For normal mode, we use the color:\n v_color = a_color;\n #endif\n\n v_color.a *= bias;\n}\n"; var VERTEX_SHADER_SOURCE$2 = SHADER_SOURCE$3; var _WebGLRenderingContex$2 = WebGLRenderingContext, UNSIGNED_BYTE$2 = _WebGLRenderingContex$2.UNSIGNED_BYTE, FLOAT$2 = _WebGLRenderingContex$2.FLOAT; var UNIFORMS$2 = ["u_matrix", "u_sizeRatio", "u_correctionRatio", "u_minEdgeThickness", "u_lengthToThicknessRatio", "u_widenessToThicknessRatio"]; var DEFAULT_EDGE_ARROW_HEAD_PROGRAM_OPTIONS = { extremity: "target", lengthToThicknessRatio: 2.5, widenessToThicknessRatio: 2 }; function createEdgeArrowHeadProgram(inputOptions) { var options = _objectSpread2(_objectSpread2({}, DEFAULT_EDGE_ARROW_HEAD_PROGRAM_OPTIONS), inputOptions || {}); return /*#__PURE__*/function (_EdgeProgram) { function EdgeArrowHeadProgram() { inherits._classCallCheck(this, EdgeArrowHeadProgram); return inherits._callSuper(this, EdgeArrowHeadProgram, arguments); } inherits._inherits(EdgeArrowHeadProgram, _EdgeProgram); return inherits._createClass(EdgeArrowHeadProgram, [{ key: "getDefinition", value: function getDefinition() { return { VERTICES: 3, VERTEX_SHADER_SOURCE: VERTEX_SHADER_SOURCE$2, FRAGMENT_SHADER_SOURCE: FRAGMENT_SHADER_SOURCE$1, METHOD: WebGLRenderingContext.TRIANGLES, UNIFORMS: UNIFORMS$2, ATTRIBUTES: [{ name: "a_position", size: 2, type: FLOAT$2 }, { name: "a_normal", size: 2, type: FLOAT$2 }, { name: "a_radius", size: 1, type: FLOAT$2 }, { name: "a_color", size: 4, type: UNSIGNED_BYTE$2, normalized: true }, { name: "a_id", size: 4, type: UNSIGNED_BYTE$2, normalized: true }], CONSTANT_ATTRIBUTES: [{ name: "a_barycentric", size: 3, type: FLOAT$2 }], CONSTANT_DATA: [[1, 0, 0], [0, 1, 0], [0, 0, 1]] }; } }, { key: "processVisibleItem", value: function processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) { if (options.extremity === "source") { var _ref = [targetData, sourceData]; sourceData = _ref[0]; targetData = _ref[1]; } var thickness = data.size || 1; var radius = targetData.size || 1; var x1 = sourceData.x; var y1 = sourceData.y; var x2 = targetData.x; var y2 = targetData.y; var color = colors.floatColor(data.color); // Computing normals var dx = x2 - x1; var dy = y2 - y1; var len = dx * dx + dy * dy; var n1 = 0; var n2 = 0; if (len) { len = 1 / Math.sqrt(len); n1 = -dy * len * thickness; n2 = dx * len * thickness; } var array = this.array; array[startIndex++] = x2; array[startIndex++] = y2; array[startIndex++] = -n1; array[startIndex++] = -n2; array[startIndex++] = radius; array[startIndex++] = color; array[startIndex++] = edgeIndex; } }, { key: "setUniforms", value: function setUniforms(params, _ref2) { var gl = _ref2.gl, uniformLocations = _ref2.uniformLocations; var u_matrix = uniformLocations.u_matrix, u_sizeRatio = uniformLocations.u_sizeRatio, u_correctionRatio = uniformLocations.u_correctionRatio, u_minEdgeThickness = uniformLocations.u_minEdgeThickness, u_lengthToThicknessRatio = uniformLocations.u_lengthToThicknessRatio, u_widenessToThicknessRatio = uniformLocations.u_widenessToThicknessRatio; gl.uniformMatrix3fv(u_matrix, false, params.matrix); gl.uniform1f(u_sizeRatio, params.sizeRatio); gl.uniform1f(u_correctionRatio, params.correctionRatio); gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness); gl.uniform1f(u_lengthToThicknessRatio, options.lengthToThicknessRatio); gl.uniform1f(u_widenessToThicknessRatio, options.widenessToThicknessRatio); } }]); }(EdgeProgram); } var EdgeArrowHeadProgram = createEdgeArrowHeadProgram(); var EdgeArrowHeadProgram$1 = EdgeArrowHeadProgram; // language=GLSL var SHADER_SOURCE$2 = /*glsl*/"\nprecision mediump float;\n\nvarying vec4 v_color;\nvarying vec2 v_normal;\nvarying float v_thickness;\nvarying float v_feather;\n\nconst vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);\n\nvoid main(void) {\n // We only handle antialiasing for normal mode:\n #ifdef PICKING_MODE\n gl_FragColor = v_color;\n #else\n float dist = length(v_normal) * v_thickness;\n\n float t = smoothstep(\n v_thickness - v_feather,\n v_thickness,\n dist\n );\n\n gl_FragColor = mix(v_color, transparent, t);\n #endif\n}\n"; var FRAGMENT_SHADER_SOURCE = SHADER_SOURCE$2; // language=GLSL var SHADER_SOURCE$1 = /*glsl*/"\nattribute vec4 a_id;\nattribute vec4 a_color;\nattribute vec2 a_normal;\nattribute float a_normalCoef;\nattribute vec2 a_positionStart;\nattribute vec2 a_positionEnd;\nattribute float a_positionCoef;\nattribute float a_radius;\nattribute float a_radiusCoef;\n\nuniform mat3 u_matrix;\nuniform float u_zoomRatio;\nuniform float u_sizeRatio;\nuniform float u_pixelRatio;\nuniform float u_correctionRatio;\nuniform float u_minEdgeThickness;\nuniform float u_lengthToThicknessRatio;\nuniform float u_feather;\n\nvarying vec4 v_color;\nvarying vec2 v_normal;\nvarying float v_thickness;\nvarying float v_feather;\n\nconst float bias = 255.0 / 254.0;\n\nvoid main() {\n float minThickness = u_minEdgeThickness;\n\n float radius = a_radius * a_radiusCoef;\n vec2 normal = a_normal * a_normalCoef;\n vec2 position = a_positionStart * (1.0 - a_positionCoef) + a_positionEnd * a_positionCoef;\n\n float normalLength = length(normal);\n vec2 unitNormal = normal / normalLength;\n\n // These first computations are taken from edge.vert.glsl. Please read it to\n // get better comments on what's happening:\n float pixelsThickness = max(normalLength, minThickness * u_sizeRatio);\n float webGLThickness = pixelsThickness * u_correctionRatio / u_sizeRatio;\n\n // Here, we move the point to leave space for the arrow head:\n float direction = sign(radius);\n float webGLNodeRadius = direction * radius * 2.0 * u_correctionRatio / u_sizeRatio;\n float webGLArrowHeadLength = webGLThickness * u_lengthToThicknessRatio * 2.0;\n\n vec2 compensationVector = vec2(-direction * unitNormal.y, direction * unitNormal.x) * (webGLNodeRadius + webGLArrowHeadLength);\n\n // Here is the proper position of the vertex\n gl_Position = vec4((u_matrix * vec3(position + unitNormal * webGLThickness + compensationVector, 1)).xy, 0, 1);\n\n v_thickness = webGLThickness / u_zoomRatio;\n\n v_normal = unitNormal;\n\n v_feather = u_feather * u_correctionRatio / u_zoomRatio / u_pixelRatio * 2.0;\n\n #ifdef PICKING_MODE\n // For picking mode, we use the ID as the color:\n v_color = a_id;\n #else\n // For normal mode, we use the color:\n v_color = a_color;\n #endif\n\n v_color.a *= bias;\n}\n"; var VERTEX_SHADER_SOURCE$1 = SHADER_SOURCE$1; var _WebGLRenderingContex$1 = WebGLRenderingContext, UNSIGNED_BYTE$1 = _WebGLRenderingContex$1.UNSIGNED_BYTE, FLOAT$1 = _WebGLRenderingContex$1.FLOAT; var UNIFORMS$1 = ["u_matrix", "u_zoomRatio", "u_sizeRatio", "u_correctionRatio", "u_pixelRatio", "u_feather", "u_minEdgeThickness", "u_lengthToThicknessRatio"]; var DEFAULT_EDGE_CLAMPED_PROGRAM_OPTIONS = { lengthToThicknessRatio: DEFAULT_EDGE_ARROW_HEAD_PROGRAM_OPTIONS.lengthToThicknessRatio }; function createEdgeClampedProgram(inputOptions) { var options = _objectSpread2(_objectSpread2({}, DEFAULT_EDGE_CLAMPED_PROGRAM_OPTIONS), inputOptions || {}); return /*#__PURE__*/function (_EdgeProgram) { function EdgeClampedProgram() { inherits._classCallCheck(this, EdgeClampedProgram); return inherits._callSuper(this, EdgeClampedProgram, arguments); } inherits._inherits(EdgeClampedProgram, _EdgeProgram); return inherits._createClass(EdgeClampedProgram, [{ key: "getDefinition", value: function getDefinition() { return { VERTICES: 6, VERTEX_SHADER_SOURCE: VERTEX_SHADER_SOURCE$1, FRAGMENT_SHADER_SOURCE: FRAGMENT_SHADER_SOURCE, METHOD: WebGLRenderingContext.TRIANGLES, UNIFORMS: UNIFORMS$1, ATTRIBUTES: [{ name: "a_positionStart", size: 2, type: FLOAT$1 }, { name: "a_positionEnd", size: 2, type: FLOAT$1 }, { name: "a_normal", size: 2, type: FLOAT$1 }, { name: "a_color", size: 4, type: UNSIGNED_BYTE$1, normalized: true }, { name: "a_id", size: 4, type: UNSIGNED_BYTE$1, normalized: true }, { name: "a_radius", size: 1, type: FLOAT$1 }], CONSTANT_ATTRIBUTES: [ // If 0, then position will be a_positionStart // If 1, then position will be a_positionEnd { name: "a_positionCoef", size: 1, type: FLOAT$1 }, { name: "a_normalCoef", size: 1, type: FLOAT$1 }, { name: "a_radiusCoef", size: 1, type: FLOAT$1 }], CONSTANT_DATA: [[0, 1, 0], [0, -1, 0], [1, 1, 1], [1, 1, 1], [0, -1, 0], [1, -1, -1]] }; } }, { key: "processVisibleItem", value: function processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) { var thickness = data.size || 1; var x1 = sourceData.x; var y1 = sourceData.y; var x2 = targetData.x; var y2 = targetData.y; var color = colors.floatColor(data.color); // Computing normals var dx = x2 - x1; var dy = y2 - y1; var radius = targetData.size || 1; var len = dx * dx + dy * dy; var n1 = 0; var n2 = 0; if (len) { len = 1 / Math.sqrt(len); n1 = -dy * len * thickness; n2 = dx * len * thickness; } var array = this.array; array[startIndex++] = x1; array[startIndex++] = y1; array[startIndex++] = x2; array[startIndex++] = y2; array[startIndex++] = n1; array[startIndex++] = n2; array[startIndex++] = color; array[startIndex++] = edgeIndex; array[startIndex++] = radius; } }, { key: "setUniforms", value: function setUniforms(params, _ref) { var gl = _ref.gl, uniformLocations = _ref.uniformLocations; var u_matrix = uniformLocations.u_matrix, u_zoomRatio = uniformLocations.u_zoomRatio, u_feather = uniformLocations.u_feather, u_pixelRatio = uniformLocations.u_pixelRatio, u_correctionRatio = uniformLocations.u_correctionRatio, u_sizeRatio = uniformLocations.u_sizeRatio, u_minEdgeThickness = uniformLocations.u_minEdgeThickness, u_lengthToThicknessRatio = uniformLocations.u_lengthToThicknessRatio; gl.uniformMatrix3fv(u_matrix, false, params.matrix); gl.uniform1f(u_zoomRatio, params.zoomRatio); gl.uniform1f(u_sizeRatio, params.sizeRatio); gl.uniform1f(u_correctionRatio, params.correctionRatio); gl.uniform1f(u_pixelRatio, params.pixelRatio); gl.uniform1f(u_feather, params.antiAliasingFeather); gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness); gl.uniform1f(u_lengthToThicknessRatio, options.lengthToThicknessRatio); } }]); }(EdgeProgram); } var EdgeClampedProgram = createEdgeClampedProgram(); var EdgeClampedProgram$1 = EdgeClampedProgram; function createEdgeArrowProgram(inputOptions) { return createEdgeCompoundProgram([createEdgeClampedProgram(inputOptions), createEdgeArrowHeadProgram(inputOptions)]); } var EdgeArrowProgram = createEdgeArrowProgram(); var EdgeArrowProgram$1 = EdgeArrowProgram; // language=GLSL var SHADER_SOURCE = /*glsl*/"\nattribute vec4 a_id;\nattribute vec4 a_color;\nattribute vec2 a_normal;\nattribute float a_normalCoef;\nattribute vec2 a_positionStart;\nattribute vec2 a_positionEnd;\nattribute float a_positionCoef;\n\nuniform mat3 u_matrix;\nuniform float u_sizeRatio;\nuniform float u_zoomRatio;\nuniform float u_pixelRatio;\nuniform float u_correctionRatio;\nuniform float u_minEdgeThickness;\nuniform float u_feather;\n\nvarying vec4 v_color;\nvarying vec2 v_normal;\nvarying float v_thickness;\nvarying float v_feather;\n\nconst float bias = 255.0 / 254.0;\n\nvoid main() {\n float minThickness = u_minEdgeThickness;\n\n vec2 normal = a_normal * a_normalCoef;\n vec2 position = a_positionStart * (1.0 - a_positionCoef) + a_positionEnd * a_positionCoef;\n\n float normalLength = length(normal);\n vec2 unitNormal = normal / normalLength;\n\n // We require edges to be at least \"minThickness\" pixels thick *on screen*\n // (so we need to compensate the size ratio):\n float pixelsThickness = max(normalLength, minThickness * u_sizeRatio);\n\n // Then, we need to retrieve the normalized thickness of the edge in the WebGL\n // referential (in a ([0, 1], [0, 1]) space), using our \"magic\" correction\n // ratio:\n float webGLThickness = pixelsThickness * u_correctionRatio / u_sizeRatio;\n\n // Here is the proper position of the vertex\n gl_Position = vec4((u_matrix * vec3(position + unitNormal * webGLThickness, 1)).xy, 0, 1);\n\n // For the fragment shader though, we need a thickness that takes the \"magic\"\n // correction ratio into account (as in webGLThickness), but so that the\n // antialiasing effect does not depend on the zoom level. So here's yet\n // another thickness version:\n v_thickness = webGLThickness / u_zoomRatio;\n\n v_normal = unitNormal;\n\n v_feather = u_feather * u_correctionRatio / u_zoomRatio / u_pixelRatio * 2.0;\n\n #ifdef PICKING_MODE\n // For picking mode, we use the ID as the color:\n v_color = a_id;\n #else\n // For normal mode, we use the color:\n v_color = a_color;\n #endif\n\n v_color.a *= bias;\n}\n"; var VERTEX_SHADER_SOURCE = SHADER_SOURCE; var _WebGLRenderingContex = WebGLRenderingContext, UNSIGNED_BYTE = _WebGLRenderingContex.UNSIGNED_BYTE, FLOAT = _WebGLRenderingContex.FLOAT; var UNIFORMS = ["u_matrix", "u_zoomRatio", "u_sizeRatio", "u_correctionRatio", "u_pixelRatio", "u_feather", "u_minEdgeThickness"]; var EdgeRectangleProgram = /*#__PURE__*/function (_EdgeProgram) { function EdgeRectangleProgram() { inherits._classCallCheck(this, EdgeRectangleProgram); return inherits._callSuper(this, EdgeRectangleProgram, arguments); } inherits._inherits(EdgeRectangleProgram, _EdgeProgram); return inherits._createClass(EdgeRectangleProgram, [{ key: "getDefinition", value: function getDefinition() { return { VERTICES: 6, VERTEX_SHADER_SOURCE: VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE: FRAGMENT_SHADER_SOURCE, METHOD: WebGLRenderingContext.TRIANGLES, UNIFORMS: UNIFORMS, ATTRIBUTES: [{ name: "a_positionStart", size: 2, type: FLOAT }, { name: "a_positionEnd", size: 2, type: FLOAT }, { name: "a_normal", size: 2, type: FLOAT }, { name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true }, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }], CONSTANT_ATTRIBUTES: [ // If 0, then position will be a_positionStart // If 2, then position will be a_positionEnd { name: "a_positionCoef", size: 1, type: FLOAT }, { name: "a_normalCoef", size: 1, type: FLOAT }], CONSTANT_DATA: [[0, 1], [0, -1], [1, 1], [1, 1], [0, -1], [1, -1]] }; } }, { key: "processVisibleItem", value: function processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) { var thickness = data.size || 1; var x1 = sourceData.x; var y1 = sourceData.y; var x2 = targetData.x; var y2 = targetData.y; var color = colors.floatColor(data.color); // Computing normals var dx = x2 - x1; var dy = y2 - y1; var len = dx * dx + dy * dy; var n1 = 0; var n2 = 0; if (len) { len = 1 / Math.sqrt(len); n1 = -dy * len * thickness; n2 = dx * len * thickness; } var array = this.array; array[startIndex++] = x1; array[startIndex++] = y1; array[startIndex++] = x2; array[startIndex++] = y2; array[startIndex++] = n1; array[startIndex++] = n2; array[startIndex++] = color; array[startIndex++] = edgeIndex; } }, { key: "setUniforms", value: function setUniforms(params, _ref) { var gl = _ref.gl, uniformLocations = _ref.uniformLocations; var u_matrix = unifor