feat: удаление последнего измерения и очистка всех измерений
This commit is contained in:
+55
-21
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user