feat: удаление последнего измерения и очистка всех измерений

This commit is contained in:
Maxim Dolgolyov
2026-04-14 14:05:40 +03:00
parent 74fe2c4179
commit d822b705c4
2 changed files with 65 additions and 21 deletions
+55 -21
View File
@@ -115,7 +115,8 @@ class StereoSim {
this._labelGroup = new THREE.Group();
this._sectionGroup = new THREE.Group();
this._sphereGroup = new THREE.Group();
this._measureGroup = new THREE.Group();
this._measureGroup = new THREE.Group();
this._measurePickGroup = new THREE.Group();
this._gridGroup = new THREE.Group();
this._markGroup = new THREE.Group();
this._derivedGroup = new THREE.Group();
@@ -124,6 +125,7 @@ class StereoSim {
this.scene.add(this._sectionGroup);
this.scene.add(this._sphereGroup);
this.scene.add(this._measureGroup);
this.scene.add(this._measurePickGroup);
this.scene.add(this._markGroup);
this.scene.add(this._derivedGroup);
this.scene.add(this._labelGroup);
@@ -310,10 +312,52 @@ class StereoSim {
this._pointMode = false;
this._angleMode = null;
this._measurePicks = [];
if (!on) { this._clearGroup(this._measureGroup); this._measurements = []; }
this._clearGroup(this._measurePickGroup);
if (!on) { this._measurements = []; this._rebuildMeasureGroup(); }
this.renderer.domElement.style.cursor = on ? 'crosshair' : 'grab';
}
removeLastMeasurement() {
if (!this._measurements.length) return;
this._measurements.pop();
this._rebuildMeasureGroup();
}
clearMeasurements() {
this._measurements = [];
this._measurePicks = [];
this._rebuildMeasureGroup();
this._clearGroup(this._measurePickGroup);
}
_rebuildMeasureGroup() {
this._clearGroup(this._measureGroup);
for (const m of this._measurements) {
const g = new THREE.Group();
// spheres at endpoints
for (const pos of [m.posA, m.posB]) {
const sGeo = new THREE.SphereGeometry(0.14, 12, 12);
const sMat = new THREE.MeshBasicMaterial({ color: 0xFFD166 });
const s = new THREE.Mesh(sGeo, sMat);
s.position.copy(pos);
g.add(s);
}
// dashed line
const lineGeo = new THREE.BufferGeometry().setFromPoints([m.posA, m.posB]);
const lineMat = new THREE.LineDashedMaterial({ color: 0xFFD166, dashSize: 0.15, gapSize: 0.1, transparent: true, opacity: 0.9 });
const line = new THREE.Line(lineGeo, lineMat);
line.computeLineDistances();
g.add(line);
// label
const mid = new THREE.Vector3().addVectors(m.posA, m.posB).multiplyScalar(0.5);
const label = this._makeTextSprite(`${m.from}${m.to} = ${m.dist}`, '#FFD166', 40);
label.position.copy(mid).add(new THREE.Vector3(0, 0.3, 0));
label.scale.set(1.4, 0.5, 1);
g.add(label);
this._measureGroup.add(g);
}
}
setAngleMode(mode) {
// mode: 'edge' | 'linePlane' | 'dihedral' | null
this._angleMode = mode;
@@ -1718,34 +1762,24 @@ class StereoSim {
this._measurePicks.push(bestPick);
// Highlight picked point
// Highlight first pick in temporary group
const sGeo = new THREE.SphereGeometry(0.14, 12, 12);
const sMat = new THREE.MeshBasicMaterial({ color: 0xFFD166 });
const s = new THREE.Mesh(sGeo, sMat);
s.position.copy(bestPick.pos);
this._measureGroup.add(s);
this._measurePickGroup.add(s);
if (this._measurePicks.length === 2) {
const [a, b] = this._measurePicks;
const dist = a.pos.distanceTo(b.pos);
const mid = new THREE.Vector3().addVectors(a.pos, b.pos).multiplyScalar(0.5);
// Dashed line
const pts = [a.pos, b.pos];
const lineGeo = new THREE.BufferGeometry().setFromPoints(pts);
const lineMat = new THREE.LineDashedMaterial({ color: 0xFFD166, dashSize: 0.15, gapSize: 0.1, transparent: true, opacity: 0.9 });
const line = new THREE.Line(lineGeo, lineMat);
line.computeLineDistances();
this._measureGroup.add(line);
// Label
const label = this._makeTextSprite(`${a.label}${b.label} = ${dist.toFixed(2)}`, '#FFD166', 40);
label.position.copy(mid).add(new THREE.Vector3(0, 0.3, 0));
label.scale.set(1.4, 0.5, 1);
this._measureGroup.add(label);
this._measurements.push({ from: a.label, to: b.label, dist: Math.round(dist * 100) / 100 });
this._measurements.push({
from: a.label, to: b.label,
dist: Math.round(dist * 100) / 100,
posA: a.pos.clone(), posB: b.pos.clone(),
});
this._measurePicks = [];
this._clearGroup(this._measurePickGroup);
this._rebuildMeasureGroup();
}
}
+10
View File
@@ -3670,6 +3670,8 @@
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:4px">
<button class="gp-btn" id="stereo-unfold-btn" onclick="stereoUnfold(this)">Развёртка</button>
<button class="gp-btn" id="stereo-measure-btn" onclick="stereoMeasure(this)">Измерение</button>
<button class="gp-btn" onclick="stereoMeasureUndo()">Удалить посл.</button>
<button class="gp-btn" onclick="stereoMeasureClear()">Очистить</button>
</div>
<div class="gp-section-title" style="margin-top:8px">Углы и расстояния</div>
@@ -8223,6 +8225,14 @@
if (stereoSim) stereoSim.toggleMeasure(on);
}
function stereoMeasureUndo() {
if (stereoSim) stereoSim.removeLastMeasurement();
}
function stereoMeasureClear() {
if (stereoSim) stereoSim.clearMeasurements();
}
function stereoToggleHeight(btn) {
const on = !btn.classList.contains('active');
btn.classList.toggle('active', on);