frontend: expand cosmos runtime tuning and diagnostics

This commit is contained in:
Oxy8
2026-04-06 13:36:42 -03:00
parent ca715d7c3c
commit 48ce99aac5
5 changed files with 380 additions and 17 deletions

View File

@@ -1,6 +1,6 @@
import { memo, useEffect, useMemo, useRef, useState } from "react";
import { Graph, type GraphConfig } from "@cosmos.gl/graph";
import { cosmosRuntimeConfig } from "./cosmos_config";
import { cosmosBackgroundCss, cosmosRuntimeConfig } from "./cosmos_config";
import {
computeLayoutMetrics,
type GraphLayoutMetrics,
@@ -194,28 +194,68 @@ export const TripleGraphView = memo(function TripleGraphView({ model }: TripleGr
};
const config: GraphConfig = {
backgroundColor: "#05070a",
backgroundColor: cosmosRuntimeConfig.backgroundColor,
spaceSize: cosmosRuntimeConfig.spaceSize,
enableSimulation: cosmosRuntimeConfig.enableSimulation,
enableDrag: true,
enableZoom: true,
fitViewOnInit: false,
pointDefaultColor: cosmosRuntimeConfig.pointDefaultColor,
pointGreyoutColor: cosmosRuntimeConfig.pointGreyoutColor,
pointGreyoutOpacity: cosmosRuntimeConfig.pointGreyoutOpacity,
pointDefaultSize: cosmosRuntimeConfig.pointDefaultSize,
pointOpacity: cosmosRuntimeConfig.pointOpacity,
pointSizeScale: cosmosRuntimeConfig.pointSizeScale,
hoveredPointCursor: cosmosRuntimeConfig.hoveredPointCursor,
hoveredLinkCursor: cosmosRuntimeConfig.hoveredLinkCursor,
renderHoveredPointRing: cosmosRuntimeConfig.renderHoveredPointRing,
hoveredPointRingColor: cosmosRuntimeConfig.hoveredPointRingColor,
focusedPointRingColor: cosmosRuntimeConfig.focusedPointRingColor,
renderLinks: cosmosRuntimeConfig.renderLinks,
linkDefaultColor: cosmosRuntimeConfig.linkDefaultColor,
linkOpacity: cosmosRuntimeConfig.linkOpacity,
linkGreyoutOpacity: cosmosRuntimeConfig.linkGreyoutOpacity,
linkDefaultWidth: cosmosRuntimeConfig.linkDefaultWidth,
hoveredLinkColor: cosmosRuntimeConfig.hoveredLinkColor,
hoveredLinkWidthIncrease: cosmosRuntimeConfig.hoveredLinkWidthIncrease,
linkWidthScale: cosmosRuntimeConfig.linkWidthScale,
scaleLinksOnZoom: cosmosRuntimeConfig.scaleLinksOnZoom,
enableDrag: cosmosRuntimeConfig.enableDrag,
enableZoom: cosmosRuntimeConfig.enableZoom,
enableSimulationDuringZoom: cosmosRuntimeConfig.enableSimulationDuringZoom,
fitViewOnInit: cosmosRuntimeConfig.fitViewOnInit,
fitViewDelay: cosmosRuntimeConfig.fitViewDelay,
fitViewPadding: cosmosRuntimeConfig.fitViewPadding,
rescalePositions: false,
fitViewDuration: cosmosRuntimeConfig.fitViewDuration,
initialZoomLevel: cosmosRuntimeConfig.initialZoomLevel,
pointSamplingDistance: cosmosRuntimeConfig.pointSamplingDistance,
rescalePositions: cosmosRuntimeConfig.rescalePositions,
curvedLinks: cosmosRuntimeConfig.curvedLinks,
curvedLinkSegments: cosmosRuntimeConfig.curvedLinkSegments,
curvedLinkWeight: cosmosRuntimeConfig.curvedLinkWeight,
curvedLinkControlPointDistance: cosmosRuntimeConfig.curvedLinkControlPointDistance,
linkDefaultArrows: cosmosRuntimeConfig.linkDefaultArrows,
linkArrowsSizeScale: cosmosRuntimeConfig.linkArrowsSizeScale,
linkVisibilityDistanceRange: cosmosRuntimeConfig.linkVisibilityDistanceRange,
linkVisibilityMinTransparency: cosmosRuntimeConfig.linkVisibilityMinTransparency,
useClassicQuadtree: cosmosRuntimeConfig.useClassicQuadtree,
simulationDecay: cosmosRuntimeConfig.simulationDecay,
simulationGravity: cosmosRuntimeConfig.simulationGravity,
simulationCenter: cosmosRuntimeConfig.simulationCenter,
simulationRepulsion: cosmosRuntimeConfig.simulationRepulsion,
simulationRepulsionTheta: cosmosRuntimeConfig.simulationRepulsionTheta,
simulationRepulsionQuadtreeLevels:
cosmosRuntimeConfig.simulationRepulsionQuadtreeLevels,
simulationLinkSpring: cosmosRuntimeConfig.simulationLinkSpring,
simulationLinkDistance: cosmosRuntimeConfig.simulationLinkDistance,
simulationLinkDistRandomVariationRange:
cosmosRuntimeConfig.simulationLinkDistRandomVariationRange,
simulationRepulsionFromMouse: cosmosRuntimeConfig.simulationRepulsionFromMouse,
enableRightClickRepulsion: cosmosRuntimeConfig.enableRightClickRepulsion,
simulationFriction: cosmosRuntimeConfig.simulationFriction,
renderHoveredPointRing: true,
hoveredPointRingColor: "#35d6ff",
hoveredPointCursor: "pointer",
hoveredLinkCursor: "pointer",
hoveredLinkColor: "#ffd166",
hoveredLinkWidthIncrease: 2.5,
simulationCluster: cosmosRuntimeConfig.simulationCluster,
randomSeed: cosmosRuntimeConfig.randomSeed,
showFPSMonitor: cosmosRuntimeConfig.showFPSMonitor,
pixelRatio: cosmosRuntimeConfig.pixelRatio,
scalePointsOnZoom: cosmosRuntimeConfig.scalePointsOnZoom,
attribution: cosmosRuntimeConfig.attribution,
onSimulationStart: () => {
reportLayout("simulation-start", "running", 1);
},
@@ -320,7 +360,14 @@ export const TripleGraphView = memo(function TripleGraphView({ model }: TripleGr
}, [activeDetail]);
return (
<div style={{ position: "relative", flex: 1, minHeight: 0, background: "#05070a" }}>
<div
style={{
position: "relative",
flex: 1,
minHeight: 0,
background: cosmosBackgroundCss,
}}
>
<div
ref={containerRef}
style={{ position: "absolute", inset: 0, width: "100%", height: "100%" }}
@@ -468,7 +515,18 @@ function applyGraphModel(graph: Graph, model: TripleGraphModel): void {
graph.setLinkWidths(model.linkWidths);
graph.render(0);
requestAnimationFrame(() => {
graph.fitViewByPointPositions(Array.from(model.pointPositions), 0, cosmosRuntimeConfig.fitViewPadding);
if (typeof cosmosRuntimeConfig.initialZoomLevel === "number") {
graph.setZoomLevel(
cosmosRuntimeConfig.initialZoomLevel,
cosmosRuntimeConfig.fitViewDuration,
);
} else {
graph.fitViewByPointPositions(
Array.from(model.pointPositions),
cosmosRuntimeConfig.fitViewDuration,
cosmosRuntimeConfig.fitViewPadding,
);
}
if (cosmosRuntimeConfig.enableSimulation) {
graph.start(1);
}

View File

@@ -1,3 +1,5 @@
type CosmosColor = string | [number, number, number, number];
function parseBoolean(value: string | undefined, fallback: boolean): boolean {
if (value === undefined) return fallback;
const normalized = value.trim().toLowerCase();
@@ -12,17 +14,167 @@ function parseNumber(value: string | undefined, fallback: number): number {
return Number.isFinite(parsed) ? parsed : fallback;
}
function parseOptionalNumber(value: string | undefined): number | undefined {
if (value === undefined) return undefined;
const trimmed = value.trim();
if (trimmed.length === 0) return undefined;
const parsed = Number(trimmed);
return Number.isFinite(parsed) ? parsed : undefined;
}
function parseOptionalString(value: string | undefined): string | undefined {
if (value === undefined) return undefined;
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : undefined;
}
function parseNumberList(value: string | undefined, fallback: number[]): number[] {
return parseOptionalNumberList(value) ?? fallback;
}
function parseOptionalNumberList(value: string | undefined): number[] | undefined {
const raw = parseOptionalString(value);
if (!raw) return undefined;
const normalized = raw.startsWith("[") && raw.endsWith("]") ? raw.slice(1, -1) : raw;
const parts = normalized
.split(",")
.map((entry) => entry.trim())
.filter((entry) => entry.length > 0);
if (parts.length === 0) return undefined;
const parsed = parts.map((entry) => Number(entry));
return parsed.every((entry) => Number.isFinite(entry)) ? parsed : undefined;
}
function parseColor(value: string | undefined, fallback: CosmosColor): CosmosColor {
return parseOptionalColor(value) ?? fallback;
}
function parseOptionalColor(value: string | undefined): CosmosColor | undefined {
const raw = parseOptionalString(value);
if (!raw) return undefined;
const rgba = parseOptionalNumberList(raw);
if (rgba && rgba.length === 4) {
return [rgba[0], rgba[1], rgba[2], rgba[3]];
}
return raw;
}
function parseOptionalSeed(value: string | undefined): number | string | undefined {
const raw = parseOptionalString(value);
if (!raw) return undefined;
const numeric = Number(raw);
return Number.isFinite(numeric) ? numeric : raw;
}
function toCssColor(color: CosmosColor): string {
if (typeof color === "string") return color;
return `rgba(${color[0]}, ${color[1]}, ${color[2]}, ${color[3] / 255})`;
}
export const cosmosRuntimeConfig = {
enableSimulation: parseBoolean(import.meta.env.VITE_COSMOS_ENABLE_SIMULATION, true),
debugLayout: parseBoolean(import.meta.env.VITE_COSMOS_DEBUG_LAYOUT, false),
backgroundColor: parseColor(import.meta.env.VITE_COSMOS_BACKGROUND_COLOR, "#05070a"),
spaceSize: parseNumber(import.meta.env.VITE_COSMOS_SPACE_SIZE, 4096),
pointDefaultColor: parseOptionalColor(import.meta.env.VITE_COSMOS_POINT_DEFAULT_COLOR),
pointGreyoutColor: parseOptionalColor(import.meta.env.VITE_COSMOS_POINT_GREYOUT_COLOR),
pointGreyoutOpacity: parseOptionalNumber(import.meta.env.VITE_COSMOS_POINT_GREYOUT_OPACITY),
pointDefaultSize: parseNumber(import.meta.env.VITE_COSMOS_POINT_DEFAULT_SIZE, 4),
pointOpacity: parseNumber(import.meta.env.VITE_COSMOS_POINT_OPACITY, 1),
pointSizeScale: parseNumber(import.meta.env.VITE_COSMOS_POINT_SIZE_SCALE, 1),
hoveredPointCursor: parseOptionalString(import.meta.env.VITE_COSMOS_HOVERED_POINT_CURSOR) ?? "pointer",
hoveredLinkCursor: parseOptionalString(import.meta.env.VITE_COSMOS_HOVERED_LINK_CURSOR) ?? "pointer",
renderHoveredPointRing: parseBoolean(
import.meta.env.VITE_COSMOS_RENDER_HOVERED_POINT_RING,
true,
),
hoveredPointRingColor: parseColor(
import.meta.env.VITE_COSMOS_HOVERED_POINT_RING_COLOR,
"#35d6ff",
),
focusedPointRingColor: parseColor(
import.meta.env.VITE_COSMOS_FOCUSED_POINT_RING_COLOR,
"white",
),
renderLinks: parseBoolean(import.meta.env.VITE_COSMOS_RENDER_LINKS, true),
linkDefaultColor: parseOptionalColor(import.meta.env.VITE_COSMOS_LINK_DEFAULT_COLOR),
linkOpacity: parseNumber(import.meta.env.VITE_COSMOS_LINK_OPACITY, 1),
linkGreyoutOpacity: parseNumber(import.meta.env.VITE_COSMOS_LINK_GREYOUT_OPACITY, 0.1),
linkDefaultWidth: parseNumber(import.meta.env.VITE_COSMOS_LINK_DEFAULT_WIDTH, 1),
hoveredLinkColor: parseColor(import.meta.env.VITE_COSMOS_HOVERED_LINK_COLOR, "#ffd166"),
hoveredLinkWidthIncrease: parseNumber(
import.meta.env.VITE_COSMOS_HOVERED_LINK_WIDTH_INCREASE,
2.5,
),
linkWidthScale: parseNumber(import.meta.env.VITE_COSMOS_LINK_WIDTH_SCALE, 1),
scaleLinksOnZoom: parseBoolean(import.meta.env.VITE_COSMOS_SCALE_LINKS_ON_ZOOM, false),
curvedLinks: parseBoolean(import.meta.env.VITE_COSMOS_CURVED_LINKS, true),
fitViewPadding: parseNumber(import.meta.env.VITE_COSMOS_FIT_VIEW_PADDING, 0.12),
curvedLinkSegments: parseNumber(import.meta.env.VITE_COSMOS_CURVED_LINK_SEGMENTS, 19),
curvedLinkWeight: parseNumber(import.meta.env.VITE_COSMOS_CURVED_LINK_WEIGHT, 0.8),
curvedLinkControlPointDistance: parseNumber(
import.meta.env.VITE_COSMOS_CURVED_LINK_CONTROL_POINT_DISTANCE,
0.5,
),
linkDefaultArrows: parseBoolean(import.meta.env.VITE_COSMOS_LINK_DEFAULT_ARROWS, false),
linkArrowsSizeScale: parseNumber(import.meta.env.VITE_COSMOS_LINK_ARROWS_SIZE_SCALE, 1),
linkVisibilityDistanceRange: parseNumberList(
import.meta.env.VITE_COSMOS_LINK_VISIBILITY_DISTANCE_RANGE,
[50, 150],
),
linkVisibilityMinTransparency: parseNumber(
import.meta.env.VITE_COSMOS_LINK_VISIBILITY_MIN_TRANSPARENCY,
0.25,
),
useClassicQuadtree: parseBoolean(import.meta.env.VITE_COSMOS_USE_CLASSIC_QUADTREE, false),
simulationDecay: parseNumber(import.meta.env.VITE_COSMOS_SIMULATION_DECAY, 5000),
simulationGravity: parseNumber(import.meta.env.VITE_COSMOS_SIMULATION_GRAVITY, 0),
simulationCenter: parseNumber(import.meta.env.VITE_COSMOS_SIMULATION_CENTER, 0.05),
simulationRepulsion: parseNumber(import.meta.env.VITE_COSMOS_SIMULATION_REPULSION, 0.5),
simulationRepulsionTheta: parseNumber(
import.meta.env.VITE_COSMOS_SIMULATION_REPULSION_THETA,
1.15,
),
simulationRepulsionQuadtreeLevels: parseNumber(
import.meta.env.VITE_COSMOS_SIMULATION_REPULSION_QUADTREE_LEVELS,
12,
),
simulationLinkSpring: parseNumber(import.meta.env.VITE_COSMOS_SIMULATION_LINK_SPRING, 1),
simulationLinkDistance: parseNumber(import.meta.env.VITE_COSMOS_SIMULATION_LINK_DISTANCE, 10),
simulationLinkDistRandomVariationRange: parseNumberList(
import.meta.env.VITE_COSMOS_SIMULATION_LINK_DISTANCE_RANDOM_VARIATION_RANGE,
[1, 1.2],
),
simulationRepulsionFromMouse: parseNumber(
import.meta.env.VITE_COSMOS_SIMULATION_REPULSION_FROM_MOUSE,
2,
),
enableRightClickRepulsion: parseBoolean(
import.meta.env.VITE_COSMOS_ENABLE_RIGHT_CLICK_REPULSION,
false,
),
simulationFriction: parseNumber(import.meta.env.VITE_COSMOS_SIMULATION_FRICTION, 0.1),
} as const;
simulationCluster: parseNumber(import.meta.env.VITE_COSMOS_SIMULATION_CLUSTER, 0.1),
showFPSMonitor: parseBoolean(import.meta.env.VITE_COSMOS_SHOW_FPS_MONITOR, false),
pixelRatio: parseNumber(import.meta.env.VITE_COSMOS_PIXEL_RATIO, 2),
scalePointsOnZoom: parseBoolean(import.meta.env.VITE_COSMOS_SCALE_POINTS_ON_ZOOM, false),
initialZoomLevel: parseOptionalNumber(import.meta.env.VITE_COSMOS_INITIAL_ZOOM_LEVEL),
enableZoom: parseBoolean(import.meta.env.VITE_COSMOS_ENABLE_ZOOM, true),
enableSimulationDuringZoom: parseBoolean(
import.meta.env.VITE_COSMOS_ENABLE_SIMULATION_DURING_ZOOM,
false,
),
enableDrag: parseBoolean(import.meta.env.VITE_COSMOS_ENABLE_DRAG, true),
fitViewOnInit: parseBoolean(import.meta.env.VITE_COSMOS_FIT_VIEW_ON_INIT, false),
fitViewDelay: parseNumber(import.meta.env.VITE_COSMOS_FIT_VIEW_DELAY, 250),
fitViewPadding: parseNumber(import.meta.env.VITE_COSMOS_FIT_VIEW_PADDING, 0.12),
fitViewDuration: parseNumber(import.meta.env.VITE_COSMOS_FIT_VIEW_DURATION, 250),
randomSeed: parseOptionalSeed(import.meta.env.VITE_COSMOS_RANDOM_SEED),
pointSamplingDistance: parseNumber(
import.meta.env.VITE_COSMOS_POINT_SAMPLING_DISTANCE,
150,
),
rescalePositions: parseBoolean(import.meta.env.VITE_COSMOS_RESCALE_POSITIONS, false),
attribution: parseOptionalString(import.meta.env.VITE_COSMOS_ATTRIBUTION),
};
export const cosmosBackgroundCss = toCssColor(cosmosRuntimeConfig.backgroundColor);

View File

@@ -213,12 +213,23 @@ export class Renderer {
const count = xs.length;
const edgeCount = edges.length / 2;
this.nodeCount = count;
console.log("[renderer.init] start", {
nodes: count,
edges: edgeCount,
route_line_vertices: routeLineVertices ? routeLineVertices.length / 2 : 0,
});
// Build quadtree (spatially sorts the array)
const spatialStart = performance.now();
const { sorted, leaves, order } = buildSpatialIndex(xs, ys);
this.leaves = leaves;
this.sorted = sorted;
this.sortedToOriginal = order;
console.log("[renderer.init] spatial index built", {
nodes: count,
leaves: leaves.length,
spatial_ms: Math.round(performance.now() - spatialStart),
});
// Pre-allocate arrays for render loop (zero-allocation rendering)
this.visibleLeafIndices = new Uint32Array(leaves.length);
@@ -226,12 +237,18 @@ export class Renderer {
this.countsArray = new Int32Array(leaves.length);
// Upload sorted particles to GPU as STATIC VBO (never changes)
const uploadNodesStart = performance.now();
gl.bindVertexArray(this.vao);
gl.bindBuffer(gl.ARRAY_BUFFER, this.nodeVbo);
gl.bufferData(gl.ARRAY_BUFFER, sorted, gl.STATIC_DRAW);
gl.bindVertexArray(null);
console.log("[renderer.init] node buffer uploaded", {
upload_ms: Math.round(performance.now() - uploadNodesStart),
sorted_bytes: sorted.byteLength,
});
// Build vertex ID → original input index mapping
const mapsStart = performance.now();
const vertexIdToOriginal = new Map<number, number>();
for (let i = 0; i < count; i++) {
vertexIdToOriginal.set(vertexIds[i], i);
@@ -250,6 +267,10 @@ export class Renderer {
vertexIdToSortedIndex.set(vertexIds[i], originalToSorted[i]);
}
this.vertexIdToSortedIndex = vertexIdToSortedIndex;
console.log("[renderer.init] index maps built", {
maps_ms: Math.round(performance.now() - mapsStart),
vertex_id_map_size: vertexIdToSortedIndex.size,
});
this.useRawLineSegments = routeLineVertices !== null && routeLineVertices.length > 0;
this.rawLineVertexCount = this.useRawLineSegments && routeLineVertices ? routeLineVertices.length / 2 : 0;
@@ -257,14 +278,20 @@ export class Renderer {
this.edgeCount = edgeCount;
this.leafEdgeStarts = new Uint32Array(0);
this.leafEdgeCounts = new Uint32Array(0);
const uploadRoutesStart = performance.now();
gl.bindVertexArray(this.lineVao);
gl.bindBuffer(gl.ARRAY_BUFFER, this.lineVbo);
gl.bufferData(gl.ARRAY_BUFFER, routeLineVertices, gl.STATIC_DRAW);
gl.bindVertexArray(null);
console.log("[renderer.init] raw line segments uploaded", {
upload_ms: Math.round(performance.now() - uploadRoutesStart),
total_ms: Math.round(performance.now() - t0),
});
return performance.now() - t0;
}
// Remap edges from vertex IDs to sorted indices
const remapEdgesStart = performance.now();
const lineIndices = new Uint32Array(edgeCount * 2);
let validEdges = 0;
for (let i = 0; i < edgeCount; i++) {
@@ -278,9 +305,15 @@ export class Renderer {
validEdges++;
}
this.edgeCount = validEdges;
console.log("[renderer.init] edges remapped", {
remap_ms: Math.round(performance.now() - remapEdgesStart),
valid_edges: validEdges,
line_indices_bytes: lineIndices.byteLength,
});
// Build per-leaf edge index for efficient visible-only edge drawing
// Find which leaf each sorted index belongs to
const edgeIndexStart = performance.now();
const nodeToLeaf = new Uint32Array(count);
for (let li = 0; li < leaves.length; li++) {
const lf = leaves[li];
@@ -314,11 +347,22 @@ export class Renderer {
this.leafEdgeStarts = leafEdgeOffsets;
this.leafEdgeCounts = leafEdgeCounts;
console.log("[renderer.init] leaf edge index built", {
leaf_index_ms: Math.round(performance.now() - edgeIndexStart),
leaves: leaves.length,
sorted_edge_indices_bytes: sortedEdgeIndices.byteLength,
});
// Upload sorted edges to GPU
const uploadEdgesStart = performance.now();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.linesIbo);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sortedEdgeIndices, gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
console.log("[renderer.init] edge buffer uploaded", {
upload_ms: Math.round(performance.now() - uploadEdgesStart),
total_ms: Math.round(performance.now() - t0),
valid_edges: validEdges,
});
return performance.now() - t0;
}

View File

@@ -4,16 +4,65 @@ interface ImportMetaEnv {
readonly VITE_BACKEND_URL?: string;
readonly VITE_COSMOS_ENABLE_SIMULATION?: string;
readonly VITE_COSMOS_DEBUG_LAYOUT?: string;
readonly VITE_COSMOS_BACKGROUND_COLOR?: string;
readonly VITE_COSMOS_SPACE_SIZE?: string;
readonly VITE_COSMOS_POINT_DEFAULT_COLOR?: string;
readonly VITE_COSMOS_POINT_GREYOUT_COLOR?: string;
readonly VITE_COSMOS_POINT_GREYOUT_OPACITY?: string;
readonly VITE_COSMOS_POINT_DEFAULT_SIZE?: string;
readonly VITE_COSMOS_POINT_OPACITY?: string;
readonly VITE_COSMOS_POINT_SIZE_SCALE?: string;
readonly VITE_COSMOS_HOVERED_POINT_CURSOR?: string;
readonly VITE_COSMOS_HOVERED_LINK_CURSOR?: string;
readonly VITE_COSMOS_RENDER_HOVERED_POINT_RING?: string;
readonly VITE_COSMOS_HOVERED_POINT_RING_COLOR?: string;
readonly VITE_COSMOS_FOCUSED_POINT_RING_COLOR?: string;
readonly VITE_COSMOS_RENDER_LINKS?: string;
readonly VITE_COSMOS_LINK_DEFAULT_COLOR?: string;
readonly VITE_COSMOS_LINK_OPACITY?: string;
readonly VITE_COSMOS_LINK_GREYOUT_OPACITY?: string;
readonly VITE_COSMOS_LINK_DEFAULT_WIDTH?: string;
readonly VITE_COSMOS_HOVERED_LINK_COLOR?: string;
readonly VITE_COSMOS_HOVERED_LINK_WIDTH_INCREASE?: string;
readonly VITE_COSMOS_LINK_WIDTH_SCALE?: string;
readonly VITE_COSMOS_SCALE_LINKS_ON_ZOOM?: string;
readonly VITE_COSMOS_CURVED_LINKS?: string;
readonly VITE_COSMOS_CURVED_LINK_SEGMENTS?: string;
readonly VITE_COSMOS_CURVED_LINK_WEIGHT?: string;
readonly VITE_COSMOS_CURVED_LINK_CONTROL_POINT_DISTANCE?: string;
readonly VITE_COSMOS_LINK_DEFAULT_ARROWS?: string;
readonly VITE_COSMOS_LINK_ARROWS_SIZE_SCALE?: string;
readonly VITE_COSMOS_LINK_VISIBILITY_DISTANCE_RANGE?: string;
readonly VITE_COSMOS_LINK_VISIBILITY_MIN_TRANSPARENCY?: string;
readonly VITE_COSMOS_USE_CLASSIC_QUADTREE?: string;
readonly VITE_COSMOS_FIT_VIEW_PADDING?: string;
readonly VITE_COSMOS_SIMULATION_DECAY?: string;
readonly VITE_COSMOS_SIMULATION_GRAVITY?: string;
readonly VITE_COSMOS_SIMULATION_CENTER?: string;
readonly VITE_COSMOS_SIMULATION_REPULSION?: string;
readonly VITE_COSMOS_SIMULATION_REPULSION_THETA?: string;
readonly VITE_COSMOS_SIMULATION_REPULSION_QUADTREE_LEVELS?: string;
readonly VITE_COSMOS_SIMULATION_LINK_SPRING?: string;
readonly VITE_COSMOS_SIMULATION_LINK_DISTANCE?: string;
readonly VITE_COSMOS_SIMULATION_LINK_DISTANCE_RANDOM_VARIATION_RANGE?: string;
readonly VITE_COSMOS_SIMULATION_REPULSION_FROM_MOUSE?: string;
readonly VITE_COSMOS_ENABLE_RIGHT_CLICK_REPULSION?: string;
readonly VITE_COSMOS_SIMULATION_FRICTION?: string;
readonly VITE_COSMOS_SIMULATION_CLUSTER?: string;
readonly VITE_COSMOS_SHOW_FPS_MONITOR?: string;
readonly VITE_COSMOS_PIXEL_RATIO?: string;
readonly VITE_COSMOS_SCALE_POINTS_ON_ZOOM?: string;
readonly VITE_COSMOS_INITIAL_ZOOM_LEVEL?: string;
readonly VITE_COSMOS_ENABLE_ZOOM?: string;
readonly VITE_COSMOS_ENABLE_SIMULATION_DURING_ZOOM?: string;
readonly VITE_COSMOS_ENABLE_DRAG?: string;
readonly VITE_COSMOS_FIT_VIEW_ON_INIT?: string;
readonly VITE_COSMOS_FIT_VIEW_DELAY?: string;
readonly VITE_COSMOS_FIT_VIEW_DURATION?: string;
readonly VITE_COSMOS_RANDOM_SEED?: string;
readonly VITE_COSMOS_POINT_SAMPLING_DISTANCE?: string;
readonly VITE_COSMOS_RESCALE_POSITIONS?: string;
readonly VITE_COSMOS_ATTRIBUTION?: string;
}
interface ImportMeta {