Реструктуризация проекта и генератор синтетических датасетов эхолота.

Перенесены backend/frontend/desktop/engine, добавлены вкладки конструктора сцен и генератора датасета с параметрами лучей и длины сетки рельефа, обновлены API и Docker-сборка.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-17 12:25:00 +03:00
co-authored by Cursor
parent 18a58f2e85
commit 4f253b860f
134 changed files with 5263 additions and 863 deletions
+457
View File
@@ -0,0 +1,457 @@
.pragma library
function inferParamType(valueText) {
var v = (valueText === undefined || valueText === null) ? "" : String(valueText).trim()
if (v === "true" || v === "false")
return "bool"
if (/^-?\d+$/.test(v))
return "int"
if (/^-?(?:\d+\.\d*|\d*\.\d+)$/.test(v))
return "float"
return "string"
}
function parseDefaults(defaultsText) {
var out = []
if (!defaultsText)
return out
var chunks = String(defaultsText).split(",")
for (var i = 0; i < chunks.length; ++i) {
var chunk = chunks[i].trim()
if (!chunk)
continue
var eq = chunk.indexOf("=")
var key = eq >= 0 ? chunk.slice(0, eq).trim() : chunk
var value = eq >= 0 ? chunk.slice(eq + 1).trim() : ""
out.push({ key: key, value: value, kind: inferParamType(value) })
}
return out
}
function serializeParams(items) {
var parts = []
for (var i = 0; i < items.length; ++i) {
var p = items[i]
parts.push(p.key + "=" + p.value)
}
return parts.join(",")
}
function paramDescription(key) {
if (key === "minCluster")
return "Минимальный размер кластера в точках."
if (key === "targetPoints")
return "Целевое количество точек после прореживания."
if (key === "leaf")
return "Размер вокселя для Voxel Grid."
if (key === "meanK")
return "Число соседей для статистической оценки."
if (key === "stddev")
return "Порог отклонения для удаления выбросов."
if (key === "radius")
return "Радиус поиска соседей."
if (key === "minNeighbors")
return "Минимум соседей, чтобы точка считалась валидной."
if (key === "threshold")
return "Порог отклонения точки от геометрической модели."
if (key === "shadowThreshold")
return "Порог для удаления теневых точек по нормалям."
if (key === "resolution")
return "Размер ячейки 2D-сетки для фильтра GridMinimum."
if (key === "sample")
return "Количество точек, которое нужно оставить после выборки."
if (key === "axis")
return "Ось фильтрации: x, y или z."
if (key === "min" || key === "max")
return "Граница диапазона для фильтра PassThrough."
if (key === "minX" || key === "minY" || key === "minZ" || key === "maxX" || key === "maxY" || key === "maxZ")
return "Границы CropBox/CropHull по соответствующим осям."
if (key === "near" || key === "far")
return "Ближняя/дальняя граница фрустума."
if (key === "hfov" || key === "vfov")
return "Горизонтальный/вертикальный угол обзора (в градусах)."
if (key === "a" || key === "b" || key === "c" || key === "d")
return "Коэффициенты плоскости ax+by+cz+d=0."
if (key === "keepPositive")
return "Оставлять ли точки на положительной стороне плоскости."
if (key === "zMin" || key === "zMax")
return "Допустимый диапазон координаты Z для conditional-фильтра."
if (key === "nth")
return "Оставлять каждую N-ю точку."
if (key === "radiusMax")
return "Максимальный радиус точки от начала координат."
if (key === "sigmaS" || key === "sigmaR")
return "Параметры bilateral-фильтра (пространство/интенсивность)."
if (key === "sigma" || key === "kernel")
return "Параметры гауссова ядра свертки."
if (key === "iterations")
return "Число итераций уточнения."
if (key === "minHits")
return "Минимальная заполненность вокселя для прохождения фильтра."
if (key === "neighborRadiusScale")
return "Масштаб радиуса поиска соседей для fallback-реконструкции."
if (key === "runEveryNthFrame")
return "Запуск реконструкции на каждом N-м кадре."
if (key === "searchRadius")
return "Радиус поиска соседей для greedy triangulation."
if (key === "mu")
return "Коэффициент плотности соседей для greedy triangulation."
if (key === "maxNearest")
return "Максимум соседей для greedy triangulation."
if (key === "maxSurfaceAngle")
return "Максимальный угол поверхности в радианах."
if (key === "poissonDepth")
return "Глубина октодерева для Poisson реконструкции."
if (key === "samplesPerNode")
return "Число выборок на узел для сглаживания Poisson."
return "Параметр этапа обработки."
}
function reconstructionTitle(id) {
if (id === "surface_fallback")
return "Fallback Surface"
if (id === "pcl_greedy_triangulation")
return "PCL Greedy Triangulation"
if (id === "pcl_poisson_reconstruction")
return "PCL Poisson Reconstruction"
return id
}
function phaseModel() {
return [
{
id: "crop",
title: "Обрезка",
hint: "Ограничение области интереса и удаление лишних фрагментов.",
accent: "#88d1ff",
filterBg: "#263e55",
filterBorder: "#4b7598"
},
{
id: "nan_preclean",
title: "NaN (предочистка)",
hint: "Удаление NaN сразу после загрузки/обрезки, иначе статистические фильтры работают нестабильно.",
accent: "#8fe8ff",
filterBg: "#1f4450",
filterBorder: "#3f8394"
},
{
id: "conditions_indexes",
title: "Условия/Индексы",
hint: "Отбор точек по полям, диапазонам и индексным маскам.",
accent: "#9fd7ff",
filterBg: "#24405a",
filterBorder: "#4f7aa1"
},
{
id: "noise",
title: "Шум",
hint: "Удаление выбросов и нестабильных точек перед геометрией.",
accent: "#a4f4b9",
filterBg: "#244534",
filterBorder: "#4b8f68"
},
{
id: "morphology",
title: "Морфология",
hint: "Геометрические операции локальной структуры облака.",
accent: "#9cf5d1",
filterBg: "#1f4a3e",
filterBorder: "#4b8f7d"
},
{
id: "downsample",
title: "Прореживание",
hint: "Снижение плотности облака для скорости и устойчивости.",
accent: "#ffcb8a",
filterBg: "#4a3724",
filterBorder: "#8e6f47"
},
{
id: "smoothing",
title: "Сглаживание",
hint: "Снижение локального шума перед расчетом нормалей и реконструкцией.",
accent: "#ffd892",
filterBg: "#4e3a22",
filterBorder: "#917349"
},
{
id: "normals",
title: "Нормали",
hint: "Подготовка нормалей для продвинутой реконструкции (этап зарезервирован).",
accent: "#d2b7ff",
filterBg: "#3e3155",
filterBorder: "#6f5a95"
},
{
id: "reconstruction",
title: "Реконструкция",
hint: "Построение поверхности по подготовленному облаку точек.",
accent: "#ff9dc4",
filterBg: "#4b2f40",
filterBorder: "#8d5a75"
}
]
}
function filterDefinitions() {
return [
{
title: "Крупнейший кластер",
idValue: "keep_largest_cluster",
phaseId: "crop",
hint: "Оставляет основной объект и отбрасывает изолированные фрагменты."
},
{
title: "Remove NaN Points",
idValue: "pcl_remove_nan",
phaseId: "nan_preclean",
family: "preprocess",
hint: "Удаляет NaN/Inf после загрузки и обрезки, до статистических фильтров."
},
{
title: "Remove NaN Normals",
idValue: "pcl_remove_nan_normals",
phaseId: "nan_preclean",
family: "preprocess",
hint: "Удаляет невалидные нормали (в текущем формате — невалидную геометрию)."
},
{
title: "PassThrough",
idValue: "pcl_pass_through",
phaseId: "crop",
hint: "Фильтрует точки по диапазону выбранной оси."
},
{
title: "CropBox",
idValue: "pcl_crop_box",
phaseId: "crop",
hint: "Ограничивает облако заданным 3D-параллелепипедом."
},
{
title: "CropHull",
idValue: "pcl_crop_hull",
phaseId: "crop",
hint: "Обрезка по области интереса (в текущей версии через box-границы)."
},
{
title: "Frustum Culling",
idValue: "pcl_frustum_culling",
phaseId: "crop",
hint: "Оставляет точки в пирамиде видимости камеры."
},
{
title: "PlaneClipper3D",
idValue: "pcl_plane_clipper_3d",
phaseId: "crop",
hint: "Отсекает точки по уравнению плоскости."
},
{
title: "Conditional Removal",
idValue: "pcl_conditional_removal",
phaseId: "conditions_indexes",
hint: "Удаляет точки по логическому условию (диапазон Z)."
},
{
title: "Extract Indices",
idValue: "pcl_extract_indices",
phaseId: "conditions_indexes",
hint: "Извлекает точки по индексной маске (каждая N-я)."
},
{
title: "Functor Filter",
idValue: "pcl_functor_filter",
phaseId: "conditions_indexes",
hint: "Пользовательский предикат (радиус + проверка валидности)."
},
{
title: "ProjectInliers",
idValue: "pcl_project_inliers",
phaseId: "normals",
hint: "Проецирует точки на геометрическую модель (плоскость)."
},
{
title: "Normal Refinement",
idValue: "pcl_normal_refinement",
phaseId: "normals",
hint: "Уточняет локальную геометрию по соседям."
},
{
title: "Статистическая фильтрация",
idValue: "pcl_statistical_outlier",
phaseId: "noise",
hint: "Удаляет выбросы на основе распределения расстояний до соседей."
},
{
title: "Радиусная фильтрация",
idValue: "pcl_radius_outlier",
phaseId: "noise",
hint: "Удаляет точки с недостаточным числом соседей в заданном радиусе."
},
{
title: "Model Outlier Removal",
idValue: "pcl_model_outlier",
phaseId: "noise",
hint: "Удаляет точки, отклоняющиеся от геометрической модели."
},
{
title: "Shadow Points Removal",
idValue: "pcl_shadow_points",
phaseId: "noise",
hint: "Удаляет теневые точки на основе нормалей поверхности."
},
{
title: "Approximate Voxel Grid",
idValue: "pcl_approximate_voxel_grid",
phaseId: "downsample",
hint: "Ускоренное воксельное прореживание для больших облаков."
},
{
title: "Voxel Grid Label",
idValue: "pcl_voxel_grid_label",
phaseId: "downsample",
hint: "Воксельное прореживание с поддержкой меток."
},
{
title: "Voxel Grid Covariance",
idValue: "pcl_voxel_grid_covariance",
phaseId: "downsample",
hint: "Воксельная сетка с ковариациями (для NDT-пайплайнов)."
},
{
title: "Grid Minimum",
idValue: "pcl_grid_minimum",
phaseId: "downsample",
hint: "Оставляет точку с минимальным Z в каждой ячейке."
},
{
title: "Farthest Point Sampling",
idValue: "pcl_farthest_point_sampling",
phaseId: "downsample",
hint: "Выбирает наиболее удаленные друг от друга точки."
},
{
title: "Normal Space Sampling",
idValue: "pcl_normal_space_sampling",
phaseId: "downsample",
hint: "Равномерная выборка в пространстве нормалей."
},
{
title: "Sampling Surface Normal",
idValue: "pcl_sampling_surface_normal",
phaseId: "downsample",
hint: "Выборка точек на основе нормалей поверхности."
},
{
title: "Bilateral Filter",
idValue: "pcl_bilateral_filter",
phaseId: "smoothing",
hint: "Двустороннее сглаживание с сохранением границ."
},
{
title: "Fast Bilateral Filter",
idValue: "pcl_fast_bilateral_filter",
phaseId: "smoothing",
hint: "Быстрое двустороннее сглаживание."
},
{
title: "Fast Bilateral Filter OMP",
idValue: "pcl_fast_bilateral_filter_omp",
phaseId: "smoothing",
hint: "Параллельная версия bilateral-фильтра."
},
{
title: "Convolution",
idValue: "pcl_convolution",
phaseId: "smoothing",
hint: "Свертка облака точек с ядром."
},
{
title: "Gaussian Kernel",
idValue: "pcl_gaussian_kernel",
phaseId: "smoothing",
hint: "Гауссово ядро свертки."
},
{
title: "Gaussian Kernel RGB",
idValue: "pcl_gaussian_kernel_rgb",
phaseId: "smoothing",
hint: "Гауссово ядро с RGB-ориентированной семантикой."
},
{
title: "VoxelGrid Occlusion Estimation",
idValue: "pcl_voxel_grid_occlusion",
phaseId: "morphology",
hint: "Оценка окклюзии через заполненность вокселей."
},
{
title: "Fallback Surface",
idValue: "surface_fallback",
phaseId: "reconstruction",
family: "reconstruction",
hint: "Базовая реконструкция поверхности по облаку точек."
},
{
title: "PCL Greedy Triangulation",
idValue: "pcl_greedy_triangulation",
phaseId: "reconstruction",
family: "reconstruction",
hint: "Жадная триангуляция с параметрами радиуса и углов."
},
{
title: "PCL Poisson Reconstruction",
idValue: "pcl_poisson_reconstruction",
phaseId: "reconstruction",
family: "reconstruction",
hint: "Реконструкция поверхности методом Poisson из libpcl_surface."
},
{
title: "Прореживание плотности",
idValue: "downsample_dense",
phaseId: "downsample",
hint: "Снижает число точек для ускорения пайплайна на плотных облаках."
},
{
title: "PCL Voxel Grid",
idValue: "pcl_voxel_grid",
phaseId: "downsample",
hint: "Равномерно прореживает облако с помощью воксельной сетки."
}
]
}
function filterPaletteModel() {
return filterDefinitions()
}
function filterPaletteGroupedModel() {
var phases = phaseModel()
var filters = filterDefinitions()
var grouped = []
for (var p = 0; p < phases.length; ++p) {
var phase = phases[p]
var items = []
for (var i = 0; i < filters.length; ++i) {
if (filters[i].phaseId === phase.id)
items.push(filters[i])
}
grouped.push({
phaseId: phase.id,
phaseTitle: phase.title,
phaseHint: phase.hint,
phaseAccent: phase.accent,
phaseFilterBg: phase.filterBg,
phaseFilterBorder: phase.filterBorder,
items: items
})
}
return grouped
}
function reconstructionPaletteModel() {
return [
{ title: "Fallback Surface", idValue: "surface_fallback" },
{ title: "PCL Greedy Triangulation", idValue: "pcl_greedy_triangulation" },
{ title: "PCL Poisson Reconstruction", idValue: "pcl_poisson_reconstruction" }
]
}