feat: update algorithm integrations and point cloud overlays

This commit is contained in:
2026-06-30 16:46:36 +08:00
parent ddca7e5436
commit 7e2e56a50d
64 changed files with 4356 additions and 2781 deletions

View File

@@ -1,7 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
export type SampledPoint = { x: number; y: number; z: number; error: number };
export type SampledPoint = { x: number; y: number; z: number; error: number; r?: number; g?: number; b?: number };
/** 与 fileRoutes 批量采样一致:随机 seek 文本点云行 */
export async function randomSeekSample(
@@ -170,15 +170,20 @@ function samplePlyBinary(
const bytesPerVertex = properties.reduce((s, p) => s + p.byteSize, 0);
// 找 x, y, z(可能叫 x/y/z 或 X/Y/Z;允许宽松匹配)
// 找 x, y, z,以及 red/green/blue(uchar 0-255)
let xOff = -1, yOff = -1, zOff = -1;
let rOff = -1, gOff = -1, bOff = -1;
let xType = 'float', yType = 'float', zType = 'float';
let rType = 'uchar', gType = 'uchar', bType = 'uchar';
let byteOff = 0;
for (const p of properties) {
const n = p.name.toLowerCase();
if (n === 'x') { xOff = byteOff; xType = p.type; }
else if (n === 'y') { yOff = byteOff; yType = p.type; }
else if (n === 'z') { zOff = byteOff; zType = p.type; }
else if (n === 'red') { rOff = byteOff; rType = p.type; }
else if (n === 'green') { gOff = byteOff; gType = p.type; }
else if (n === 'blue') { bOff = byteOff; bType = p.type; }
byteOff += p.byteSize;
}
@@ -224,7 +229,13 @@ function samplePlyBinary(
const z = readNum(recBuf, zOff, zType);
if (!isFinite(x) || !isFinite(y) || !isFinite(z)) continue;
const error = Math.abs(Math.sin(x * 0.001) * Math.cos(z * 0.001)) * 1.5;
points.push({ x, y, z, error });
const pt: SampledPoint = { x, y, z, error };
if (rOff >= 0 && gOff >= 0 && bOff >= 0) {
pt.r = readNum(recBuf, rOff, rType);
pt.g = readNum(recBuf, gOff, gType);
pt.b = readNum(recBuf, bOff, bType);
}
points.push(pt);
}
} finally {
fs.closeSync(fd);
@@ -277,12 +288,25 @@ function samplePlyAscii(
const line = (nl2 === -1 ? afterFirst : afterFirst.slice(0, nl2)).trim();
if (!line) continue;
const parts = line.split(/\s+/);
const x = parseFloat(parts[0]);
const y = parseFloat(parts[1]);
const z = parseFloat(parts[2]);
// 按 header properties 顺序找 x/y/z/red/green/blue 的列索引
let xi = -1, yi = -1, zi = -1, ri = -1, gi = -1, bi = -1;
header.properties.forEach((p, i) => {
const n = p.name.toLowerCase();
if (n === 'x') xi = i; else if (n === 'y') yi = i; else if (n === 'z') zi = i;
else if (n === 'red') ri = i; else if (n === 'green') gi = i; else if (n === 'blue') bi = i;
});
const x = parseFloat(parts[xi >= 0 ? xi : 0]);
const y = parseFloat(parts[yi >= 0 ? yi : 1]);
const z = parseFloat(parts[zi >= 0 ? zi : 2]);
if (!isFinite(x) || !isFinite(y) || !isFinite(z)) continue;
const error = Math.abs(Math.sin(x * 0.001) * Math.cos(z * 0.001)) * 1.5;
points.push({ x, y, z, error });
const pt: SampledPoint = { x, y, z, error };
if (ri >= 0 && gi >= 0 && bi >= 0 && parts[ri] !== undefined) {
pt.r = parseFloat(parts[ri]);
pt.g = parseFloat(parts[gi]);
pt.b = parseFloat(parts[bi]);
}
points.push(pt);
}
} finally {
fs.closeSync(fd);