copper3d 3.6.6 → 3.6.8
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/Scene/baseScene.js +8 -5
- package/dist/Scene/baseScene.js.map +1 -1
- package/dist/Utils/surfaceAnnotation/MeshGraph.d.ts +4 -0
- package/dist/Utils/surfaceAnnotation/MeshGraph.js +9 -0
- package/dist/Utils/surfaceAnnotation/MeshGraph.js.map +1 -1
- package/dist/Utils/surfaceAnnotation/SurfaceAnnotator.d.ts +31 -0
- package/dist/Utils/surfaceAnnotation/SurfaceAnnotator.js +138 -12
- package/dist/Utils/surfaceAnnotation/SurfaceAnnotator.js.map +1 -1
- package/dist/Utils/surfaceAnnotation/annotationStore.d.ts +2 -0
- package/dist/Utils/surfaceAnnotation/annotationStore.js +8 -0
- package/dist/Utils/surfaceAnnotation/annotationStore.js.map +1 -1
- package/dist/Utils/surfaceAnnotation/types.d.ts +1 -0
- package/dist/Utils/surfaceAnnotation/types.js.map +1 -1
- package/dist/bundle.esm.js +167 -21
- package/dist/bundle.umd.js +167 -21
- package/dist/types/Utils/surfaceAnnotation/MeshGraph.d.ts +4 -0
- package/dist/types/Utils/surfaceAnnotation/SurfaceAnnotator.d.ts +31 -0
- package/dist/types/Utils/surfaceAnnotation/annotationStore.d.ts +2 -0
- package/dist/types/Utils/surfaceAnnotation/types.d.ts +1 -0
- package/package.json +1 -1
package/dist/bundle.umd.js
CHANGED
|
@@ -49760,8 +49760,11 @@ void main() {
|
|
|
49760
49760
|
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
|
|
49761
49761
|
};
|
|
49762
49762
|
this.renderer = renderer;
|
|
49763
|
-
|
|
49764
|
-
|
|
49763
|
+
// three r165+ removed `useLegacyLights`; lighting is always physically
|
|
49764
|
+
// correct now, which makes the same intensity ~1/PI as dim as the old
|
|
49765
|
+
// (three <=0.150) legacy default. Scale by PI to keep the prior brightness.
|
|
49766
|
+
this.ambientLight = new AmbientLight(0x606060, 0.8 * Math.PI);
|
|
49767
|
+
this.directionalLight = new DirectionalLight(0xffffff, 1.0 * Math.PI);
|
|
49765
49768
|
if (!(opt === null || opt === void 0 ? void 0 : opt.alpha)) {
|
|
49766
49769
|
this.vignette = createBackground({
|
|
49767
49770
|
aspect: this.container.clientWidth / this.container.clientHeight,
|
|
@@ -49846,7 +49849,7 @@ void main() {
|
|
|
49846
49849
|
}
|
|
49847
49850
|
addLights() {
|
|
49848
49851
|
// Hemisphere light: sky/ground for broad ambient fill
|
|
49849
|
-
const hemiLight = new HemisphereLight(0xddeeff, 0x0f0e0d, 0.6);
|
|
49852
|
+
const hemiLight = new HemisphereLight(0xddeeff, 0x0f0e0d, 0.6 * Math.PI);
|
|
49850
49853
|
hemiLight.name = "hemi_light";
|
|
49851
49854
|
this.scene.add(hemiLight);
|
|
49852
49855
|
// Main key light — front-right, slightly above
|
|
@@ -49856,12 +49859,12 @@ void main() {
|
|
|
49856
49859
|
this.camera.add(this.ambientLight);
|
|
49857
49860
|
this.camera.add(this.directionalLight);
|
|
49858
49861
|
// Fill light — opposite side to soften shadows
|
|
49859
|
-
const fillLight = new DirectionalLight(0xffffff, 0.4);
|
|
49862
|
+
const fillLight = new DirectionalLight(0xffffff, 0.4 * Math.PI);
|
|
49860
49863
|
fillLight.name = "fill_light";
|
|
49861
49864
|
fillLight.position.set(-0.5, -0.2, -0.866);
|
|
49862
49865
|
this.camera.add(fillLight);
|
|
49863
49866
|
// Top light — illuminates the top surface that key/fill lights miss
|
|
49864
|
-
const topLight = new DirectionalLight(0xffffff, 0.5);
|
|
49867
|
+
const topLight = new DirectionalLight(0xffffff, 0.5 * Math.PI);
|
|
49865
49868
|
topLight.name = "top_light";
|
|
49866
49869
|
topLight.position.set(0, 1, 0.2);
|
|
49867
49870
|
this.camera.add(topLight);
|
|
@@ -61173,6 +61176,15 @@ void main() {
|
|
|
61173
61176
|
const nm = new Matrix3().getNormalMatrix(mesh.matrixWorld);
|
|
61174
61177
|
return n.applyMatrix3(nm).normalize();
|
|
61175
61178
|
}
|
|
61179
|
+
/** Vertex local normal at index i (reads from the welded graphGeo normal attribute). */
|
|
61180
|
+
vertexNormalLocal(i) {
|
|
61181
|
+
return new Vector3(this.normals ? this.normals[i * 3] : 0, this.normals ? this.normals[i * 3 + 1] : 0, this.normals ? this.normals[i * 3 + 2] : 1);
|
|
61182
|
+
}
|
|
61183
|
+
/** Normal at the vertex nearest to localPoint (for recovering normals from imported point coordinates). */
|
|
61184
|
+
nearestNormalLocal(p) {
|
|
61185
|
+
const i = this.nearestVertex(p);
|
|
61186
|
+
return this.vertexNormalLocal(i);
|
|
61187
|
+
}
|
|
61176
61188
|
/** Vertex local coordinates + local normal (the graph geometry is already local space). */
|
|
61177
61189
|
vertexLocal(i) {
|
|
61178
61190
|
return {
|
|
@@ -61398,6 +61410,13 @@ void main() {
|
|
|
61398
61410
|
this.notify();
|
|
61399
61411
|
}
|
|
61400
61412
|
}
|
|
61413
|
+
setVisible(id, visible) {
|
|
61414
|
+
const a = this.get(id);
|
|
61415
|
+
if (a) {
|
|
61416
|
+
a.visible = visible;
|
|
61417
|
+
this.notify();
|
|
61418
|
+
}
|
|
61419
|
+
}
|
|
61401
61420
|
toJSON(modelName, mesh, opts = {}) {
|
|
61402
61421
|
var _a;
|
|
61403
61422
|
const space = (_a = opts.space) !== null && _a !== void 0 ? _a : "local";
|
|
@@ -61422,6 +61441,7 @@ void main() {
|
|
|
61422
61441
|
label: a.label,
|
|
61423
61442
|
color: a.color,
|
|
61424
61443
|
closed: a.closed,
|
|
61444
|
+
visible: a.visible,
|
|
61425
61445
|
points: a.vertices.map(toPt),
|
|
61426
61446
|
})),
|
|
61427
61447
|
};
|
|
@@ -61441,6 +61461,10 @@ void main() {
|
|
|
61441
61461
|
var _a, _b, _c;
|
|
61442
61462
|
this.mode = "navigate";
|
|
61443
61463
|
this.spaceHeld = false;
|
|
61464
|
+
this.drawLock = false;
|
|
61465
|
+
this.armed = "freehand";
|
|
61466
|
+
this.spaceDownAt = 0;
|
|
61467
|
+
this.spaceDragged = false;
|
|
61444
61468
|
this.pointerDown = false;
|
|
61445
61469
|
this.store = new AnnotationStore();
|
|
61446
61470
|
this.managed = new Set();
|
|
@@ -61467,14 +61491,18 @@ void main() {
|
|
|
61467
61491
|
(this.activeGeoLine.material.resolution.set(w, h));
|
|
61468
61492
|
};
|
|
61469
61493
|
this.onPointerDown = (e) => {
|
|
61470
|
-
if (this.spaceHeld)
|
|
61471
|
-
return;
|
|
61472
61494
|
if (e.button !== 0)
|
|
61473
61495
|
return; // left button only
|
|
61474
61496
|
if (!this.insideContainer(e))
|
|
61475
61497
|
return;
|
|
61476
61498
|
this.pointerDown = true;
|
|
61477
|
-
|
|
61499
|
+
// Only act with the armed tool when in drawing mode (drawLock or spaceHeld).
|
|
61500
|
+
// When not drawing, navigation is the default — pointer events go to camera controls.
|
|
61501
|
+
if (!this.drawing)
|
|
61502
|
+
return;
|
|
61503
|
+
// Use armed tool (not this.mode which may be "navigate")
|
|
61504
|
+
const activeTool = this.armed;
|
|
61505
|
+
if (activeTool === "point") {
|
|
61478
61506
|
const h = this.hit(e);
|
|
61479
61507
|
if (!h)
|
|
61480
61508
|
return;
|
|
@@ -61488,13 +61516,14 @@ void main() {
|
|
|
61488
61516
|
label: `Point ${this.seq}`,
|
|
61489
61517
|
color: this.pointColorVal,
|
|
61490
61518
|
closed: false,
|
|
61519
|
+
visible: true,
|
|
61491
61520
|
vertices: [v],
|
|
61492
61521
|
object3D: marker,
|
|
61493
61522
|
};
|
|
61494
61523
|
this.store.add(ann);
|
|
61495
61524
|
return;
|
|
61496
61525
|
}
|
|
61497
|
-
if (
|
|
61526
|
+
if (activeTool === "freehand") {
|
|
61498
61527
|
this.activeStroke = new StrokeContour(this.minGap, this.maxJump, this.o.mesh);
|
|
61499
61528
|
this.activeStroke.begin();
|
|
61500
61529
|
const h = this.hit(e);
|
|
@@ -61504,7 +61533,7 @@ void main() {
|
|
|
61504
61533
|
this.o.scene.add(this.activeLine);
|
|
61505
61534
|
return;
|
|
61506
61535
|
}
|
|
61507
|
-
if (
|
|
61536
|
+
if (activeTool === "geodesic") {
|
|
61508
61537
|
// First check whether an existing anchor was clicked → cancel that point (any point can be canceled).
|
|
61509
61538
|
const pick = this.pickGeoMarker(e);
|
|
61510
61539
|
if (pick >= 0 && this.activeGeo) {
|
|
@@ -61531,15 +61560,26 @@ void main() {
|
|
|
61531
61560
|
}
|
|
61532
61561
|
};
|
|
61533
61562
|
this.onPointerMove = (e) => {
|
|
61534
|
-
if (
|
|
61535
|
-
|
|
61563
|
+
// Track if user dragged while space was held (so a hold-drag is not treated as a tap).
|
|
61564
|
+
if (this.spaceHeld && this.pointerDown) {
|
|
61565
|
+
this.spaceDragged = true;
|
|
61566
|
+
}
|
|
61567
|
+
// When not drawing, navigation is default — don't interfere with camera controls.
|
|
61568
|
+
if (!this.drawing) {
|
|
61569
|
+
// In geodesic mode we can still show the hover hint when not drawing.
|
|
61570
|
+
if (this.armed === "geodesic" && !this.pointerDown) {
|
|
61571
|
+
this.setGeoHover(this.insideContainer(e) ? this.pickGeoMarker(e) : -1);
|
|
61572
|
+
}
|
|
61573
|
+
else {
|
|
61574
|
+
this.setGeoHover(-1);
|
|
61575
|
+
}
|
|
61536
61576
|
return;
|
|
61537
61577
|
}
|
|
61538
|
-
//
|
|
61539
|
-
if (this.
|
|
61578
|
+
// Drawing mode: geodesic hover hint
|
|
61579
|
+
if (this.armed === "geodesic" && !this.pointerDown) {
|
|
61540
61580
|
this.setGeoHover(this.insideContainer(e) ? this.pickGeoMarker(e) : -1);
|
|
61541
61581
|
}
|
|
61542
|
-
if (this.
|
|
61582
|
+
if (this.armed === "freehand" &&
|
|
61543
61583
|
this.pointerDown &&
|
|
61544
61584
|
this.activeStroke &&
|
|
61545
61585
|
this.activeLine) {
|
|
@@ -61564,6 +61604,7 @@ void main() {
|
|
|
61564
61604
|
label: `Contour ${this.seq}`,
|
|
61565
61605
|
color: this.freehandColor,
|
|
61566
61606
|
closed: false,
|
|
61607
|
+
visible: true,
|
|
61567
61608
|
vertices: verts,
|
|
61568
61609
|
object3D: this.activeLine,
|
|
61569
61610
|
};
|
|
@@ -61581,11 +61622,17 @@ void main() {
|
|
|
61581
61622
|
if (this.isTypingTarget(e))
|
|
61582
61623
|
return;
|
|
61583
61624
|
if (e.code === "Space") {
|
|
61625
|
+
if (!this.spaceHeld) {
|
|
61626
|
+
this.spaceDownAt = performance.now();
|
|
61627
|
+
this.spaceDragged = false;
|
|
61628
|
+
}
|
|
61584
61629
|
this.spaceHeld = true;
|
|
61585
61630
|
this.applyCameraGating();
|
|
61631
|
+
e.preventDefault();
|
|
61586
61632
|
return;
|
|
61587
61633
|
}
|
|
61588
61634
|
if (e.key === "Escape") {
|
|
61635
|
+
this.drawLock = false;
|
|
61589
61636
|
this.setMode("navigate");
|
|
61590
61637
|
return;
|
|
61591
61638
|
}
|
|
@@ -61618,7 +61665,11 @@ void main() {
|
|
|
61618
61665
|
};
|
|
61619
61666
|
this.onKeyUp = (e) => {
|
|
61620
61667
|
if (e.code === "Space") {
|
|
61668
|
+
const held = performance.now() - this.spaceDownAt;
|
|
61621
61669
|
this.spaceHeld = false;
|
|
61670
|
+
if (held <= SurfaceAnnotator.TAP_MS && !this.spaceDragged) {
|
|
61671
|
+
this.drawLock = !this.drawLock; // tap toggles lock
|
|
61672
|
+
}
|
|
61622
61673
|
this.applyCameraGating();
|
|
61623
61674
|
}
|
|
61624
61675
|
};
|
|
@@ -61674,6 +61725,10 @@ void main() {
|
|
|
61674
61725
|
if (m !== "geodesic" && this.activeGeo)
|
|
61675
61726
|
this.clearActiveGeo();
|
|
61676
61727
|
this.mode = m;
|
|
61728
|
+
// Record armed tool when choosing a drawing mode (not navigate).
|
|
61729
|
+
// Camera gating is NOT changed here — the user must use Space to enter drawing.
|
|
61730
|
+
if (m !== "navigate")
|
|
61731
|
+
this.armed = m;
|
|
61677
61732
|
this.applyCameraGating();
|
|
61678
61733
|
(_b = (_a = this.o).onModeChange) === null || _b === void 0 ? void 0 : _b.call(_a, m);
|
|
61679
61734
|
}
|
|
@@ -61736,10 +61791,92 @@ void main() {
|
|
|
61736
61791
|
exportJSON(modelName, opts) {
|
|
61737
61792
|
return this.store.toJSON(modelName, this.o.mesh, opts);
|
|
61738
61793
|
}
|
|
61794
|
+
setVisible(id, visible) {
|
|
61795
|
+
this.store.setVisible(id, visible);
|
|
61796
|
+
}
|
|
61797
|
+
/**
|
|
61798
|
+
* Rebuild annotations from an exported payload (local-space points). Normals are taken from the
|
|
61799
|
+
* point when present ([x,y,z,nx,ny,nz]); otherwise recovered from the welded graph's nearest
|
|
61800
|
+
* vertex. Each imported item becomes first-class (select/recolor/hide/delete/export).
|
|
61801
|
+
*/
|
|
61802
|
+
importAnnotations(payload) {
|
|
61803
|
+
var _a, _b, _c, _d;
|
|
61804
|
+
let count = 0;
|
|
61805
|
+
let maxImported = this.seq;
|
|
61806
|
+
for (const a of (_a = payload.annotations) !== null && _a !== void 0 ? _a : []) {
|
|
61807
|
+
const verts = a.points.map((p) => {
|
|
61808
|
+
const [x, y, z] = p;
|
|
61809
|
+
let nx = p[3], ny = p[4], nz = p[5];
|
|
61810
|
+
if (nx === undefined || ny === undefined || nz === undefined) {
|
|
61811
|
+
const nrm = this.graph.nearestNormalLocal(new Vector3(x, y, z));
|
|
61812
|
+
nx = nrm.x;
|
|
61813
|
+
ny = nrm.y;
|
|
61814
|
+
nz = nrm.z;
|
|
61815
|
+
}
|
|
61816
|
+
return { x, y, z, nx, ny, nz, faceIndex: 0 };
|
|
61817
|
+
});
|
|
61818
|
+
if (a.type === "points") {
|
|
61819
|
+
for (const v of verts) {
|
|
61820
|
+
// Only reuse the provided id for a single-point entry (the round-trip case);
|
|
61821
|
+
// a multi-point points entry must get a fresh id per marker to avoid duplicate keys.
|
|
61822
|
+
const id = a.id && verts.length === 1 ? a.id : this.nextId();
|
|
61823
|
+
const marker = makePointMarker(v, this.o.mesh, a.color, this.markerRadius);
|
|
61824
|
+
this.o.scene.add(marker);
|
|
61825
|
+
this.store.add({
|
|
61826
|
+
id,
|
|
61827
|
+
type: "points",
|
|
61828
|
+
mode: null,
|
|
61829
|
+
label: a.label,
|
|
61830
|
+
color: a.color,
|
|
61831
|
+
closed: false,
|
|
61832
|
+
visible: (_b = a.visible) !== null && _b !== void 0 ? _b : true,
|
|
61833
|
+
vertices: [v],
|
|
61834
|
+
object3D: marker,
|
|
61835
|
+
});
|
|
61836
|
+
// track max numeric id
|
|
61837
|
+
const m = id.match(/^a(\d+)$/);
|
|
61838
|
+
if (m)
|
|
61839
|
+
maxImported = Math.max(maxImported, parseInt(m[1], 10));
|
|
61840
|
+
count++;
|
|
61841
|
+
}
|
|
61842
|
+
}
|
|
61843
|
+
else {
|
|
61844
|
+
if (verts.length < 2)
|
|
61845
|
+
continue;
|
|
61846
|
+
const id = (_c = a.id) !== null && _c !== void 0 ? _c : this.nextId();
|
|
61847
|
+
const line = makeContourLine(verts, a.color, a.closed, this.o.container, this.epsilon, this.o.mesh);
|
|
61848
|
+
this.o.scene.add(line);
|
|
61849
|
+
this.store.add({
|
|
61850
|
+
id,
|
|
61851
|
+
type: "contour",
|
|
61852
|
+
mode: a.mode,
|
|
61853
|
+
label: a.label,
|
|
61854
|
+
color: a.color,
|
|
61855
|
+
closed: a.closed,
|
|
61856
|
+
visible: (_d = a.visible) !== null && _d !== void 0 ? _d : true,
|
|
61857
|
+
vertices: verts,
|
|
61858
|
+
object3D: line,
|
|
61859
|
+
});
|
|
61860
|
+
const m = id.match(/^a(\d+)$/);
|
|
61861
|
+
if (m)
|
|
61862
|
+
maxImported = Math.max(maxImported, parseInt(m[1], 10));
|
|
61863
|
+
count++;
|
|
61864
|
+
}
|
|
61865
|
+
}
|
|
61866
|
+
// keep seq ahead of any imported numeric ids to avoid collisions
|
|
61867
|
+
if (maxImported > this.seq)
|
|
61868
|
+
this.seq = maxImported;
|
|
61869
|
+
return count;
|
|
61870
|
+
}
|
|
61739
61871
|
// ---- Internal ----
|
|
61872
|
+
get drawing() {
|
|
61873
|
+
return this.drawLock || this.spaceHeld;
|
|
61874
|
+
}
|
|
61740
61875
|
applyCameraGating() {
|
|
61741
|
-
|
|
61742
|
-
|
|
61876
|
+
var _a, _b;
|
|
61877
|
+
// Default is navigate (camera enabled). Drawing only when drawLock or spaceHeld.
|
|
61878
|
+
this.o.controls.enabled = !this.drawing;
|
|
61879
|
+
(_b = (_a = this.o).onInteractionChange) === null || _b === void 0 ? void 0 : _b.call(_a, { drawing: this.drawing, armed: this.armed, locked: this.drawLock });
|
|
61743
61880
|
}
|
|
61744
61881
|
/** Reconcile the scene against store.list(): add missing objects, remove deleted ones (no dispose, kept for undo restore). */
|
|
61745
61882
|
reconcile() {
|
|
@@ -61757,6 +61894,11 @@ void main() {
|
|
|
61757
61894
|
this.o.scene.add(o);
|
|
61758
61895
|
}
|
|
61759
61896
|
this.managed = present;
|
|
61897
|
+
// Apply per-annotation visibility
|
|
61898
|
+
for (const a of this.store.list()) {
|
|
61899
|
+
if (a.object3D)
|
|
61900
|
+
a.object3D.visible = a.visible;
|
|
61901
|
+
}
|
|
61760
61902
|
this.applySelection();
|
|
61761
61903
|
(_b = (_a = this.o).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.store.list());
|
|
61762
61904
|
}
|
|
@@ -61764,6 +61906,8 @@ void main() {
|
|
|
61764
61906
|
for (const a of this.store.list()) {
|
|
61765
61907
|
if (!a.object3D)
|
|
61766
61908
|
continue;
|
|
61909
|
+
if (!a.visible)
|
|
61910
|
+
continue;
|
|
61767
61911
|
const sel = a.id === this.selectedId;
|
|
61768
61912
|
if (a.type === "contour") {
|
|
61769
61913
|
const mat = a.object3D.material;
|
|
@@ -61996,6 +62140,7 @@ void main() {
|
|
|
61996
62140
|
label: `Contour ${this.seq}`,
|
|
61997
62141
|
color: this.geodesicColor,
|
|
61998
62142
|
closed,
|
|
62143
|
+
visible: true,
|
|
61999
62144
|
vertices: verts,
|
|
62000
62145
|
object3D: this.activeGeoLine,
|
|
62001
62146
|
};
|
|
@@ -62029,7 +62174,8 @@ void main() {
|
|
|
62029
62174
|
window.removeEventListener("keyup", this.onKeyUp);
|
|
62030
62175
|
window.removeEventListener("resize", this.onResize);
|
|
62031
62176
|
}
|
|
62032
|
-
}
|
|
62177
|
+
}
|
|
62178
|
+
SurfaceAnnotator.TAP_MS = 250;
|
|
62033
62179
|
|
|
62034
62180
|
class copperScene extends baseScene {
|
|
62035
62181
|
// rayster pick
|
|
@@ -83452,15 +83598,15 @@ void main() {
|
|
|
83452
83598
|
}
|
|
83453
83599
|
|
|
83454
83600
|
// import * as kiwrious from "copper3d_plugin_heart_k";
|
|
83455
|
-
// "v3.6.
|
|
83601
|
+
// "v3.6.8" is injected at build time by rollup @rollup/plugin-replace, sourced from package.json version.
|
|
83456
83602
|
// When copper3d is consumed from local source (no rollup replace step), the identifier is undefined and
|
|
83457
83603
|
// referencing it throws a ReferenceError — guard it so local loading still works.
|
|
83458
83604
|
let _revision = "unknown";
|
|
83459
83605
|
try {
|
|
83460
|
-
_revision = "v3.6.
|
|
83606
|
+
_revision = "v3.6.8";
|
|
83461
83607
|
}
|
|
83462
83608
|
catch (_a) {
|
|
83463
|
-
/* "v3.6.
|
|
83609
|
+
/* "v3.6.8" not injected (local source build) */
|
|
83464
83610
|
}
|
|
83465
83611
|
const REVISION = _revision;
|
|
83466
83612
|
// Expose on global so the version can be read in a production browser console via window.__COPPER3D_VERSION__
|
|
@@ -29,6 +29,10 @@ export declare class MeshGraph {
|
|
|
29
29
|
shortestPath(startV: number, endV: number): number[];
|
|
30
30
|
vertexWorld(i: number, matrixWorld: THREE.Matrix4): THREE.Vector3;
|
|
31
31
|
vertexNormalWorld(i: number, mesh: THREE.Mesh): THREE.Vector3;
|
|
32
|
+
/** Vertex local normal at index i (reads from the welded graphGeo normal attribute). */
|
|
33
|
+
vertexNormalLocal(i: number): THREE.Vector3;
|
|
34
|
+
/** Normal at the vertex nearest to localPoint (for recovering normals from imported point coordinates). */
|
|
35
|
+
nearestNormalLocal(p: THREE.Vector3): THREE.Vector3;
|
|
32
36
|
/** Vertex local coordinates + local normal (the graph geometry is already local space). */
|
|
33
37
|
vertexLocal(i: number): {
|
|
34
38
|
x: number;
|
|
@@ -31,6 +31,12 @@ export interface SurfaceAnnotatorOptions {
|
|
|
31
31
|
onModeChange?: (m: AnnotationMode) => void;
|
|
32
32
|
/** Callback when the annotation list changes (add/remove/undo/clear). */
|
|
33
33
|
onChange?: (annotations: Annotation[]) => void;
|
|
34
|
+
/** Callback when interaction state changes (drawing, armed tool, draw-lock status). */
|
|
35
|
+
onInteractionChange?: (s: {
|
|
36
|
+
drawing: boolean;
|
|
37
|
+
armed: AnnotationMode;
|
|
38
|
+
locked: boolean;
|
|
39
|
+
}) => void;
|
|
34
40
|
}
|
|
35
41
|
/**
|
|
36
42
|
* Main surface-annotation controller (Phase 4): four modes navigate / freehand / geodesic / point,
|
|
@@ -42,6 +48,11 @@ export declare class SurfaceAnnotator {
|
|
|
42
48
|
private o;
|
|
43
49
|
private mode;
|
|
44
50
|
private spaceHeld;
|
|
51
|
+
private drawLock;
|
|
52
|
+
private armed;
|
|
53
|
+
private spaceDownAt;
|
|
54
|
+
private spaceDragged;
|
|
55
|
+
private static readonly TAP_MS;
|
|
45
56
|
private pointerDown;
|
|
46
57
|
private readonly markerRadius;
|
|
47
58
|
private readonly epsilon;
|
|
@@ -91,9 +102,29 @@ export declare class SurfaceAnnotator {
|
|
|
91
102
|
label: string;
|
|
92
103
|
color: string;
|
|
93
104
|
closed: boolean;
|
|
105
|
+
visible: boolean;
|
|
94
106
|
points: number[][];
|
|
95
107
|
}[];
|
|
96
108
|
};
|
|
109
|
+
setVisible(id: string, visible: boolean): void;
|
|
110
|
+
/**
|
|
111
|
+
* Rebuild annotations from an exported payload (local-space points). Normals are taken from the
|
|
112
|
+
* point when present ([x,y,z,nx,ny,nz]); otherwise recovered from the welded graph's nearest
|
|
113
|
+
* vertex. Each imported item becomes first-class (select/recolor/hide/delete/export).
|
|
114
|
+
*/
|
|
115
|
+
importAnnotations(payload: {
|
|
116
|
+
annotations: Array<{
|
|
117
|
+
id?: string;
|
|
118
|
+
type: "contour" | "points";
|
|
119
|
+
mode: "freehand" | "geodesic" | null;
|
|
120
|
+
label: string;
|
|
121
|
+
color: string;
|
|
122
|
+
closed: boolean;
|
|
123
|
+
visible?: boolean;
|
|
124
|
+
points: number[][];
|
|
125
|
+
}>;
|
|
126
|
+
}): number;
|
|
127
|
+
private get drawing();
|
|
97
128
|
private applyCameraGating;
|
|
98
129
|
/** Reconcile the scene against store.list(): add missing objects, remove deleted ones (no dispose, kept for undo restore). */
|
|
99
130
|
private reconcile;
|
|
@@ -20,6 +20,7 @@ export declare class AnnotationStore {
|
|
|
20
20
|
get(id: string): Annotation | undefined;
|
|
21
21
|
setLabel(id: string, label: string): void;
|
|
22
22
|
setColor(id: string, color: string): void;
|
|
23
|
+
setVisible(id: string, visible: boolean): void;
|
|
23
24
|
toJSON(modelName: string, mesh: THREE.Mesh, opts?: ExportOptions): {
|
|
24
25
|
model: string;
|
|
25
26
|
exportedAt: string;
|
|
@@ -31,6 +32,7 @@ export declare class AnnotationStore {
|
|
|
31
32
|
label: string;
|
|
32
33
|
color: string;
|
|
33
34
|
closed: boolean;
|
|
35
|
+
visible: boolean;
|
|
34
36
|
points: number[][];
|
|
35
37
|
}[];
|
|
36
38
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "copper3d",
|
|
3
3
|
"description": "A 3d visualisation package base on threejs provides multiple scenes and Nrrd image load funtion.",
|
|
4
|
-
"version": "3.6.
|
|
4
|
+
"version": "3.6.8",
|
|
5
5
|
"main": "dist/bundle.umd.js",
|
|
6
6
|
"moudle": "dist/bundle.esm.js",
|
|
7
7
|
"types": "dist/types/index.d.ts",
|