MCPcopy
hub / github.com/opentrace/opentrace / applyLabelCulling

Method applyLabelCulling

ui/src/components/pixi/PixiRenderer.ts:1281–1368  ·  view source on GitHub ↗

* Show labels for the given nodes, culling any that overlap a previously * placed label. Nodes are processed largest-first so important nodes win. * * This method ONLY controls visibility. Scale and position are handled by * the update paths (update3D, updatePositionsFromBuffer, applyCou

(candidates: PixiNode[], invScale: number)

Source from the content-addressed store, hash-verified

1279 * to avoid jitter from competing writes.
1280 */
1281 private applyLabelCulling(candidates: PixiNode[], invScale: number): void {
1282 // Sort by size descending — largest (highest degree) nodes get labels first
1283 candidates.sort((a, b) => b.size - a.size);
1284
1285 const boxes: { x: number; y: number; w: number; h: number }[] = [];
1286 const lm = this.labelScaleMultiplier;
1287 const screenLabelScale = invScale * lm * this.vp.scale;
1288 const labelH = (LABEL_SIZE + 4) * screenLabelScale;
1289
1290 // Viewport bounds in screen pixels with a small margin so a label
1291 // partially clipped at the edge still gets a slot — avoids
1292 // labels popping in/out as you pan across the boundary (Fix #49).
1293 const VIEWPORT_MARGIN = 80;
1294 const vpLeft = -VIEWPORT_MARGIN;
1295 const vpRight = this.width + VIEWPORT_MARGIN;
1296 const vpTop = -VIEWPORT_MARGIN;
1297 const vpBottom = this.height + VIEWPORT_MARGIN;
1298
1299 // Skip labels for nodes whose sprite is too small on screen
1300 // (Fix #49). At zoom-out the entire graph compresses into a tiny
1301 // area; without this gate, every node still tries for a label
1302 // slot and the screen fills with text. Sprite on-screen radius =
1303 // node.size × vp.scale^(1-zoomSizeExponent). 2.5 px is the
1304 // current threshold — was 4, lowered so larger anchor nodes get
1305 // labels at lower zoom levels (overlap cull still keeps the
1306 // screen from filling with text at extreme zoom-out).
1307 const MIN_SPRITE_SCREEN_RADIUS = 2.5;
1308 const spriteRadiusFactor = Math.pow(
1309 this.vp.scale,
1310 Math.max(0, 1 - this.zoomSizeExponent),
1311 );
1312
1313 for (const node of candidates) {
1314 // Screen position of the sprite — used for the viewport
1315 // pre-filter (skip cull work for off-screen labels).
1316 const cx = node.sprite.position.x * this.vp.scale + this.vp.x;
1317 const cy = node.sprite.position.y * this.vp.scale + this.vp.y;
1318 if (cx < vpLeft || cx > vpRight || cy < vpTop || cy > vpBottom) {
1319 if (node.label) node.label.visible = false;
1320 continue;
1321 }
1322
1323 // Size gate — sprites too small to read don't get labels.
1324 const spriteScreenRadius = node.size * spriteRadiusFactor;
1325 if (spriteScreenRadius < MIN_SPRITE_SCREEN_RADIUS) {
1326 if (node.label) node.label.visible = false;
1327 continue;
1328 }
1329
1330 // World-space gap that lands the label just outside the sprite
1331 // edge (Fix #27 — the only piece of my label rework that
1332 // survived the revert; without it the label slides inside the
1333 // sprite at deep zoom because the sprite is in world coords
1334 // while the label is screen-pixel-constant).
1335 const gap = this.labelGap(node);
1336 const nx = node.sprite.position.x;
1337 const ny = node.sprite.position.y;
1338

Callers 4

applyCounterScaleMethod · 0.95
setNodeVisibilityMethod · 0.95
applyVisualsMethod · 0.95
runLabelCullMethod · 0.95

Calls 4

labelGapMethod · 0.95
createLabelMethod · 0.95
pushMethod · 0.80
cleanLabelFunction · 0.70

Tested by

no test coverage detected