module import Graph from "graphology" ; import { Dimensions , Coordinates } from "../types" ; /**
 * 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.
 */ class LabelCandidate { key : string ; size : number ; constructor ( key , size ) { this . key = key ; this . size = size ; } static compare ( first , second ) { if ( first . size > second . size ) return - 1 ; if ( first . size < second . size ) return 1 ; if ( first . key > second . key ) return 1 ; return - 1 ; } } /**
 * Class representing a 2D spatial grid divided into constant-size cells.
 */ export class LabelGrid { width = 0 ; height = 0 ; cellSize = 0 ; columns = 0 ; rows = 0 ; cells : Record < number , Array < LabelCandidate > > = { } ; resizeAndClear ( 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 = { } ; } private getIndex ( pos ) { const xIndex = Math . floor ( pos . x / this . cellSize ) ; const yIndex = Math . floor ( pos . y / this . cellSize ) ; return xIndex * this . columns + yIndex ; } add ( key , size , pos ) { const candidate = new LabelCandidate ( key , size ) ; const index = this . getIndex ( pos ) ; let cell = this . cells [ index ] ; if ( ! cell ) { cell = [ ] ; this . cells [ index ] = cell ; } cell . push ( candidate ) ; } organize ( ) { for ( const k in this . cells ) { const cell = this . cells [ k ] ; cell . sort ( LabelCandidate . compare ) ; } } getLabelsToDisplay ( ratio , density ) { const cellArea = this . cellSize * this . cellSize ; const scaledCellArea = cellArea / ratio / ratio ; const scaledDensity = ( scaledCellArea * density ) / cellArea ; const labelsToDisplayPerCell = Math . ceil ( scaledDensity ) ; const labels = [ ] ; for ( const k in this . cells ) { const cell = this . cells [ k ] ; for ( let i = 0 ; i < Math . min ( labelsToDisplayPerCell , cell . length ) ; i ++ ) { labels . push ( cell [ i ] . key ) ; } } return labels ; } } param { object } params param { Set } displayedNodeLabels param { Set } highlightedNodes param { Graph } graph param { string } hoveredNode return { Array } export function edgeLabelsToDisplayFromNodes ( params ) { const { graph , hoveredNode , highlightedNodes , displayedNodeLabels } = params ; const worthyEdges = [ ] ; graph . forEachEdge ( ( 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 ; }