UNPKG

@antv/layout

Version:
282 lines (279 loc) 8.83 kB
import isNil from '../node_modules/@antv/util/esm/lodash/is-nil.js'; class GraphLib { constructor(data, options = {}) { this.edgeIdCounter = new Map(); this.nodeMap = extractNodeData(data.nodes, options.node); this.edgeMap = extractEdgeData(data.edges || [], options.edge, this.getEdgeId.bind(this)); } data() { return { nodes: this.nodeMap, edges: this.edgeMap }; } replace(result) { this.nodeMap = result.nodes; this.edgeMap = result.edges; this.clearCache(); } nodes() { return Array.from(this.nodeMap.values()); } node(id) { return this.nodeMap.get(id); } nodeAt(index) { if (!this.indexNodeCache) { this.buildNodeIndexCache(); } const nodeId = this.indexNodeCache.get(index); return nodeId ? this.nodeMap.get(nodeId) : undefined; } nodeIndexOf(id) { var _a; if (!this.nodeIndexCache) { this.buildNodeIndexCache(); } return (_a = this.nodeIndexCache.get(id)) !== null && _a !== void 0 ? _a : -1; } firstNode() { return this.nodeMap.values().next().value; } forEachNode(callback) { let i = 0; this.nodeMap.forEach((node) => callback(node, i++)); } originalNode(id) { const node = this.nodeMap.get(id); return node === null || node === void 0 ? void 0 : node._original; } nodeCount() { return this.nodeMap.size; } edges() { return Array.from(this.edgeMap.values()); } edge(id) { return this.edgeMap.get(id); } firstEdge() { return this.edgeMap.values().next().value; } forEachEdge(callback) { let i = 0; this.edgeMap.forEach((edge) => callback(edge, i++)); } originalEdge(id) { const edge = this.edgeMap.get(id); return edge === null || edge === void 0 ? void 0 : edge._original; } edgeCount() { return this.edgeMap.size; } getEdgeId(edge) { if (edge.id) return edge.id; const baseId = `${edge.source}-${edge.target}`; const count = this.edgeIdCounter.get(baseId) || 0; const id = count === 0 ? baseId : `${baseId}-${count}`; this.edgeIdCounter.set(baseId, count + 1); return id; } degree(nodeId, direction = 'both') { if (!this.degreeCache) { this.buildDegreeCache(); } const degree = this.degreeCache.get(nodeId); if (!degree) return 0; return degree[direction]; } neighbors(nodeId, direction = 'both') { if (!this.outAdjacencyCache || !this.inAdjacencyCache) { this.buildAdjacencyCache(); } if (direction === 'out') { return Array.from(this.outAdjacencyCache.get(nodeId) || []); } if (direction === 'in') { return Array.from(this.inAdjacencyCache.get(nodeId) || []); } if (this.bothAdjacencyCache) { return Array.from(this.bothAdjacencyCache.get(nodeId) || []); } const inSet = this.inAdjacencyCache.get(nodeId); const outSet = this.outAdjacencyCache.get(nodeId); if (!inSet && !outSet) return []; if (!inSet) return Array.from(outSet); if (!outSet) return Array.from(inSet); const merged = new Set(); inSet.forEach((id) => merged.add(id)); outSet.forEach((id) => merged.add(id)); return Array.from(merged); } successors(nodeId) { return this.neighbors(nodeId, 'out'); } predecessors(nodeId) { return this.neighbors(nodeId, 'in'); } setNodeOrder(nodes) { const next = new Map(); for (const node of nodes) next.set(node.id, node); this.nodeMap = next; this.nodeIndexCache = undefined; this.indexNodeCache = undefined; } clearCache() { this.degreeCache = undefined; this.inAdjacencyCache = undefined; this.outAdjacencyCache = undefined; this.bothAdjacencyCache = undefined; this.nodeIndexCache = undefined; this.indexNodeCache = undefined; } buildDegreeCache() { this.degreeCache = new Map(); for (const edge of this.edges()) { const { source, target } = edge; if (edge.source === edge.target) continue; if (!this.degreeCache.has(source)) { this.degreeCache.set(source, { in: 0, out: 0, both: 0 }); } const sourceDeg = this.degreeCache.get(edge.source); if (sourceDeg) { sourceDeg.out++; sourceDeg.both++; } if (!this.degreeCache.has(target)) { this.degreeCache.set(target, { in: 0, out: 0, both: 0 }); } const targetDeg = this.degreeCache.get(edge.target); if (targetDeg) { targetDeg.in++; targetDeg.both++; } } } buildAdjacencyCache() { this.inAdjacencyCache = new Map(); this.outAdjacencyCache = new Map(); for (const edge of this.edges()) { if (!this.nodeMap.has(edge.source) || !this.nodeMap.has(edge.target)) continue; if (!this.outAdjacencyCache.has(edge.source)) { this.outAdjacencyCache.set(edge.source, new Set()); } this.outAdjacencyCache.get(edge.source).add(edge.target); if (!this.inAdjacencyCache.has(edge.target)) { this.inAdjacencyCache.set(edge.target, new Set()); } this.inAdjacencyCache.get(edge.target).add(edge.source); } } buildNodeIndexCache() { this.nodeIndexCache = new Map(); this.indexNodeCache = new Map(); let index = 0; this.nodeMap.forEach((_node, nodeId) => { this.nodeIndexCache.set(nodeId, index); this.indexNodeCache.set(index, nodeId); index++; }); } destroy() { this.clearCache(); this.nodeMap.clear(); this.edgeMap.clear(); this.edgeIdCounter.clear(); } } const nodeFields = [ 'id', 'x', 'y', 'z', 'vx', 'vy', 'vz', 'fx', 'fy', 'fz', 'parentId', ]; const edgeFields = ['id', 'source', 'target', 'points']; function extractNodeData(nodes, node) { if (!nodes) { throw new Error('Data.nodes is required'); } const result = new Map(); for (const datum of nodes) { const nodeData = { _original: datum }; for (const field of nodeFields) { const value = datum[field]; if (isNil(value)) continue; nodeData[field] = value; } if (node) { const customFields = node(datum); for (const key in customFields) { const value = customFields[key]; if (isNil(value)) continue; nodeData[key] = value; } } if (isNil(nodeData.id)) { throw new Error(`Node is missing id field`); } result.set(nodeData.id, nodeData); } return result; } function extractEdgeData(edges, edge, getEdgeId) { const result = new Map(); for (const datum of edges) { const edgeData = { _original: datum }; for (const field of edgeFields) { const value = datum[field]; if (isNil(value)) continue; edgeData[field] = value; } if (edge) { const customFields = edge(datum); for (const key in customFields) { const value = customFields[key]; if (isNil(value)) continue; edgeData[key] = value; } } if (isNil(edgeData.source) || isNil(edgeData.target)) { throw new Error(`Edge is missing source or target field`); } if (isNil(edgeData.id)) { edgeData.id = getEdgeId === null || getEdgeId === void 0 ? void 0 : getEdgeId(datum); } result.set(edgeData.id, edgeData); } return result; } function initNodePosition(model, width, height, dimensions = 2) { model.forEachNode((node) => { if (isNil(node.x)) { node.x = Math.random() * width; } if (isNil(node.y)) { node.y = Math.random() * height; } if (dimensions === 3 && isNil(node.z)) { node.z = Math.random() * Math.min(width, height); } }); } export { GraphLib, initNodePosition }; //# sourceMappingURL=data.js.map