@@ -294,6 +294,7 @@ export const api = {
|
||||
seed = 42,
|
||||
outputDir = "sonar_dataset",
|
||||
objectScale = 1,
|
||||
objectScaleIsMax = false,
|
||||
beamCount = 45,
|
||||
lengthCount = 45,
|
||||
modelFile,
|
||||
@@ -306,6 +307,7 @@ export const api = {
|
||||
formData.append("seed", String(seed));
|
||||
formData.append("outputDir", outputDir || "sonar_dataset");
|
||||
formData.append("objectScale", String(objectScale ?? 1));
|
||||
formData.append("objectScaleIsMax", objectScaleIsMax ? "true" : "false");
|
||||
formData.append("beamCount", String(beamCount ?? 45));
|
||||
formData.append("lengthCount", String(lengthCount ?? 45));
|
||||
formData.append("model", modelFile, modelFile.name || "model.obj");
|
||||
|
||||
@@ -13,6 +13,7 @@ export const useDatasetStore = defineStore("dataset", {
|
||||
modelFile: null,
|
||||
modelFileName: "",
|
||||
objectScale: 1,
|
||||
objectScaleIsMax: false,
|
||||
beamCount: 45,
|
||||
lengthCount: 45,
|
||||
lastResult: null,
|
||||
@@ -117,7 +118,7 @@ export const useDatasetStore = defineStore("dataset", {
|
||||
this.busy = true;
|
||||
this.statusText = "Генерация датасета…";
|
||||
this.pushLog(
|
||||
`Старт: count=${this.count}, seed=${this.seed}, beams=${this.beamCount}, length=${this.lengthCount}, scale=${this.objectScale}, dir=${this.outputDir}, model=${this.modelFileName}`,
|
||||
`Старт: count=${this.count}, seed=${this.seed}, beams=${this.beamCount}, length=${this.lengthCount}, scale=${this.objectScale}${this.objectScaleIsMax ? " (макс.)" : ""}, dir=${this.outputDir}, model=${this.modelFileName}`,
|
||||
);
|
||||
try {
|
||||
const result = await api.datasetGenerate({
|
||||
@@ -125,6 +126,7 @@ export const useDatasetStore = defineStore("dataset", {
|
||||
seed: Number(this.seed) || 0,
|
||||
outputDir: String(this.outputDir || "sonar_dataset"),
|
||||
objectScale: Number(this.objectScale) || 1,
|
||||
objectScaleIsMax: !!this.objectScaleIsMax,
|
||||
beamCount: Number(this.beamCount) || 45,
|
||||
lengthCount: Number(this.lengthCount) || 45,
|
||||
modelFile: this.modelFile,
|
||||
@@ -133,8 +135,11 @@ export const useDatasetStore = defineStore("dataset", {
|
||||
this.resolvedOutputDir = result?.outputDir || null;
|
||||
const s = result?.stats || {};
|
||||
this.statusText = `Готово: ${result.count} сцен → ${result.outputDir}`;
|
||||
const scaleNote = result.objectScaleIsMax
|
||||
? `scale=1…${result.objectScale ?? this.objectScale} (макс.)`
|
||||
: `scale=${result.objectScale ?? this.objectScale}`;
|
||||
this.pushLog(
|
||||
`Модель: ${result.objectName || this.modelFileName} (${result.objectVertexCount || "?"} вершин), scale=${result.objectScale ?? this.objectScale}, ширина=${result.beamCount ?? this.beamCount}, длина=${result.lengthCount ?? this.lengthCount}. class 1 = object.`,
|
||||
`Модель: ${result.objectName || this.modelFileName} (${result.objectVertexCount || "?"} вершин), ${scaleNote}, ширина=${result.beamCount ?? this.beamCount}, длина=${result.lengthCount ?? this.lengthCount}. class 1 = object.`,
|
||||
);
|
||||
this.pushLog(
|
||||
`Записано ${result.count} сцен. С объектом: ${s.withObject}, без: ${s.withoutObject}.`,
|
||||
@@ -143,8 +148,10 @@ export const useDatasetStore = defineStore("dataset", {
|
||||
`Видимость: nearly_hidden=${s.nearly_hidden || 0}, partial=${s.partial || 0}, visible=${s.visible || 0}, absent=${s.absent || 0}.`,
|
||||
);
|
||||
for (const item of result.written || []) {
|
||||
const scalePart =
|
||||
item.objectScale != null ? `, scale=${Number(item.objectScale).toFixed(3)}` : "";
|
||||
this.pushLog(
|
||||
`${item.stem}: pts=${item.pointCount}, object=${item.objectPointCount}, ${item.visibility}`,
|
||||
`${item.stem}: pts=${item.pointCount}, object=${item.objectPointCount}, ${item.visibility}${scalePart}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,17 @@ function onHighlightClassChange(event) {
|
||||
</label>
|
||||
|
||||
<label class="field">
|
||||
<span>Относительный масштаб объекта</span>
|
||||
<span class="field-label-row">
|
||||
<span>Относительный масштаб объекта</span>
|
||||
<label class="check-inline" title="Верхняя граница: для каждой сцены масштаб случайный от 1 до заданного значения">
|
||||
<input
|
||||
v-model="store.objectScaleIsMax"
|
||||
type="checkbox"
|
||||
:disabled="store.busy"
|
||||
/>
|
||||
макс.
|
||||
</label>
|
||||
</span>
|
||||
<input
|
||||
v-model.number="store.objectScale"
|
||||
type="number"
|
||||
@@ -128,7 +138,14 @@ function onHighlightClassChange(event) {
|
||||
step="0.05"
|
||||
:disabled="store.busy"
|
||||
/>
|
||||
<span class="ref-caption">1.0 = размер после нормализации mesh; >1 увеличивает объект</span>
|
||||
<span class="ref-caption">
|
||||
<template v-if="store.objectScaleIsMax">
|
||||
Верхняя граница: для каждой сцены масштаб случайно из [1 … значение] (имитация разной высоты АНПА).
|
||||
</template>
|
||||
<template v-else>
|
||||
1.0 = размер после нормализации mesh; >1 увеличивает объект
|
||||
</template>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<label class="field">
|
||||
@@ -142,7 +159,7 @@ function onHighlightClassChange(event) {
|
||||
:disabled="store.busy"
|
||||
/>
|
||||
<span class="ref-caption">
|
||||
Ширина рельефа (X): N лучей = N точек по ширине сетки дна.
|
||||
Поперечные лучи эхолота (X): N лучей = N возвратов по ширине галса.
|
||||
</span>
|
||||
</label>
|
||||
|
||||
@@ -157,7 +174,7 @@ function onHighlightClassChange(event) {
|
||||
:disabled="store.busy"
|
||||
/>
|
||||
<span class="ref-caption">
|
||||
Длина рельефа (Y): L = число точек по длине сетки дна.
|
||||
Пинги вдоль курса (Y): L возвратов по длине. Итого точек сцены: N×L (первый отклик луча).
|
||||
</span>
|
||||
</label>
|
||||
|
||||
@@ -283,12 +300,23 @@ function onHighlightClassChange(event) {
|
||||
|
||||
<style scoped>
|
||||
.dataset-layout {
|
||||
grid-template-columns: 320px minmax(0, 1fr);
|
||||
align-items: stretch;
|
||||
height: calc(100vh - 56px);
|
||||
min-height: 0;
|
||||
max-height: calc(100vh - 56px);
|
||||
overflow: hidden;
|
||||
gap: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
.dataset-sidebar {
|
||||
width: 320px;
|
||||
max-width: 100%;
|
||||
overflow: auto;
|
||||
width: auto;
|
||||
max-width: none;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
align-content: start;
|
||||
}
|
||||
.panel {
|
||||
padding: 14px 16px 20px;
|
||||
@@ -338,6 +366,27 @@ function onHighlightClassChange(event) {
|
||||
gap: 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.field-label-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
.check-inline {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--muted-text);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.check-inline input {
|
||||
width: auto;
|
||||
margin: 0;
|
||||
accent-color: var(--chain-selected-border, #6ea8ff);
|
||||
}
|
||||
.field input,
|
||||
.field select {
|
||||
padding: 6px 8px;
|
||||
@@ -424,17 +473,19 @@ function onHighlightClassChange(event) {
|
||||
font-size: 11px;
|
||||
}
|
||||
.dataset-content {
|
||||
min-height: 0;
|
||||
height: calc(100vh - 76px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 8px 12px 12px 0;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
}
|
||||
.viewer-wrap {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
min-height: 280px;
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
border: 1px solid var(--header-border);
|
||||
border-radius: var(--radius-sm, 6px);
|
||||
overflow: hidden;
|
||||
@@ -456,6 +507,7 @@ function onHighlightClassChange(event) {
|
||||
}
|
||||
.log-panel {
|
||||
flex: 0 0 140px;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -466,10 +518,23 @@ function onHighlightClassChange(event) {
|
||||
.log {
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
font-size: 11px;
|
||||
line-height: 1.35;
|
||||
white-space: pre-wrap;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.dataset-layout {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: minmax(200px, 36vh) minmax(0, 1fr);
|
||||
height: calc(100vh - 56px);
|
||||
max-height: calc(100vh - 56px);
|
||||
}
|
||||
.dataset-sidebar {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user