cloudmr-ux 4.6.2 → 4.6.3
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/CmrComponents/niivue-viewer/CloudMrNiivueViewer.js +6 -14
- package/dist/CmrComponents/niivue-viewer/NiivuePatcher.js +54 -74
- package/dist/CmrComponents/niivue-viewer/penDraftUtils.d.ts +0 -21
- package/dist/CmrComponents/niivue-viewer/penDraftUtils.js +1 -30
- package/dist/CmrComponents/niivue-viewer/shapeDraftUtils.d.ts +3 -1
- package/dist/CmrComponents/niivue-viewer/shapeDraftUtils.js +61 -1
- package/package.json +1 -1
|
@@ -832,13 +832,11 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
832
832
|
(_a = nv.cloudMrCancelPolyline) === null || _a === void 0 ? void 0 : _a.call(nv);
|
|
833
833
|
}
|
|
834
834
|
}
|
|
835
|
-
function
|
|
835
|
+
function syncActiveShapeDraftRef() {
|
|
836
836
|
nv._cloudMrActiveShapeDraft = shapeDraftRef.current;
|
|
837
|
-
nv._cloudMrActivePenDraft = penDraftRef.current;
|
|
838
837
|
}
|
|
839
|
-
function
|
|
838
|
+
function clearActiveShapeDraftRef() {
|
|
840
839
|
nv._cloudMrActiveShapeDraft = null;
|
|
841
|
-
nv._cloudMrActivePenDraft = null;
|
|
842
840
|
}
|
|
843
841
|
function cancelPenDraftHandler() {
|
|
844
842
|
var _a;
|
|
@@ -853,7 +851,6 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
853
851
|
setPenDraft(null);
|
|
854
852
|
penDraftRef.current = null;
|
|
855
853
|
nv._cloudMrPenDraftActive = false;
|
|
856
|
-
clearActiveDraftRefs();
|
|
857
854
|
if (drawShapeToolRef.current === "pen") {
|
|
858
855
|
nvSetDrawingEnabled(true);
|
|
859
856
|
}
|
|
@@ -871,7 +868,6 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
871
868
|
setPenDraft(null);
|
|
872
869
|
penDraftRef.current = null;
|
|
873
870
|
nv._cloudMrPenDraftActive = false;
|
|
874
|
-
clearActiveDraftRefs();
|
|
875
871
|
setDrawingChanged(true);
|
|
876
872
|
if (drawShapeToolRef.current === "pen") {
|
|
877
873
|
nvSetDrawingEnabled(true);
|
|
@@ -888,7 +884,6 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
888
884
|
function onPenDraftChange(draft) {
|
|
889
885
|
setPenDraft(draft);
|
|
890
886
|
penDraftRef.current = draft;
|
|
891
|
-
syncActiveDraftRefs();
|
|
892
887
|
if (draft.kind === "polyline") {
|
|
893
888
|
syncPolylineDraftToNv(nv, draft);
|
|
894
889
|
}
|
|
@@ -900,7 +895,6 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
900
895
|
setPenDraft(draft);
|
|
901
896
|
penDraftRef.current = draft;
|
|
902
897
|
nv._cloudMrPenDraftActive = true;
|
|
903
|
-
syncActiveDraftRefs();
|
|
904
898
|
nvSetDrawingEnabled(false);
|
|
905
899
|
};
|
|
906
900
|
nv.onPolylineChange = function (count) {
|
|
@@ -915,13 +909,11 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
915
909
|
if (draft) {
|
|
916
910
|
setPenDraft(draft);
|
|
917
911
|
penDraftRef.current = draft;
|
|
918
|
-
syncActiveDraftRefs();
|
|
919
912
|
}
|
|
920
913
|
}
|
|
921
914
|
else if (((_b = penDraftRef.current) === null || _b === void 0 ? void 0 : _b.kind) === "polyline") {
|
|
922
915
|
setPenDraft(null);
|
|
923
916
|
penDraftRef.current = null;
|
|
924
|
-
syncActiveDraftRefs();
|
|
925
917
|
}
|
|
926
918
|
};
|
|
927
919
|
function cancelShapeDraft() {
|
|
@@ -934,7 +926,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
934
926
|
setShapeDraft(null);
|
|
935
927
|
shapeDraftRef.current = null;
|
|
936
928
|
nv._cloudMrShapeDraftActive = false;
|
|
937
|
-
|
|
929
|
+
clearActiveShapeDraftRef();
|
|
938
930
|
if (drawShapeToolRef.current) {
|
|
939
931
|
nvSetDrawingEnabled(true);
|
|
940
932
|
}
|
|
@@ -947,7 +939,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
947
939
|
setShapeDraft(null);
|
|
948
940
|
shapeDraftRef.current = null;
|
|
949
941
|
nv._cloudMrShapeDraftActive = false;
|
|
950
|
-
|
|
942
|
+
clearActiveShapeDraftRef();
|
|
951
943
|
if (drawShapeToolRef.current) {
|
|
952
944
|
nvSetDrawingEnabled(true);
|
|
953
945
|
}
|
|
@@ -956,13 +948,13 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
956
948
|
function onShapeDraftChange(draft) {
|
|
957
949
|
setShapeDraft(draft);
|
|
958
950
|
shapeDraftRef.current = draft;
|
|
959
|
-
|
|
951
|
+
syncActiveShapeDraftRef();
|
|
960
952
|
}
|
|
961
953
|
nv.onShapeDraftReady = function (draft) {
|
|
962
954
|
setShapeDraft(draft);
|
|
963
955
|
shapeDraftRef.current = draft;
|
|
964
956
|
nv._cloudMrShapeDraftActive = true;
|
|
965
|
-
|
|
957
|
+
syncActiveShapeDraftRef();
|
|
966
958
|
nvSetDrawingEnabled(false);
|
|
967
959
|
};
|
|
968
960
|
nv.onApplyActiveDraft = function () {
|
|
@@ -23,9 +23,6 @@ import {
|
|
|
23
23
|
} from "./polylinePenUtils.js";
|
|
24
24
|
import {
|
|
25
25
|
captureFreehandDraft,
|
|
26
|
-
capturePenDraftFromClick,
|
|
27
|
-
isPenDrawToolActive,
|
|
28
|
-
redrawFreehandDraft,
|
|
29
26
|
shouldDeferFreehandCommit,
|
|
30
27
|
} from "./penDraftUtils.js";
|
|
31
28
|
|
|
@@ -1476,89 +1473,83 @@ function cloudMrHasApplyableDraft(nv) {
|
|
|
1476
1473
|
return !!(nv._cloudMrShapeDraftActive || nv._cloudMrPenDraftActive);
|
|
1477
1474
|
}
|
|
1478
1475
|
|
|
1479
|
-
function
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
}
|
|
1483
|
-
if (nv._cloudMrShapeDraftActive && nv._cloudMrActiveShapeDraft) {
|
|
1484
|
-
return nv._cloudMrActiveShapeDraft;
|
|
1485
|
-
}
|
|
1486
|
-
return null;
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1489
|
-
function isClickOnActiveDraft(nv) {
|
|
1490
|
-
const draft = getActiveDraft(nv);
|
|
1491
|
-
if (!draft) return false;
|
|
1476
|
+
function isClickOnActiveShapeDraft(nv) {
|
|
1477
|
+
const draft = nv._cloudMrActiveShapeDraft;
|
|
1478
|
+
if (!draft || !nv._cloudMrShapeDraftActive) return false;
|
|
1492
1479
|
const vox = voxFromMouse(nv);
|
|
1493
1480
|
if (!vox) return false;
|
|
1494
1481
|
return isVoxelPartOfDraft(nv, draft, vox);
|
|
1495
1482
|
}
|
|
1496
1483
|
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1484
|
+
function canReopenShapeDraftOnClick(nv) {
|
|
1485
|
+
const penType = nv.opts.penType;
|
|
1486
|
+
return (
|
|
1487
|
+
nv.opts.deferShapeCommit &&
|
|
1488
|
+
nv.opts.drawingEnabled &&
|
|
1489
|
+
!nv._cloudMrShapeDraftActive &&
|
|
1490
|
+
!nv._cloudMrPenDraftActive &&
|
|
1491
|
+
(penType === NI_PEN_TYPE.RECTANGLE || penType === NI_PEN_TYPE.ELLIPSE)
|
|
1492
|
+
);
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
function cloudMrOpenShapeDraftFromClick(nv) {
|
|
1496
|
+
const reopenDraft = captureShapeDraftFromClick(nv);
|
|
1497
|
+
if (!reopenDraft) return false;
|
|
1498
|
+
redrawDraftShape(nv, reopenDraft);
|
|
1499
|
+
nv._cloudMrSuppressDrawingChangedMouseUp = true;
|
|
1500
|
+
if (typeof nv.onShapeDraftReady === "function") {
|
|
1501
|
+
nv.onShapeDraftReady(reopenDraft);
|
|
1508
1502
|
}
|
|
1509
1503
|
return true;
|
|
1510
1504
|
}
|
|
1511
1505
|
|
|
1512
1506
|
/**
|
|
1513
|
-
*
|
|
1514
|
-
* shape or pen draft so the bounding-box overlay reappears for re-editing.
|
|
1507
|
+
* Re-enter rectangle/ellipse edit mode when clicking an existing shape ROI.
|
|
1515
1508
|
*/
|
|
1516
|
-
function
|
|
1517
|
-
if (
|
|
1518
|
-
nv._cloudMrShapeDraftActive ||
|
|
1519
|
-
nv._cloudMrPenDraftActive ||
|
|
1520
|
-
!isClickWithoutDrag(nv.uiData)
|
|
1521
|
-
) {
|
|
1509
|
+
function cloudMrTryReopenShapeDraftOnClick(nv) {
|
|
1510
|
+
if (!isClickWithoutDrag(nv.uiData) || !canReopenShapeDraftOnClick(nv)) {
|
|
1522
1511
|
return false;
|
|
1523
1512
|
}
|
|
1513
|
+
return cloudMrOpenShapeDraftFromClick(nv);
|
|
1514
|
+
}
|
|
1524
1515
|
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1516
|
+
/**
|
|
1517
|
+
* While editing one shape, mousedown on another shape applies the current
|
|
1518
|
+
* draft immediately and opens the clicked shape for editing.
|
|
1519
|
+
*/
|
|
1520
|
+
function cloudMrTrySwitchShapeDraftOnMouseDown(nv) {
|
|
1521
|
+
if (!nv._cloudMrShapeDraftActive || nv._cloudMrPenDraftActive) {
|
|
1522
|
+
return false;
|
|
1523
|
+
}
|
|
1524
|
+
if (!nv.opts.deferShapeCommit || !nv.opts.drawingEnabled) {
|
|
1533
1525
|
return false;
|
|
1534
1526
|
}
|
|
1535
1527
|
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
redrawDraftShape(nv, reopenDraft);
|
|
1540
|
-
nv._cloudMrSuppressDrawingChangedMouseUp = true;
|
|
1541
|
-
if (typeof nv.onShapeDraftReady === "function") {
|
|
1542
|
-
nv.onShapeDraftReady(reopenDraft);
|
|
1543
|
-
}
|
|
1544
|
-
return true;
|
|
1528
|
+
const vox = voxFromMouse(nv);
|
|
1529
|
+
if (!vox || isClickOnActiveShapeDraft(nv)) {
|
|
1530
|
+
return false;
|
|
1545
1531
|
}
|
|
1546
1532
|
|
|
1547
|
-
const
|
|
1548
|
-
if (!
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1533
|
+
const dims = nv.back?.dims;
|
|
1534
|
+
if (!dims || !nv.drawBitmap) return false;
|
|
1535
|
+
const dx = dims[1];
|
|
1536
|
+
const dy = dims[2];
|
|
1537
|
+
const idx = vox[0] + vox[1] * dx + vox[2] * dx * dy;
|
|
1538
|
+
if (!nv.drawBitmap[idx]) {
|
|
1539
|
+
return false;
|
|
1553
1540
|
}
|
|
1554
|
-
|
|
1555
|
-
|
|
1541
|
+
|
|
1542
|
+
if (typeof nv.onApplyActiveDraft === "function") {
|
|
1543
|
+
nv.onApplyActiveDraft();
|
|
1556
1544
|
}
|
|
1557
|
-
return
|
|
1545
|
+
return cloudMrOpenShapeDraftFromClick(nv);
|
|
1558
1546
|
}
|
|
1559
1547
|
|
|
1560
1548
|
const _mouseDownListener = Niivue.prototype.mouseDownListener;
|
|
1561
1549
|
Niivue.prototype.mouseDownListener = function cloudMrMouseDownListener(e) {
|
|
1550
|
+
if (e.button === 0 && cloudMrTrySwitchShapeDraftOnMouseDown(this)) {
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1562
1553
|
if (shouldDeferFreehandCommit(this) && this.drawBitmap) {
|
|
1563
1554
|
this._cloudMrFreehandSessionStartBitmap = this.drawBitmap.slice();
|
|
1564
1555
|
this._cloudMrFreehandAxCorSag = -1;
|
|
@@ -1622,30 +1613,19 @@ Niivue.prototype.mouseUpListener = function cloudMrMouseUpListener() {
|
|
|
1622
1613
|
_mouseUpListener.call(this);
|
|
1623
1614
|
|
|
1624
1615
|
if (polylineClick) {
|
|
1625
|
-
if (cloudMrTryReopenDraftOnClick(this)) return;
|
|
1626
1616
|
addPolylineVertex(this);
|
|
1627
1617
|
return;
|
|
1628
1618
|
}
|
|
1629
1619
|
|
|
1630
|
-
if (cloudMrHasApplyableDraft(this) && isClickWithoutDrag(this.uiData)) {
|
|
1631
|
-
if (cloudMrTryApplyDraftOnClickAway(this)) {
|
|
1632
|
-
cloudMrTryReopenDraftOnClick(this);
|
|
1633
|
-
return;
|
|
1634
|
-
}
|
|
1635
|
-
if (isClickOnActiveDraft(this)) {
|
|
1636
|
-
return;
|
|
1637
|
-
}
|
|
1638
|
-
}
|
|
1639
|
-
|
|
1640
1620
|
if (!pendingDraft?.baseBitmap) {
|
|
1641
|
-
|
|
1621
|
+
cloudMrTryReopenShapeDraftOnClick(this);
|
|
1642
1622
|
return;
|
|
1643
1623
|
}
|
|
1644
1624
|
if (isDraftTooSmall(pendingDraft.ptA, pendingDraft.ptB)) {
|
|
1645
1625
|
this.drawBitmap.set(pendingDraft.baseBitmap);
|
|
1646
1626
|
this.refreshDrawing(true, false);
|
|
1647
1627
|
this.drawScene();
|
|
1648
|
-
|
|
1628
|
+
cloudMrTryReopenShapeDraftOnClick(this);
|
|
1649
1629
|
return;
|
|
1650
1630
|
}
|
|
1651
1631
|
this._cloudMrSuppressDrawingChangedMouseUp = true;
|
|
@@ -13,27 +13,6 @@
|
|
|
13
13
|
export function isEraserActive(nv: any): any;
|
|
14
14
|
export function isFreehandPenActive(nv: any): any;
|
|
15
15
|
export function shouldDeferFreehandCommit(nv: any): any;
|
|
16
|
-
export function isPenDrawToolActive(nv: any): any;
|
|
17
|
-
/**
|
|
18
|
-
* Re-enter pen edit mode when clicking an existing freehand/polyline ROI.
|
|
19
|
-
* Reopens as a freehand draft (move via bounding box) since vertex data is
|
|
20
|
-
* not stored in the bitmap alone.
|
|
21
|
-
*/
|
|
22
|
-
export function capturePenDraftFromClick(nv: any): {
|
|
23
|
-
kind: string;
|
|
24
|
-
baseBitmap: Uint8Array;
|
|
25
|
-
axCorSag: any;
|
|
26
|
-
penValue: number;
|
|
27
|
-
strokeVoxels: [number, number, number][];
|
|
28
|
-
bounds: {
|
|
29
|
-
x1: any;
|
|
30
|
-
y1: any;
|
|
31
|
-
z1: any;
|
|
32
|
-
x2: any;
|
|
33
|
-
y2: any;
|
|
34
|
-
z2: any;
|
|
35
|
-
};
|
|
36
|
-
} | null;
|
|
37
16
|
export function redrawPolylineDraft(nv: any, draft: any): void;
|
|
38
17
|
export function translatePolylineVertices(vertices: any, delta: any): any;
|
|
39
18
|
export function updatePolylineVertex(vertices: any, index: any, newVox: any): any;
|
|
@@ -18,8 +18,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
18
18
|
}
|
|
19
19
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
20
20
|
};
|
|
21
|
-
import { translatePt
|
|
22
|
-
import { axCorSagFromMouse, voxFromMouse } from "./polylinePenUtils";
|
|
21
|
+
import { translatePt } from "./shapeDraftUtils";
|
|
23
22
|
import { NI_PEN_TYPE } from "./niivuePenType";
|
|
24
23
|
/** @typedef {'polyline' | 'freehand'} PenDraftKind */
|
|
25
24
|
/**
|
|
@@ -48,34 +47,6 @@ export function isFreehandPenActive(nv) {
|
|
|
48
47
|
export function shouldDeferFreehandCommit(nv) {
|
|
49
48
|
return !!nv.opts.deferFreehandCommit && isFreehandPenActive(nv);
|
|
50
49
|
}
|
|
51
|
-
export function isPenDrawToolActive(nv) {
|
|
52
|
-
return (nv.opts.drawingEnabled &&
|
|
53
|
-
nv.opts.penType === NI_PEN_TYPE.PEN &&
|
|
54
|
-
nv.opts.penValue > 0 &&
|
|
55
|
-
(nv.opts.deferFreehandCommit || nv.opts.polylinePenMode));
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Re-enter pen edit mode when clicking an existing freehand/polyline ROI.
|
|
59
|
-
* Reopens as a freehand draft (move via bounding box) since vertex data is
|
|
60
|
-
* not stored in the bitmap alone.
|
|
61
|
-
*/
|
|
62
|
-
export function capturePenDraftFromClick(nv) {
|
|
63
|
-
var seedVox = voxFromMouse(nv);
|
|
64
|
-
var cluster = floodFillClusterFromVox(nv, seedVox);
|
|
65
|
-
if (!cluster)
|
|
66
|
-
return null;
|
|
67
|
-
var label = cluster.label, visited = cluster.visited, voxels = cluster.voxels, bounds = cluster.bounds;
|
|
68
|
-
var x1 = bounds.x1, y1 = bounds.y1, z1 = bounds.z1, x2 = bounds.x2, y2 = bounds.y2, z2 = bounds.z2;
|
|
69
|
-
var axCorSag = nv.drawPenAxCorSag >= 0 ? nv.drawPenAxCorSag : axCorSagFromMouse(nv);
|
|
70
|
-
return {
|
|
71
|
-
kind: "freehand",
|
|
72
|
-
baseBitmap: eraseClusterFromBitmap(nv.drawBitmap, visited),
|
|
73
|
-
axCorSag: axCorSag,
|
|
74
|
-
penValue: label,
|
|
75
|
-
strokeVoxels: voxels,
|
|
76
|
-
bounds: { x1: x1, y1: y1, z1: z1, x2: x2, y2: y2, z2: z2 }
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
50
|
export function redrawPolylineDraft(nv, draft) {
|
|
80
51
|
var _a;
|
|
81
52
|
if (!((_a = draft === null || draft === void 0 ? void 0 : draft.vertices) === null || _a === void 0 ? void 0 : _a.length) || !draft.baseBitmap)
|
|
@@ -62,6 +62,8 @@ export function floodFillClusterFromVox(nv: any, seedVox: any): {
|
|
|
62
62
|
/** True when a voxel belongs to the live draft overlay (drawn on top of baseBitmap). */
|
|
63
63
|
export function isVoxelPartOfDraft(nv: any, draft: any, seedVox: any): boolean;
|
|
64
64
|
export function eraseClusterFromBitmap(bitmap: any, visited: any): Uint8Array;
|
|
65
|
+
/** Guess rectangle vs ellipse from the filled voxel pattern, not the active tool. */
|
|
66
|
+
export function inferShapePenTypeFromCluster(cluster: any, axCorSag: any): 1 | 2;
|
|
65
67
|
/**
|
|
66
68
|
* When the user clicks on an existing filled ROI while the rectangle/ellipse tool
|
|
67
69
|
* is active (but no draft is currently open), flood-fill the clicked cluster to
|
|
@@ -74,7 +76,7 @@ export function captureShapeDraftFromClick(nv: any): {
|
|
|
74
76
|
ptB: any[];
|
|
75
77
|
penValue: number;
|
|
76
78
|
axCorSag: number;
|
|
77
|
-
penType:
|
|
79
|
+
penType: 1 | 2;
|
|
78
80
|
baseBitmap: Uint8Array;
|
|
79
81
|
} | null;
|
|
80
82
|
export type ShapeDraftKind = 'rectangle' | 'ellipse';
|
|
@@ -295,6 +295,65 @@ export function eraseClusterFromBitmap(bitmap, visited) {
|
|
|
295
295
|
});
|
|
296
296
|
return next;
|
|
297
297
|
}
|
|
298
|
+
function sliceKey(axCorSag, x, y, z) {
|
|
299
|
+
if (axCorSag === 0)
|
|
300
|
+
return "".concat(x, ",").concat(y);
|
|
301
|
+
if (axCorSag === 1)
|
|
302
|
+
return "".concat(x, ",").concat(z);
|
|
303
|
+
return "".concat(y, ",").concat(z);
|
|
304
|
+
}
|
|
305
|
+
/** Guess rectangle vs ellipse from the filled voxel pattern, not the active tool. */
|
|
306
|
+
export function inferShapePenTypeFromCluster(cluster, axCorSag) {
|
|
307
|
+
var bounds = cluster.bounds, voxels = cluster.voxels;
|
|
308
|
+
var x1 = bounds.x1, y1 = bounds.y1, z1 = bounds.z1, x2 = bounds.x2, y2 = bounds.y2, z2 = bounds.z2;
|
|
309
|
+
var filled = new Set();
|
|
310
|
+
for (var _i = 0, voxels_1 = voxels; _i < voxels_1.length; _i++) {
|
|
311
|
+
var _a = voxels_1[_i], x = _a[0], y = _a[1], z = _a[2];
|
|
312
|
+
filled.add(sliceKey(axCorSag, x, y, z));
|
|
313
|
+
}
|
|
314
|
+
var uMin;
|
|
315
|
+
var uMax;
|
|
316
|
+
var vMin;
|
|
317
|
+
var vMax;
|
|
318
|
+
if (axCorSag === 0) {
|
|
319
|
+
uMin = x1;
|
|
320
|
+
uMax = x2;
|
|
321
|
+
vMin = y1;
|
|
322
|
+
vMax = y2;
|
|
323
|
+
}
|
|
324
|
+
else if (axCorSag === 1) {
|
|
325
|
+
uMin = x1;
|
|
326
|
+
uMax = x2;
|
|
327
|
+
vMin = z1;
|
|
328
|
+
vMax = z2;
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
uMin = y1;
|
|
332
|
+
uMax = y2;
|
|
333
|
+
vMin = z1;
|
|
334
|
+
vMax = z2;
|
|
335
|
+
}
|
|
336
|
+
if (uMax <= uMin || vMax <= vMin) {
|
|
337
|
+
return NI_PEN_TYPE.RECTANGLE;
|
|
338
|
+
}
|
|
339
|
+
var cu = (uMin + uMax) / 2;
|
|
340
|
+
var cv = (vMin + vMax) / 2;
|
|
341
|
+
var ru = Math.max(0.5, (uMax - uMin) / 2);
|
|
342
|
+
var rv = Math.max(0.5, (vMax - vMin) / 2);
|
|
343
|
+
var rectScore = 0;
|
|
344
|
+
var ellipseScore = 0;
|
|
345
|
+
for (var u = uMin; u <= uMax; u++) {
|
|
346
|
+
for (var v = vMin; v <= vMax; v++) {
|
|
347
|
+
var has = filled.has("".concat(u, ",").concat(v));
|
|
348
|
+
var inEllipse = Math.pow(((u - cu) / ru), 2) + Math.pow(((v - cv) / rv), 2) <= 1.05;
|
|
349
|
+
if (has)
|
|
350
|
+
rectScore++;
|
|
351
|
+
if (has === inEllipse)
|
|
352
|
+
ellipseScore++;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return ellipseScore > rectScore ? NI_PEN_TYPE.ELLIPSE : NI_PEN_TYPE.RECTANGLE;
|
|
356
|
+
}
|
|
298
357
|
/**
|
|
299
358
|
* When the user clicks on an existing filled ROI while the rectangle/ellipse tool
|
|
300
359
|
* is active (but no draft is currently open), flood-fill the clicked cluster to
|
|
@@ -311,12 +370,13 @@ export function captureShapeDraftFromClick(nv) {
|
|
|
311
370
|
var x1 = bounds.x1, y1 = bounds.y1, z1 = bounds.z1, x2 = bounds.x2, y2 = bounds.y2, z2 = bounds.z2;
|
|
312
371
|
var baseBitmap = eraseClusterFromBitmap(nv.drawBitmap, visited);
|
|
313
372
|
var axCorSag = inferAxCorSagFromBounds(x1, y1, z1, x2, y2, z2, nv.drawPenAxCorSag >= 0 ? nv.drawPenAxCorSag : 0);
|
|
373
|
+
var penType = inferShapePenTypeFromCluster(cluster, axCorSag);
|
|
314
374
|
return {
|
|
315
375
|
ptA: [x1, y1, z1],
|
|
316
376
|
ptB: [x2, y2, z2],
|
|
317
377
|
penValue: label,
|
|
318
378
|
axCorSag: axCorSag,
|
|
319
|
-
penType:
|
|
379
|
+
penType: penType,
|
|
320
380
|
baseBitmap: baseBitmap
|
|
321
381
|
};
|
|
322
382
|
}
|