UNPKG

sigma

Version:

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

122 lines (121 loc) 4.73 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.edgeLabelsToDisplayFromNodes = exports.LabelGrid = void 0; /** * Class representing a single candidate for the label grid selection. * * It also describes a deterministic way to compare two candidates to assess * which one is better. */ var LabelCandidate = /** @class */ (function () { function LabelCandidate(key, size) { this.key = key; this.size = size; } LabelCandidate.compare = function (first, second) { // First we compare by size if (first.size > second.size) return -1; if (first.size < second.size) return 1; // Then since no two nodes can have the same key, we use it to // deterministically tie-break by key if (first.key > second.key) return 1; // NOTE: this comparator cannot return 0 return -1; }; return LabelCandidate; }()); /** * Class representing a 2D spatial grid divided into constant-size cells. */ var LabelGrid = /** @class */ (function () { function LabelGrid() { this.width = 0; this.height = 0; this.cellSize = 0; this.columns = 0; this.rows = 0; this.cells = {}; } LabelGrid.prototype.resizeAndClear = function (dimensions, cellSize) { this.width = dimensions.width; this.height = dimensions.height; this.cellSize = cellSize; this.columns = Math.ceil(dimensions.width / cellSize); this.rows = Math.ceil(dimensions.height / cellSize); this.cells = {}; }; LabelGrid.prototype.getIndex = function (pos) { var xIndex = Math.floor(pos.x / this.cellSize); var yIndex = Math.floor(pos.y / this.cellSize); return yIndex * this.columns + xIndex; }; LabelGrid.prototype.add = function (key, size, pos) { var candidate = new LabelCandidate(key, size); var index = this.getIndex(pos); var cell = this.cells[index]; if (!cell) { cell = []; this.cells[index] = cell; } cell.push(candidate); }; LabelGrid.prototype.organize = function () { for (var k in this.cells) { var cell = this.cells[k]; cell.sort(LabelCandidate.compare); } }; LabelGrid.prototype.getLabelsToDisplay = function (ratio, density) { // TODO: work on visible nodes to optimize? ^ -> threshold outside so that memoization works? // TODO: adjust threshold lower, but increase cells a bit? // TODO: hunt for geom issue in disguise // TODO: memoize while ratio does not move. method to force recompute var cellArea = this.cellSize * this.cellSize; var scaledCellArea = cellArea / ratio / ratio; var scaledDensity = (scaledCellArea * density) / cellArea; var labelsToDisplayPerCell = Math.ceil(scaledDensity); var labels = []; for (var k in this.cells) { var cell = this.cells[k]; for (var i = 0; i < Math.min(labelsToDisplayPerCell, cell.length); i++) { labels.push(cell[i].key); } } return labels; }; return LabelGrid; }()); exports.LabelGrid = LabelGrid; /** * Label heuristic selecting edge labels to display, based on displayed node * labels * * @param {object} params - Parameters: * @param {Set} displayedNodeLabels - Currently displayed node labels. * @param {Set} highlightedNodes - Highlighted nodes. * @param {Graph} graph - The rendered graph. * @param {string} hoveredNode - Hovered node (optional) * @return {Array} - The selected labels. */ function edgeLabelsToDisplayFromNodes(params) { var graph = params.graph, hoveredNode = params.hoveredNode, highlightedNodes = params.highlightedNodes, displayedNodeLabels = params.displayedNodeLabels; var worthyEdges = []; // TODO: the code below can be optimized using #.forEach and batching the code per adj // We should display an edge's label if: // - Any of its extremities is highlighted or hovered // - Both of its extremities has its label shown graph.forEachEdge(function (edge, _, source, target) { if (source === hoveredNode || target === hoveredNode || highlightedNodes.has(source) || highlightedNodes.has(target) || (displayedNodeLabels.has(source) && displayedNodeLabels.has(target))) { worthyEdges.push(edge); } }); return worthyEdges; } exports.edgeLabelsToDisplayFromNodes = edgeLabelsToDisplayFromNodes;