copper3d 3.4.9 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Renderer/baseRenderer.d.ts +3 -0
- package/dist/Renderer/baseRenderer.js +20 -0
- package/dist/Renderer/baseRenderer.js.map +1 -1
- package/dist/Renderer/copperMSceneRenderer.d.ts +3 -0
- package/dist/Renderer/copperMSceneRenderer.js +22 -0
- package/dist/Renderer/copperMSceneRenderer.js.map +1 -1
- package/dist/Renderer/copperRenderer.d.ts +0 -2
- package/dist/Renderer/copperRenderer.js +0 -5
- package/dist/Renderer/copperRenderer.js.map +1 -1
- package/dist/Scene/copperScene.d.ts +12 -0
- package/dist/Scene/copperScene.js +38 -44
- package/dist/Scene/copperScene.js.map +1 -1
- package/dist/Utils/segmentation/DrawToolCore.d.ts +3 -0
- package/dist/Utils/segmentation/DrawToolCore.js +29 -1
- package/dist/Utils/segmentation/DrawToolCore.js.map +1 -1
- package/dist/Utils/segmentation/NrrdTools.d.ts +54 -0
- package/dist/Utils/segmentation/NrrdTools.js +119 -0
- package/dist/Utils/segmentation/NrrdTools.js.map +1 -1
- package/dist/Utils/segmentation/core/index.d.ts +1 -1
- package/dist/Utils/segmentation/core/index.js +1 -1
- package/dist/Utils/segmentation/core/index.js.map +1 -1
- package/dist/Utils/segmentation/core/types.d.ts +11 -1
- package/dist/Utils/segmentation/core/types.js +30 -0
- package/dist/Utils/segmentation/core/types.js.map +1 -1
- package/dist/Utils/segmentation/eventRouter/EventRouter.d.ts +2 -0
- package/dist/Utils/segmentation/eventRouter/EventRouter.js +37 -6
- package/dist/Utils/segmentation/eventRouter/EventRouter.js.map +1 -1
- package/dist/Utils/segmentation/eventRouter/types.d.ts +3 -2
- package/dist/Utils/segmentation/tools/AiAssistTool.d.ts +146 -0
- package/dist/Utils/segmentation/tools/AiAssistTool.js +470 -0
- package/dist/Utils/segmentation/tools/AiAssistTool.js.map +1 -0
- package/dist/Utils/surfaceAnnotation/MeshGraph.d.ts +40 -0
- package/dist/Utils/surfaceAnnotation/MeshGraph.js +198 -0
- package/dist/Utils/surfaceAnnotation/MeshGraph.js.map +1 -0
- package/dist/Utils/surfaceAnnotation/SurfaceAnnotator.d.ts +103 -0
- package/dist/Utils/surfaceAnnotation/SurfaceAnnotator.js +402 -0
- package/dist/Utils/surfaceAnnotation/SurfaceAnnotator.js.map +1 -0
- package/dist/Utils/surfaceAnnotation/annotationStore.d.ts +37 -0
- package/dist/Utils/surfaceAnnotation/annotationStore.js +105 -0
- package/dist/Utils/surfaceAnnotation/annotationStore.js.map +1 -0
- package/dist/Utils/surfaceAnnotation/contourRender.d.ts +7 -0
- package/dist/Utils/surfaceAnnotation/contourRender.js +57 -0
- package/dist/Utils/surfaceAnnotation/contourRender.js.map +1 -0
- package/dist/Utils/surfaceAnnotation/geodesicContour.d.ts +19 -0
- package/dist/Utils/surfaceAnnotation/geodesicContour.js +43 -0
- package/dist/Utils/surfaceAnnotation/geodesicContour.js.map +1 -0
- package/dist/Utils/surfaceAnnotation/index.d.ts +3 -0
- package/dist/Utils/surfaceAnnotation/index.js +2 -0
- package/dist/Utils/surfaceAnnotation/index.js.map +1 -0
- package/dist/Utils/surfaceAnnotation/pointMarkers.d.ts +7 -0
- package/dist/Utils/surfaceAnnotation/pointMarkers.js +16 -0
- package/dist/Utils/surfaceAnnotation/pointMarkers.js.map +1 -0
- package/dist/Utils/surfaceAnnotation/raycastSurface.d.ts +7 -0
- package/dist/Utils/surfaceAnnotation/raycastSurface.js +27 -0
- package/dist/Utils/surfaceAnnotation/raycastSurface.js.map +1 -0
- package/dist/Utils/surfaceAnnotation/strokeContour.d.ts +19 -0
- package/dist/Utils/surfaceAnnotation/strokeContour.js +35 -0
- package/dist/Utils/surfaceAnnotation/strokeContour.js.map +1 -0
- package/dist/Utils/surfaceAnnotation/types.d.ts +40 -0
- package/dist/Utils/surfaceAnnotation/types.js +26 -0
- package/dist/Utils/surfaceAnnotation/types.js.map +1 -0
- package/dist/bundle.esm.js +3701 -201
- package/dist/bundle.umd.js +3703 -200
- package/dist/index.d.ts +7 -4
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/types/Renderer/baseRenderer.d.ts +3 -0
- package/dist/types/Renderer/copperMSceneRenderer.d.ts +3 -0
- package/dist/types/Renderer/copperRenderer.d.ts +0 -2
- package/dist/types/Scene/copperScene.d.ts +12 -0
- package/dist/types/Utils/segmentation/DrawToolCore.d.ts +3 -0
- package/dist/types/Utils/segmentation/NrrdTools.d.ts +54 -0
- package/dist/types/Utils/segmentation/core/index.d.ts +1 -1
- package/dist/types/Utils/segmentation/core/types.d.ts +11 -1
- package/dist/types/Utils/segmentation/eventRouter/EventRouter.d.ts +2 -0
- package/dist/types/Utils/segmentation/eventRouter/types.d.ts +3 -2
- package/dist/types/Utils/segmentation/tools/AiAssistTool.d.ts +146 -0
- package/dist/types/Utils/surfaceAnnotation/MeshGraph.d.ts +40 -0
- package/dist/types/Utils/surfaceAnnotation/SurfaceAnnotator.d.ts +103 -0
- package/dist/types/Utils/surfaceAnnotation/annotationStore.d.ts +37 -0
- package/dist/types/Utils/surfaceAnnotation/contourRender.d.ts +7 -0
- package/dist/types/Utils/surfaceAnnotation/geodesicContour.d.ts +19 -0
- package/dist/types/Utils/surfaceAnnotation/index.d.ts +3 -0
- package/dist/types/Utils/surfaceAnnotation/pointMarkers.d.ts +7 -0
- package/dist/types/Utils/surfaceAnnotation/raycastSurface.d.ts +7 -0
- package/dist/types/Utils/surfaceAnnotation/strokeContour.d.ts +19 -0
- package/dist/types/Utils/surfaceAnnotation/types.d.ts +40 -0
- package/dist/types/index.d.ts +7 -4
- package/package.json +1 -1
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
import { worldHitToLocalVertex } from "./types";
|
|
3
|
+
import { raycastSurface } from "./raycastSurface";
|
|
4
|
+
import { makePointMarker } from "./pointMarkers";
|
|
5
|
+
import { StrokeContour } from "./strokeContour";
|
|
6
|
+
import { makeContourLine, updateContourLine, setContourColor } from "./contourRender";
|
|
7
|
+
import { MeshGraph } from "./MeshGraph";
|
|
8
|
+
import { GeodesicContour } from "./geodesicContour";
|
|
9
|
+
import { AnnotationStore } from "./annotationStore";
|
|
10
|
+
import { mergeVertices } from "three/examples/jsm/utils/BufferGeometryUtils";
|
|
11
|
+
const LINE_W = 3;
|
|
12
|
+
const LINE_W_SEL = 6;
|
|
13
|
+
/**
|
|
14
|
+
* 表面标注主控制器(Phase 4):navigate / freehand / geodesic / point 四模式,
|
|
15
|
+
* Enter 闭合,数据交给 AnnotationStore 管理(多条带颜色标签、撤销/删除/清空、导出)。
|
|
16
|
+
* 渲染层据 store.list() 做场景对账(reconcile),撤销/删除自动加/移 three 对象。
|
|
17
|
+
*/
|
|
18
|
+
export class SurfaceAnnotator {
|
|
19
|
+
constructor(opts) {
|
|
20
|
+
var _a, _b;
|
|
21
|
+
this.mode = "navigate";
|
|
22
|
+
this.spaceHeld = false;
|
|
23
|
+
this.pointerDown = false;
|
|
24
|
+
this.store = new AnnotationStore();
|
|
25
|
+
this.managed = new Set();
|
|
26
|
+
this.seq = 0;
|
|
27
|
+
this.selectedId = null;
|
|
28
|
+
/** 窗口尺寸变化时更新所有 fat line 的像素分辨率,否则线宽会失真。 */
|
|
29
|
+
this.onResize = () => {
|
|
30
|
+
const w = this.o.container.clientWidth;
|
|
31
|
+
const h = this.o.container.clientHeight;
|
|
32
|
+
for (const a of this.store.list()) {
|
|
33
|
+
if (a.type === "contour" && a.object3D) {
|
|
34
|
+
const mat = a.object3D.material;
|
|
35
|
+
mat.resolution.set(w, h);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (this.activeLine)
|
|
39
|
+
(this.activeLine.material.resolution.set(w, h));
|
|
40
|
+
if (this.activeGeoLine)
|
|
41
|
+
(this.activeGeoLine.material.resolution.set(w, h));
|
|
42
|
+
};
|
|
43
|
+
this.onPointerDown = (e) => {
|
|
44
|
+
if (this.spaceHeld)
|
|
45
|
+
return;
|
|
46
|
+
if (e.button !== 0)
|
|
47
|
+
return; // 仅左键
|
|
48
|
+
if (!this.insideContainer(e))
|
|
49
|
+
return;
|
|
50
|
+
this.pointerDown = true;
|
|
51
|
+
if (this.mode === "point") {
|
|
52
|
+
const h = this.hit(e);
|
|
53
|
+
if (!h)
|
|
54
|
+
return;
|
|
55
|
+
const v = worldHitToLocalVertex(h, this.o.mesh);
|
|
56
|
+
const marker = makePointMarker(v, this.o.mesh, this.pointColorVal, this.markerRadius);
|
|
57
|
+
this.o.scene.add(marker);
|
|
58
|
+
const ann = {
|
|
59
|
+
id: this.nextId(),
|
|
60
|
+
type: "points",
|
|
61
|
+
mode: null,
|
|
62
|
+
label: `Point ${this.seq}`,
|
|
63
|
+
color: this.pointColorVal,
|
|
64
|
+
closed: false,
|
|
65
|
+
vertices: [v],
|
|
66
|
+
object3D: marker,
|
|
67
|
+
};
|
|
68
|
+
this.store.add(ann);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (this.mode === "freehand") {
|
|
72
|
+
this.activeStroke = new StrokeContour(this.minGap, this.o.mesh);
|
|
73
|
+
this.activeStroke.begin();
|
|
74
|
+
const h = this.hit(e);
|
|
75
|
+
if (h)
|
|
76
|
+
this.activeStroke.addSample(h);
|
|
77
|
+
this.activeLine = makeContourLine(this.activeStroke.vertices, this.freehandColor, false, this.o.container, this.epsilon, this.o.mesh);
|
|
78
|
+
this.o.scene.add(this.activeLine);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (this.mode === "geodesic") {
|
|
82
|
+
const h = this.hit(e);
|
|
83
|
+
if (!h)
|
|
84
|
+
return;
|
|
85
|
+
if (!this.activeGeo) {
|
|
86
|
+
this.activeGeo = new GeodesicContour(this.graph, this.o.mesh);
|
|
87
|
+
}
|
|
88
|
+
const local = this.o.mesh.worldToLocal(h.point.clone());
|
|
89
|
+
this.activeGeo.addAnchor(local);
|
|
90
|
+
const verts = this.activeGeo.buildVertices(false);
|
|
91
|
+
if (!this.activeGeoLine) {
|
|
92
|
+
this.activeGeoLine = makeContourLine(verts, this.geodesicColor, false, this.o.container, this.epsilon, this.o.mesh);
|
|
93
|
+
this.o.scene.add(this.activeGeoLine);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
updateContourLine(this.activeGeoLine, verts, false, this.epsilon, this.o.mesh);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
this.onPointerMove = (e) => {
|
|
101
|
+
if (this.spaceHeld)
|
|
102
|
+
return;
|
|
103
|
+
if (this.mode === "freehand" &&
|
|
104
|
+
this.pointerDown &&
|
|
105
|
+
this.activeStroke &&
|
|
106
|
+
this.activeLine) {
|
|
107
|
+
const h = this.hit(e);
|
|
108
|
+
if (!h)
|
|
109
|
+
return;
|
|
110
|
+
this.activeStroke.addSample(h);
|
|
111
|
+
updateContourLine(this.activeLine, this.activeStroke.vertices, false, this.epsilon, this.o.mesh);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
this.onPointerUp = () => {
|
|
115
|
+
if (!this.pointerDown)
|
|
116
|
+
return;
|
|
117
|
+
this.pointerDown = false;
|
|
118
|
+
if (this.activeStroke && this.activeLine) {
|
|
119
|
+
const verts = this.activeStroke.end();
|
|
120
|
+
if (verts.length >= 2) {
|
|
121
|
+
const ann = {
|
|
122
|
+
id: this.nextId(),
|
|
123
|
+
type: "contour",
|
|
124
|
+
mode: "freehand",
|
|
125
|
+
label: `Contour ${this.seq}`,
|
|
126
|
+
color: this.freehandColor,
|
|
127
|
+
closed: false,
|
|
128
|
+
vertices: verts,
|
|
129
|
+
object3D: this.activeLine,
|
|
130
|
+
};
|
|
131
|
+
this.store.add(ann);
|
|
132
|
+
this.lastFreehand = ann;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
this.o.scene.remove(this.activeLine);
|
|
136
|
+
}
|
|
137
|
+
this.activeStroke = undefined;
|
|
138
|
+
this.activeLine = undefined;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
this.onKeyDown = (e) => {
|
|
142
|
+
if (this.isTypingTarget(e))
|
|
143
|
+
return;
|
|
144
|
+
if (e.code === "Space") {
|
|
145
|
+
this.spaceHeld = true;
|
|
146
|
+
this.applyCameraGating();
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (e.key === "Escape") {
|
|
150
|
+
this.setMode("navigate");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if ((e.ctrlKey || e.metaKey) && (e.key === "z" || e.key === "Z")) {
|
|
154
|
+
e.preventDefault();
|
|
155
|
+
this.undo();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (e.key === "Delete" || e.key === "Backspace") {
|
|
159
|
+
if (this.selectedId)
|
|
160
|
+
this.deleteAnnotation(this.selectedId);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (e.key === "Enter") {
|
|
164
|
+
// 测地线进行中 → 结束并闭合;否则闭合最近一条自由手绘线。
|
|
165
|
+
if (this.activeGeo)
|
|
166
|
+
this.finishGeodesic();
|
|
167
|
+
else
|
|
168
|
+
this.closeLastContour();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (e.key === "1")
|
|
172
|
+
this.setMode("navigate");
|
|
173
|
+
if (e.key === "2")
|
|
174
|
+
this.setMode("freehand");
|
|
175
|
+
if (e.key === "3")
|
|
176
|
+
this.setMode("geodesic");
|
|
177
|
+
if (e.key === "4")
|
|
178
|
+
this.setMode("point");
|
|
179
|
+
};
|
|
180
|
+
this.onKeyUp = (e) => {
|
|
181
|
+
if (e.code === "Space") {
|
|
182
|
+
this.spaceHeld = false;
|
|
183
|
+
this.applyCameraGating();
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
this.o = opts;
|
|
187
|
+
const meshGeo = opts.mesh.geometry;
|
|
188
|
+
if (!meshGeo.getAttribute("normal"))
|
|
189
|
+
meshGeo.computeVertexNormals(); // 渲染需要法线
|
|
190
|
+
meshGeo.computeBoundingBox();
|
|
191
|
+
const diag = (_a = opts.bboxDiagonal) !== null && _a !== void 0 ? _a : meshGeo.boundingBox.getSize(new THREE.Vector3()).length();
|
|
192
|
+
this.markerRadius = (_b = opts.markerRadius) !== null && _b !== void 0 ? _b : diag * 0.006;
|
|
193
|
+
this.epsilon = diag * 0.002;
|
|
194
|
+
this.minGap = diag * 0.004;
|
|
195
|
+
// 测地线连通性:单独焊接一份"仅位置"的几何给 MeshGraph 用——
|
|
196
|
+
// 不动被渲染的 mesh(保留其法线/UV/纹理)。仅位置可保证同表面位置的顶点
|
|
197
|
+
// 被 mergeVertices 合并(否则逐面法线/UV 会阻止合并,图断裂 → 闭合穿模)。
|
|
198
|
+
const posOnly = new THREE.BufferGeometry();
|
|
199
|
+
posOnly.setAttribute("position", meshGeo.getAttribute("position").clone());
|
|
200
|
+
const graphGeo = mergeVertices(posOnly);
|
|
201
|
+
graphGeo.computeVertexNormals();
|
|
202
|
+
this.graph = new MeshGraph(graphGeo);
|
|
203
|
+
this.store.subscribe(() => this.reconcile());
|
|
204
|
+
// 监听挂到 window 的捕获阶段(capture=true):在 copper 的 TrackballControls
|
|
205
|
+
// 之前拿到每一个指针事件,避免它的 setPointerCapture / 事件路由导致拖拽中途丢 move。
|
|
206
|
+
window.addEventListener("pointerdown", this.onPointerDown, true);
|
|
207
|
+
window.addEventListener("pointermove", this.onPointerMove, true);
|
|
208
|
+
window.addEventListener("pointerup", this.onPointerUp, true);
|
|
209
|
+
window.addEventListener("keydown", this.onKeyDown);
|
|
210
|
+
window.addEventListener("keyup", this.onKeyUp);
|
|
211
|
+
window.addEventListener("resize", this.onResize);
|
|
212
|
+
this.applyCameraGating();
|
|
213
|
+
}
|
|
214
|
+
get freehandColor() {
|
|
215
|
+
var _a;
|
|
216
|
+
return (_a = this.o.freehandColor) !== null && _a !== void 0 ? _a : "#e5006e";
|
|
217
|
+
}
|
|
218
|
+
get geodesicColor() {
|
|
219
|
+
var _a;
|
|
220
|
+
return (_a = this.o.geodesicColor) !== null && _a !== void 0 ? _a : "#ffa24e";
|
|
221
|
+
}
|
|
222
|
+
get pointColorVal() {
|
|
223
|
+
var _a;
|
|
224
|
+
return (_a = this.o.pointColor) !== null && _a !== void 0 ? _a : "#ffd166";
|
|
225
|
+
}
|
|
226
|
+
// ---- 对外 API(供 Vue 调用) ----
|
|
227
|
+
getMode() {
|
|
228
|
+
return this.mode;
|
|
229
|
+
}
|
|
230
|
+
setMode(m) {
|
|
231
|
+
var _a, _b;
|
|
232
|
+
this.mode = m;
|
|
233
|
+
this.applyCameraGating();
|
|
234
|
+
(_b = (_a = this.o).onModeChange) === null || _b === void 0 ? void 0 : _b.call(_a, m);
|
|
235
|
+
}
|
|
236
|
+
getStore() {
|
|
237
|
+
return this.store;
|
|
238
|
+
}
|
|
239
|
+
/** 当前标注列表快照。 */
|
|
240
|
+
getAnnotations() {
|
|
241
|
+
return this.store.list();
|
|
242
|
+
}
|
|
243
|
+
undo() {
|
|
244
|
+
this.store.undo();
|
|
245
|
+
}
|
|
246
|
+
clearAll() {
|
|
247
|
+
const removed = this.store.clear();
|
|
248
|
+
removed.forEach((a) => {
|
|
249
|
+
if (a.object3D) {
|
|
250
|
+
this.o.scene.remove(a.object3D);
|
|
251
|
+
this.disposeObject(a.object3D);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
this.managed.clear();
|
|
255
|
+
this.selectedId = null;
|
|
256
|
+
}
|
|
257
|
+
deleteAnnotation(id) {
|
|
258
|
+
if (this.selectedId === id)
|
|
259
|
+
this.selectedId = null;
|
|
260
|
+
this.store.remove(id);
|
|
261
|
+
}
|
|
262
|
+
selectAnnotation(id) {
|
|
263
|
+
this.selectedId = id;
|
|
264
|
+
this.applySelection();
|
|
265
|
+
}
|
|
266
|
+
/** 颜色变更后重画对应 three 对象。 */
|
|
267
|
+
refreshAnnotation(id) {
|
|
268
|
+
const a = this.store.get(id);
|
|
269
|
+
if (!a || !a.object3D)
|
|
270
|
+
return;
|
|
271
|
+
if (a.type === "contour") {
|
|
272
|
+
setContourColor(a.object3D, a.color);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
const m = a.object3D;
|
|
276
|
+
m.material.color.set(a.color);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
exportJSON(modelName, opts) {
|
|
280
|
+
return this.store.toJSON(modelName, this.o.mesh, opts);
|
|
281
|
+
}
|
|
282
|
+
// ---- 内部 ----
|
|
283
|
+
applyCameraGating() {
|
|
284
|
+
// 按住 Space 临时旋转优先;否则仅 navigate 模式开相机。
|
|
285
|
+
this.o.controls.enabled = this.spaceHeld || this.mode === "navigate";
|
|
286
|
+
}
|
|
287
|
+
/** 据 store.list() 对账场景:补齐缺失对象、移除已删对象(不 dispose,留给撤销恢复)。 */
|
|
288
|
+
reconcile() {
|
|
289
|
+
var _a, _b;
|
|
290
|
+
const present = new Set();
|
|
291
|
+
for (const a of this.store.list())
|
|
292
|
+
if (a.object3D)
|
|
293
|
+
present.add(a.object3D);
|
|
294
|
+
for (const o of this.managed) {
|
|
295
|
+
if (!present.has(o))
|
|
296
|
+
this.o.scene.remove(o);
|
|
297
|
+
}
|
|
298
|
+
for (const o of present) {
|
|
299
|
+
if (!this.managed.has(o))
|
|
300
|
+
this.o.scene.add(o);
|
|
301
|
+
}
|
|
302
|
+
this.managed = present;
|
|
303
|
+
this.applySelection();
|
|
304
|
+
(_b = (_a = this.o).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.store.list());
|
|
305
|
+
}
|
|
306
|
+
applySelection() {
|
|
307
|
+
for (const a of this.store.list()) {
|
|
308
|
+
if (!a.object3D)
|
|
309
|
+
continue;
|
|
310
|
+
const sel = a.id === this.selectedId;
|
|
311
|
+
if (a.type === "contour") {
|
|
312
|
+
const mat = a.object3D.material;
|
|
313
|
+
mat.linewidth = sel ? LINE_W_SEL : LINE_W;
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
a.object3D.scale.setScalar(sel ? 1.6 : 1);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
disposeObject(o) {
|
|
321
|
+
var _a, _b, _c;
|
|
322
|
+
const any = o;
|
|
323
|
+
(_b = (_a = any.geometry) === null || _a === void 0 ? void 0 : _a.dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
324
|
+
const mat = any.material;
|
|
325
|
+
if (Array.isArray(mat))
|
|
326
|
+
mat.forEach((m) => m.dispose());
|
|
327
|
+
else
|
|
328
|
+
(_c = mat === null || mat === void 0 ? void 0 : mat.dispose) === null || _c === void 0 ? void 0 : _c.call(mat);
|
|
329
|
+
}
|
|
330
|
+
nextId() {
|
|
331
|
+
return "a" + ++this.seq;
|
|
332
|
+
}
|
|
333
|
+
hit(e) {
|
|
334
|
+
return raycastSurface(this.o.camera, this.o.container, this.o.mesh, e.clientX, e.clientY);
|
|
335
|
+
}
|
|
336
|
+
/** 事件目标是否落在标注容器内(排除面板/页面其它区域的点击)。 */
|
|
337
|
+
insideContainer(e) {
|
|
338
|
+
const t = e.target;
|
|
339
|
+
return !!t && this.o.container.contains(t);
|
|
340
|
+
}
|
|
341
|
+
closeLastContour() {
|
|
342
|
+
const last = this.lastFreehand;
|
|
343
|
+
if (!last || last.closed || last.vertices.length < 3 || !last.object3D)
|
|
344
|
+
return;
|
|
345
|
+
// 用测地线沿表面把末点连回首点,避免直线弦从模型内部"抄近路"被遮挡。
|
|
346
|
+
const tail = last.vertices[last.vertices.length - 1];
|
|
347
|
+
const head = last.vertices[0];
|
|
348
|
+
const closing = this.surfacePathBetween(tail, head);
|
|
349
|
+
last.vertices = last.vertices.concat(closing);
|
|
350
|
+
last.closed = true;
|
|
351
|
+
updateContourLine(last.object3D, last.vertices, true, this.epsilon, this.o.mesh);
|
|
352
|
+
}
|
|
353
|
+
/** 沿网格表面求 a→b 的测地路径(local 顶点),去掉与 a 重合的首点。a/b 已是 local。 */
|
|
354
|
+
surfacePathBetween(a, b) {
|
|
355
|
+
const va = this.graph.nearestVertex(new THREE.Vector3(a.x, a.y, a.z));
|
|
356
|
+
const vb = this.graph.nearestVertex(new THREE.Vector3(b.x, b.y, b.z));
|
|
357
|
+
const path = this.graph.shortestPath(va, vb);
|
|
358
|
+
return path.slice(1).map((i) => this.graph.vertexLocal(i));
|
|
359
|
+
}
|
|
360
|
+
/** 结束当前测地线:闭合成环并落定为一条 contour。 */
|
|
361
|
+
finishGeodesic() {
|
|
362
|
+
if (!this.activeGeo || !this.activeGeoLine)
|
|
363
|
+
return;
|
|
364
|
+
const closed = this.activeGeo.anchorCount > 2;
|
|
365
|
+
const verts = this.activeGeo.buildVertices(closed);
|
|
366
|
+
if (verts.length >= 2) {
|
|
367
|
+
updateContourLine(this.activeGeoLine, verts, closed, this.epsilon, this.o.mesh);
|
|
368
|
+
const ann = {
|
|
369
|
+
id: this.nextId(),
|
|
370
|
+
type: "contour",
|
|
371
|
+
mode: "geodesic",
|
|
372
|
+
label: `Contour ${this.seq}`,
|
|
373
|
+
color: this.geodesicColor,
|
|
374
|
+
closed,
|
|
375
|
+
vertices: verts,
|
|
376
|
+
object3D: this.activeGeoLine,
|
|
377
|
+
};
|
|
378
|
+
this.store.add(ann);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
this.o.scene.remove(this.activeGeoLine);
|
|
382
|
+
}
|
|
383
|
+
this.activeGeo = undefined;
|
|
384
|
+
this.activeGeoLine = undefined;
|
|
385
|
+
}
|
|
386
|
+
isTypingTarget(e) {
|
|
387
|
+
const t = e.target;
|
|
388
|
+
if (!t)
|
|
389
|
+
return false;
|
|
390
|
+
const tag = t.tagName;
|
|
391
|
+
return tag === "INPUT" || tag === "TEXTAREA" || t.isContentEditable;
|
|
392
|
+
}
|
|
393
|
+
dispose() {
|
|
394
|
+
window.removeEventListener("pointerdown", this.onPointerDown, true);
|
|
395
|
+
window.removeEventListener("pointermove", this.onPointerMove, true);
|
|
396
|
+
window.removeEventListener("pointerup", this.onPointerUp, true);
|
|
397
|
+
window.removeEventListener("keydown", this.onKeyDown);
|
|
398
|
+
window.removeEventListener("keyup", this.onKeyUp);
|
|
399
|
+
window.removeEventListener("resize", this.onResize);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
//# sourceMappingURL=SurfaceAnnotator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SurfaceAnnotator.js","sourceRoot":"","sources":["../../../src/Utils/surfaceAnnotation/SurfaceAnnotator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
import type { Annotation, ExportOptions } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* 标注数据模型 + 撤销栈 + 导出。纯数据,无 three / DOM 依赖。
|
|
5
|
+
* 撤销只记录 add / remove 两类原子操作(满足"撤销最近添加 / 恢复删除")。
|
|
6
|
+
* 通过 subscribe 通知 UI 与渲染层(后者据 list() 做场景对账)。
|
|
7
|
+
*/
|
|
8
|
+
export declare class AnnotationStore {
|
|
9
|
+
private items;
|
|
10
|
+
private undoStack;
|
|
11
|
+
private subs;
|
|
12
|
+
private notify;
|
|
13
|
+
subscribe(cb: () => void): () => void;
|
|
14
|
+
add(a: Annotation): void;
|
|
15
|
+
remove(id: string): Annotation | undefined;
|
|
16
|
+
undo(): void;
|
|
17
|
+
/** 清空,返回被清掉的项(供渲染层 dispose three 对象)。 */
|
|
18
|
+
clear(): Annotation[];
|
|
19
|
+
list(): Annotation[];
|
|
20
|
+
get(id: string): Annotation | undefined;
|
|
21
|
+
setLabel(id: string, label: string): void;
|
|
22
|
+
setColor(id: string, color: string): void;
|
|
23
|
+
toJSON(modelName: string, mesh: THREE.Mesh, opts?: ExportOptions): {
|
|
24
|
+
model: string;
|
|
25
|
+
exportedAt: string;
|
|
26
|
+
space: "local" | "world";
|
|
27
|
+
annotations: {
|
|
28
|
+
id: string;
|
|
29
|
+
type: "contour" | "points";
|
|
30
|
+
mode: "freehand" | "geodesic" | null;
|
|
31
|
+
label: string;
|
|
32
|
+
color: string;
|
|
33
|
+
closed: boolean;
|
|
34
|
+
points: number[][];
|
|
35
|
+
}[];
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
/**
|
|
3
|
+
* 标注数据模型 + 撤销栈 + 导出。纯数据,无 three / DOM 依赖。
|
|
4
|
+
* 撤销只记录 add / remove 两类原子操作(满足"撤销最近添加 / 恢复删除")。
|
|
5
|
+
* 通过 subscribe 通知 UI 与渲染层(后者据 list() 做场景对账)。
|
|
6
|
+
*/
|
|
7
|
+
export class AnnotationStore {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.items = [];
|
|
10
|
+
this.undoStack = [];
|
|
11
|
+
this.subs = new Set();
|
|
12
|
+
}
|
|
13
|
+
notify() {
|
|
14
|
+
this.subs.forEach((f) => f());
|
|
15
|
+
}
|
|
16
|
+
subscribe(cb) {
|
|
17
|
+
this.subs.add(cb);
|
|
18
|
+
return () => this.subs.delete(cb);
|
|
19
|
+
}
|
|
20
|
+
add(a) {
|
|
21
|
+
this.items.push(a);
|
|
22
|
+
this.undoStack.push({ kind: "add", ann: a });
|
|
23
|
+
this.notify();
|
|
24
|
+
}
|
|
25
|
+
remove(id) {
|
|
26
|
+
const i = this.items.findIndex((x) => x.id === id);
|
|
27
|
+
if (i < 0)
|
|
28
|
+
return undefined;
|
|
29
|
+
const [ann] = this.items.splice(i, 1);
|
|
30
|
+
this.undoStack.push({ kind: "remove", ann });
|
|
31
|
+
this.notify();
|
|
32
|
+
return ann;
|
|
33
|
+
}
|
|
34
|
+
undo() {
|
|
35
|
+
const op = this.undoStack.pop();
|
|
36
|
+
if (!op)
|
|
37
|
+
return;
|
|
38
|
+
if (op.kind === "add") {
|
|
39
|
+
const i = this.items.findIndex((x) => x.id === op.ann.id);
|
|
40
|
+
if (i >= 0)
|
|
41
|
+
this.items.splice(i, 1);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.items.push(op.ann);
|
|
45
|
+
}
|
|
46
|
+
this.notify();
|
|
47
|
+
}
|
|
48
|
+
/** 清空,返回被清掉的项(供渲染层 dispose three 对象)。 */
|
|
49
|
+
clear() {
|
|
50
|
+
const old = this.items;
|
|
51
|
+
this.items = [];
|
|
52
|
+
this.undoStack = [];
|
|
53
|
+
this.notify();
|
|
54
|
+
return old;
|
|
55
|
+
}
|
|
56
|
+
list() {
|
|
57
|
+
return this.items;
|
|
58
|
+
}
|
|
59
|
+
get(id) {
|
|
60
|
+
return this.items.find((x) => x.id === id);
|
|
61
|
+
}
|
|
62
|
+
setLabel(id, label) {
|
|
63
|
+
const a = this.get(id);
|
|
64
|
+
if (a) {
|
|
65
|
+
a.label = label;
|
|
66
|
+
this.notify();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
setColor(id, color) {
|
|
70
|
+
const a = this.get(id);
|
|
71
|
+
if (a) {
|
|
72
|
+
a.color = color;
|
|
73
|
+
this.notify();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
toJSON(modelName, mesh, opts = {}) {
|
|
77
|
+
var _a;
|
|
78
|
+
const space = (_a = opts.space) !== null && _a !== void 0 ? _a : "local";
|
|
79
|
+
const toPt = (v) => {
|
|
80
|
+
let x = v.x, y = v.y, z = v.z;
|
|
81
|
+
if (space === "world") {
|
|
82
|
+
const p = new THREE.Vector3(v.x, v.y, v.z).applyMatrix4(mesh.matrixWorld);
|
|
83
|
+
x = p.x;
|
|
84
|
+
y = p.y;
|
|
85
|
+
z = p.z;
|
|
86
|
+
}
|
|
87
|
+
return opts.includeNormals ? [x, y, z, v.nx, v.ny, v.nz] : [x, y, z];
|
|
88
|
+
};
|
|
89
|
+
return {
|
|
90
|
+
model: modelName,
|
|
91
|
+
exportedAt: new Date().toISOString(),
|
|
92
|
+
space,
|
|
93
|
+
annotations: this.items.map((a) => ({
|
|
94
|
+
id: a.id,
|
|
95
|
+
type: a.type,
|
|
96
|
+
mode: a.mode,
|
|
97
|
+
label: a.label,
|
|
98
|
+
color: a.color,
|
|
99
|
+
closed: a.closed,
|
|
100
|
+
points: a.vertices.map(toPt),
|
|
101
|
+
})),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=annotationStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotationStore.js","sourceRoot":"","sources":["../../../src/Utils/surfaceAnnotation/annotationStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
import { Line2 } from "three/examples/jsm/lines/Line2";
|
|
3
|
+
import type { AnnotationVertex } from "./types";
|
|
4
|
+
export declare function makeContourLine(verts: AnnotationVertex[], color: string, closed: boolean, container: HTMLElement, epsilon: number, mesh: THREE.Mesh): Line2;
|
|
5
|
+
export declare function updateContourLine(line: Line2, verts: AnnotationVertex[], closed: boolean, epsilon: number, mesh: THREE.Mesh): void;
|
|
6
|
+
/** 改变已有 contour 线的颜色。 */
|
|
7
|
+
export declare function setContourColor(line: Line2, color: string): void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
import { Line2 } from "three/examples/jsm/lines/Line2";
|
|
3
|
+
import { LineGeometry } from "three/examples/jsm/lines/LineGeometry";
|
|
4
|
+
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial";
|
|
5
|
+
import { localVertexToWorld } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* 把标注顶点(local)序列展平成 Line2 需要的 world [x,y,z, ...]。
|
|
8
|
+
* 每个点 local→world,再沿 world 法线外移 epsilon,避免与模型表面 z-fighting。
|
|
9
|
+
* closed 时把首点追加到末尾形成环。
|
|
10
|
+
*/
|
|
11
|
+
function flatten(verts, closed, epsilon, mesh) {
|
|
12
|
+
const pts = [];
|
|
13
|
+
const push = (v) => {
|
|
14
|
+
const { p, n } = localVertexToWorld(v, mesh);
|
|
15
|
+
pts.push(p.x + n.x * epsilon, p.y + n.y * epsilon, p.z + n.z * epsilon);
|
|
16
|
+
};
|
|
17
|
+
verts.forEach(push);
|
|
18
|
+
if (closed && verts.length > 1)
|
|
19
|
+
push(verts[0]);
|
|
20
|
+
return pts;
|
|
21
|
+
}
|
|
22
|
+
export function makeContourLine(verts, color, closed, container, epsilon, mesh) {
|
|
23
|
+
const geo = new LineGeometry();
|
|
24
|
+
const pos = flatten(verts, closed, epsilon, mesh);
|
|
25
|
+
// Line2 至少需要 2 个点;不足时给一个退化占位,后续 update 会补上。
|
|
26
|
+
geo.setPositions(pos.length >= 6 ? pos : [0, 0, 0, 0, 0, 0]);
|
|
27
|
+
const mat = new LineMaterial({
|
|
28
|
+
color: new THREE.Color(color).getHex(),
|
|
29
|
+
linewidth: 3, // 像素宽(需 resolution 配合)
|
|
30
|
+
});
|
|
31
|
+
mat.resolution.set(container.clientWidth, container.clientHeight);
|
|
32
|
+
const line = new Line2(geo, mat);
|
|
33
|
+
line.computeLineDistances();
|
|
34
|
+
line.renderOrder = 998;
|
|
35
|
+
// 关键:Line2 的包围球停留在初始点,拖拽生长后真实几何会被错误剔除。
|
|
36
|
+
// 关闭视锥剔除,保证线始终渲染。
|
|
37
|
+
line.frustumCulled = false;
|
|
38
|
+
return line;
|
|
39
|
+
}
|
|
40
|
+
export function updateContourLine(line, verts, closed, epsilon, mesh) {
|
|
41
|
+
const pos = flatten(verts, closed, epsilon, mesh);
|
|
42
|
+
if (pos.length < 6)
|
|
43
|
+
return; // Line2 需要 >=2 点
|
|
44
|
+
// 关键:Line2 在原 geometry 上 setPositions 扩容后只渲染首段(已知坑)。
|
|
45
|
+
// 改为每次重建一个新 LineGeometry 并替换,保证实例数正确、全段渲染。
|
|
46
|
+
const geo = new LineGeometry();
|
|
47
|
+
geo.setPositions(pos);
|
|
48
|
+
const old = line.geometry;
|
|
49
|
+
line.geometry = geo;
|
|
50
|
+
old.dispose();
|
|
51
|
+
line.computeLineDistances();
|
|
52
|
+
}
|
|
53
|
+
/** 改变已有 contour 线的颜色。 */
|
|
54
|
+
export function setContourColor(line, color) {
|
|
55
|
+
line.material.color.set(color);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=contourRender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contourRender.js","sourceRoot":"","sources":["../../../src/Utils/surfaceAnnotation/contourRender.ts"],"names":[],"mappings":"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"}
|