release: bump version to 0.37.0

This commit is contained in:
rayd1o
2026-04-23 07:56:10 +08:00
parent abe04030fb
commit 67f82dc41c
22 changed files with 1417 additions and 226 deletions

View File

@@ -1,17 +1,73 @@
import * as THREE from "three";
import { COMPUTE_CENTER_CONFIG, CONFIG, PATHS } from "./constants.js";
import { latLonToVector3 } from "./utils.js";
import { getSurfaceMarkerCameraScale, latLonToVector3 } from "./utils.js";
const computeCenterGroup = new THREE.Group();
const computeCenterMarkers = [];
const textureCache = new Map();
const scratchMarkerWorldPosition = new THREE.Vector3();
let showComputeCenters = true;
let supercomputerCount = 0;
let gpuClusterCount = 0;
function buildComputeCenterMarkerData(feature) {
const props = feature?.properties || {};
const coordinates = feature?.geometry?.coordinates || [];
const longitude = Number(coordinates[0]);
const latitude = Number(coordinates[1]);
if (!Number.isFinite(latitude) || !Number.isFinite(longitude)) {
return null;
}
return {
...props,
latitude,
longitude,
displayLatitude: latitude,
displayLongitude: longitude,
site_type: normalizeSiteType(props.site_type),
};
}
function spreadComputeCenterPositions(markers) {
const groups = new Map();
const precision = COMPUTE_CENTER_CONFIG.overlapSpread.groupPrecision;
markers.forEach((marker) => {
const key = `${marker.latitude.toFixed(precision)}|${marker.longitude.toFixed(precision)}`;
if (!groups.has(key)) {
groups.set(key, []);
}
groups.get(key).push(marker);
});
groups.forEach((group) => {
if (group.length <= 1) return;
const radius = COMPUTE_CENTER_CONFIG.overlapSpread.radius;
const offsetStep = COMPUTE_CENTER_CONFIG.overlapSpread.offsetStep;
group.forEach((marker, index) => {
const angle = (Math.PI * 2 * index) / group.length;
marker.displayLatitude =
marker.latitude + Math.sin(angle) * radius * offsetStep;
marker.displayLongitude =
marker.longitude + Math.cos(angle) * radius * offsetStep;
marker.isSpread = true;
marker.groupSize = group.length;
});
});
markers.forEach((marker) => {
if (marker.isSpread) return;
marker.displayLatitude = marker.latitude;
marker.displayLongitude = marker.longitude;
marker.isSpread = false;
marker.groupSize = 1;
});
return markers;
}
function createMarkerTexture(siteType, isEstimated = false) {
const textureKey = `${siteType}:${isEstimated ? "estimated" : "precise"}`;
if (textureCache.has(textureKey)) {
@@ -106,21 +162,12 @@ function getDistanceScale(marker, camera) {
return 1;
}
const distanceToCamera = camera.position.distanceTo(
marker.getWorldPosition(scratchMarkerWorldPosition),
);
const referenceDistance =
CONFIG.defaultCameraZ - CONFIG.earthRadius + COMPUTE_CENTER_CONFIG.altitudeOffset;
const referenceFovRad = (75 * Math.PI) / 180;
const cameraFovRad = ((camera.fov || 75) * Math.PI) / 180;
const worldPerPixel = distanceToCamera * Math.tan(cameraFovRad / 2);
const referenceWorldPerPixel = referenceDistance * Math.tan(referenceFovRad / 2);
const scale = worldPerPixel / referenceWorldPerPixel;
return THREE.MathUtils.clamp(
scale,
COMPUTE_CENTER_CONFIG.sizeStabilization.min,
COMPUTE_CENTER_CONFIG.sizeStabilization.max,
);
return getSurfaceMarkerCameraScale(camera, {
altitudeOffset: COMPUTE_CENTER_CONFIG.altitudeOffset,
referenceFov: 75,
min: COMPUTE_CENTER_CONFIG.sizeStabilization.min,
max: COMPUTE_CENTER_CONFIG.sizeStabilization.max,
});
}
function clearGroup(group) {
@@ -131,18 +178,10 @@ function clearGroup(group) {
}
}
function createComputeCenterMarker(feature) {
const props = feature?.properties || {};
const coordinates = feature?.geometry?.coordinates || [];
const longitude = Number(coordinates[0]);
const latitude = Number(coordinates[1]);
if (!Number.isFinite(latitude) || !Number.isFinite(longitude)) {
return null;
}
const siteType = normalizeSiteType(props.site_type);
function createComputeCenterMarker(markerData) {
const siteType = markerData.site_type;
const material = new THREE.SpriteMaterial({
map: createMarkerTexture(siteType, Boolean(props.is_estimated)),
map: createMarkerTexture(siteType, Boolean(markerData.is_estimated)),
transparent: true,
depthWrite: false,
opacity: COMPUTE_CENTER_CONFIG.marker.baseOpacity,
@@ -151,8 +190,8 @@ function createComputeCenterMarker(feature) {
const baseScale = getBaseScale(siteType);
marker.position.copy(
latLonToVector3(
latitude,
longitude,
markerData.displayLatitude,
markerData.displayLongitude,
CONFIG.earthRadius + COMPUTE_CENTER_CONFIG.altitudeOffset,
),
);
@@ -160,9 +199,7 @@ function createComputeCenterMarker(feature) {
marker.renderOrder = 8;
marker.visible = showComputeCenters;
marker.userData = {
...props,
latitude,
longitude,
...markerData,
site_type: siteType,
type: "compute_center",
baseScale,
@@ -275,10 +312,14 @@ export async function loadComputeCenters(_scene, earth) {
clearComputeCenterData(earth);
features
spreadComputeCenterPositions(
features
.map((feature) => buildComputeCenterMarkerData(feature))
.filter(Boolean),
)
.slice(0, COMPUTE_CENTER_CONFIG.maxRenderedMarkers)
.forEach((feature) => {
const marker = createComputeCenterMarker(feature);
.forEach((markerData) => {
const marker = createComputeCenterMarker(markerData);
if (!marker) return;
if (marker.userData.site_type === "supercomputer") {
supercomputerCount += 1;