Import Solver + neighbors via sparql query
This commit is contained in:
@@ -80,9 +80,11 @@ export class Renderer {
|
||||
// Data
|
||||
private leaves: Leaf[] = [];
|
||||
private sorted: Float32Array = new Float32Array(0);
|
||||
// order[sortedIdx] = originalIdx (original ordering matches input arrays)
|
||||
private sortedToOriginal: Uint32Array = new Uint32Array(0);
|
||||
private vertexIdToSortedIndex: Map<number, number> = new Map();
|
||||
private nodeCount = 0;
|
||||
private edgeCount = 0;
|
||||
private neighborMap: Map<number, number[]> = new Map();
|
||||
private leafEdgeStarts: Uint32Array = new Uint32Array(0);
|
||||
private leafEdgeCounts: Uint32Array = new Uint32Array(0);
|
||||
private maxPtSize = 256;
|
||||
@@ -202,6 +204,7 @@ export class Renderer {
|
||||
const { sorted, leaves, order } = buildSpatialIndex(xs, ys);
|
||||
this.leaves = leaves;
|
||||
this.sorted = sorted;
|
||||
this.sortedToOriginal = order;
|
||||
|
||||
// Pre-allocate arrays for render loop (zero-allocation rendering)
|
||||
this.visibleLeafIndices = new Uint32Array(leaves.length);
|
||||
@@ -226,6 +229,13 @@ export class Renderer {
|
||||
originalToSorted[order[i]] = i;
|
||||
}
|
||||
|
||||
// Build vertex ID → sorted index mapping (used by backend-driven neighbor highlighting)
|
||||
const vertexIdToSortedIndex = new Map<number, number>();
|
||||
for (let i = 0; i < count; i++) {
|
||||
vertexIdToSortedIndex.set(vertexIds[i], originalToSorted[i]);
|
||||
}
|
||||
this.vertexIdToSortedIndex = vertexIdToSortedIndex;
|
||||
|
||||
// Remap edges from vertex IDs to sorted indices
|
||||
const lineIndices = new Uint32Array(edgeCount * 2);
|
||||
let validEdges = 0;
|
||||
@@ -241,18 +251,6 @@ export class Renderer {
|
||||
}
|
||||
this.edgeCount = validEdges;
|
||||
|
||||
// Build per-node neighbor list from edges for selection queries
|
||||
const neighborMap = new Map<number, number[]>();
|
||||
for (let i = 0; i < validEdges; i++) {
|
||||
const src = lineIndices[i * 2];
|
||||
const dst = lineIndices[i * 2 + 1];
|
||||
if (!neighborMap.has(src)) neighborMap.set(src, []);
|
||||
neighborMap.get(src)!.push(dst);
|
||||
if (!neighborMap.has(dst)) neighborMap.set(dst, []);
|
||||
neighborMap.get(dst)!.push(src);
|
||||
}
|
||||
this.neighborMap = neighborMap;
|
||||
|
||||
// Build per-leaf edge index for efficient visible-only edge drawing
|
||||
// Find which leaf each sorted index belongs to
|
||||
const nodeToLeaf = new Uint32Array(count);
|
||||
@@ -331,6 +329,28 @@ export class Renderer {
|
||||
return this.nodeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a sorted buffer index (what findNodeIndexAt returns) back to the original
|
||||
* index in the input arrays used to initialize the renderer.
|
||||
*/
|
||||
sortedIndexToOriginalIndex(sortedIndex: number): number | null {
|
||||
if (
|
||||
sortedIndex < 0 ||
|
||||
sortedIndex >= this.sortedToOriginal.length
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return this.sortedToOriginal[sortedIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a backend node ID (node.id from /api/graph) to a sorted index used by the renderer.
|
||||
*/
|
||||
vertexIdToSortedIndexOrNull(vertexId: number): number | null {
|
||||
const idx = this.vertexIdToSortedIndex.get(vertexId);
|
||||
return typeof idx === "number" ? idx : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert screen coordinates (CSS pixels) to world coordinates.
|
||||
*/
|
||||
@@ -412,10 +432,10 @@ export class Renderer {
|
||||
|
||||
/**
|
||||
* Update the selection buffer with the given set of node indices.
|
||||
* Also computes neighbors of selected nodes.
|
||||
* Call this whenever React's selection state changes.
|
||||
* Neighbor indices are provided by the backend (SPARQL query) and uploaded separately.
|
||||
* Call this whenever selection or backend neighbor results change.
|
||||
*/
|
||||
updateSelection(selectedIndices: Set<number>): void {
|
||||
updateSelection(selectedIndices: Set<number>, neighborIndices: Set<number> = new Set()): void {
|
||||
const gl = this.gl;
|
||||
|
||||
// Upload selected indices
|
||||
@@ -425,23 +445,11 @@ export class Renderer {
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.DYNAMIC_DRAW);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
||||
|
||||
// Compute neighbors of selected nodes (excluding already selected)
|
||||
const neighborSet = new Set<number>();
|
||||
for (const nodeIdx of selectedIndices) {
|
||||
const nodeNeighbors = this.neighborMap.get(nodeIdx);
|
||||
if (!nodeNeighbors) continue;
|
||||
for (const n of nodeNeighbors) {
|
||||
if (!selectedIndices.has(n)) {
|
||||
neighborSet.add(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Upload neighbor indices
|
||||
const neighborIndices = new Uint32Array(neighborSet);
|
||||
this.neighborCount = neighborIndices.length;
|
||||
const neighborIndexArray = new Uint32Array(neighborIndices);
|
||||
this.neighborCount = neighborIndexArray.length;
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.neighborIbo);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, neighborIndices, gl.DYNAMIC_DRAW);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, neighborIndexArray, gl.DYNAMIC_DRAW);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user