feat: add local access control and managed point clouds

This commit is contained in:
2026-07-22 11:05:48 +08:00
parent 683e4d6c07
commit 8555aa2f2e
46 changed files with 1982 additions and 884 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; r?: number; g?: number; b?: number };
export type SampledPoint = { x: number; y: number; z: number; error?: number; r?: number; g?: number; b?: number };
/** 与 fileRoutes 批量采样一致:随机 seek 文本点云行 */
export async function randomSeekSample(
@@ -66,9 +66,10 @@ export async function randomSeekSample(
const y = parseFloat(parts[1]);
const z = parseFloat(parts[2]);
if (isNaN(x) || isNaN(y) || isNaN(z)) continue;
let error = parts.length >= 4 ? parseFloat(parts[3]) : NaN;
if (isNaN(error)) error = Math.abs(Math.sin(x * 0.5) * Math.cos(z * 0.5)) * 1.5;
points.push({ x, y, z, error });
const parsedError = parts.length >= 4 ? parseFloat(parts[3]) : NaN;
const point: SampledPoint = { x, y, z };
if (Number.isFinite(parsedError)) point.error = parsedError;
points.push(point);
}
} finally {
fs.closeSync(fd);
@@ -173,8 +174,10 @@ function samplePlyBinary(
// 找 x, y, z,以及 red/green/blue(uchar 0-255)
let xOff = -1, yOff = -1, zOff = -1;
let rOff = -1, gOff = -1, bOff = -1;
let errorOff = -1;
let xType = 'float', yType = 'float', zType = 'float';
let rType = 'uchar', gType = 'uchar', bType = 'uchar';
let errorType = 'float';
let byteOff = 0;
for (const p of properties) {
const n = p.name.toLowerCase();
@@ -184,6 +187,7 @@ function samplePlyBinary(
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; }
else if (n === 'error' || n === 'deviation') { errorOff = byteOff; errorType = p.type; }
byteOff += p.byteSize;
}
@@ -228,8 +232,11 @@ function samplePlyBinary(
const y = readNum(recBuf, yOff, yType);
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;
const pt: SampledPoint = { x, y, z, error };
const pt: SampledPoint = { x, y, z };
if (errorOff >= 0) {
const error = readNum(recBuf, errorOff, errorType);
if (Number.isFinite(error)) pt.error = error;
}
if (rOff >= 0 && gOff >= 0 && bOff >= 0) {
pt.r = readNum(recBuf, rOff, rType);
pt.g = readNum(recBuf, gOff, gType);
@@ -289,18 +296,22 @@ function samplePlyAscii(
if (!line) continue;
const parts = line.split(/\s+/);
// 按 header properties 顺序找 x/y/z/red/green/blue 的列索引
let xi = -1, yi = -1, zi = -1, ri = -1, gi = -1, bi = -1;
let xi = -1, yi = -1, zi = -1, ri = -1, gi = -1, bi = -1, errorI = -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;
else if (n === 'error' || n === 'deviation') errorI = 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;
const pt: SampledPoint = { x, y, z, error };
const pt: SampledPoint = { x, y, z };
if (errorI >= 0) {
const error = parseFloat(parts[errorI]);
if (Number.isFinite(error)) pt.error = error;
}
if (ri >= 0 && gi >= 0 && bi >= 0 && parts[ri] !== undefined) {
pt.r = parseFloat(parts[ri]);
pt.g = parseFloat(parts[gi]);