@cornerstonejs/tools 1.83.4 → 1.84.1
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/cjs/eventDispatchers/mouseEventHandlers/mouseMove.js +4 -0
- package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseMove.js.map +1 -1
- package/dist/cjs/tools/annotation/LivewireContourTool.d.ts +5 -0
- package/dist/cjs/tools/annotation/LivewireContourTool.js +154 -6
- package/dist/cjs/tools/annotation/LivewireContourTool.js.map +1 -1
- package/dist/esm/eventDispatchers/mouseEventHandlers/mouseMove.js +4 -0
- package/dist/esm/eventDispatchers/mouseEventHandlers/mouseMove.js.map +1 -1
- package/dist/esm/tools/annotation/LivewireContourTool.js +156 -9
- package/dist/esm/tools/annotation/LivewireContourTool.js.map +1 -1
- package/dist/types/eventDispatchers/mouseEventHandlers/mouseMove.d.ts.map +1 -1
- package/dist/types/tools/annotation/LivewireContourTool.d.ts +5 -0
- package/dist/types/tools/annotation/LivewireContourTool.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -3
- package/src/eventDispatchers/mouseEventHandlers/mouseMove.ts +5 -0
- package/src/tools/annotation/LivewireContourTool.ts +274 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.84.1",
|
|
4
4
|
"description": "Cornerstone3D Tools",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@cornerstonejs/core": "^1.
|
|
32
|
+
"@cornerstonejs/core": "^1.84.1",
|
|
33
33
|
"@icr/polyseg-wasm": "0.4.0",
|
|
34
34
|
"@types/offscreencanvas": "2019.7.3",
|
|
35
35
|
"comlink": "^4.4.1",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"type": "individual",
|
|
60
60
|
"url": "https://ohif.org/donate"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "e14af95b33e92828f3e0c8c21f0dc9319647abda"
|
|
63
63
|
}
|
|
@@ -7,6 +7,7 @@ import filterToolsWithAnnotationsForElement from '../../store/filterToolsWithAnn
|
|
|
7
7
|
import getToolsWithModesForMouseEvent from '../shared/getToolsWithModesForMouseEvent';
|
|
8
8
|
import triggerAnnotationRender from '../../utilities/triggerAnnotationRender';
|
|
9
9
|
import { MouseMoveEventType } from '../../types/EventTypes';
|
|
10
|
+
import { initElementCursor } from '../../cursors/elementCursor';
|
|
10
11
|
|
|
11
12
|
const { Active, Passive } = ToolModes;
|
|
12
13
|
|
|
@@ -67,4 +68,8 @@ export default function mouseMove(evt: MouseMoveEventType) {
|
|
|
67
68
|
if (annotationsNeedToBeRedrawn === true) {
|
|
68
69
|
triggerAnnotationRender(element);
|
|
69
70
|
}
|
|
71
|
+
|
|
72
|
+
if (!state.isInteractingWithTool) {
|
|
73
|
+
initElementCursor(element, null);
|
|
74
|
+
}
|
|
70
75
|
}
|
|
@@ -3,11 +3,17 @@ import {
|
|
|
3
3
|
getEnabledElement,
|
|
4
4
|
utilities as csUtils,
|
|
5
5
|
VolumeViewport,
|
|
6
|
+
utilities,
|
|
7
|
+
triggerEvent,
|
|
8
|
+
eventTarget,
|
|
6
9
|
} from '@cornerstonejs/core';
|
|
7
10
|
import type { Types } from '@cornerstonejs/core';
|
|
8
11
|
|
|
9
12
|
import { removeAnnotation } from '../../stateManagement/annotation/annotationState';
|
|
10
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
drawHandles as drawHandlesSvg,
|
|
15
|
+
drawLinkedTextBox as drawLinkedTextBoxSvg,
|
|
16
|
+
} from '../../drawingSvg';
|
|
11
17
|
import { state } from '../../store';
|
|
12
18
|
import { Events, KeyboardBindings, ChangeTypes } from '../../enums';
|
|
13
19
|
import { resetElementCursor } from '../../cursors/elementCursor';
|
|
@@ -17,9 +23,16 @@ import type {
|
|
|
17
23
|
PublicToolProps,
|
|
18
24
|
ToolProps,
|
|
19
25
|
SVGDrawingHelper,
|
|
26
|
+
TextBoxHandle,
|
|
20
27
|
} from '../../types';
|
|
21
28
|
import getMouseModifierKey from '../../eventDispatchers/shared/getMouseModifier';
|
|
22
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
getCalibratedLengthUnitsAndScale,
|
|
31
|
+
math,
|
|
32
|
+
roundNumber,
|
|
33
|
+
throttle,
|
|
34
|
+
triggerAnnotationRenderForViewportIds,
|
|
35
|
+
} from '../../utilities';
|
|
23
36
|
import findHandlePolylineIndex from '../../utilities/contours/findHandlePolylineIndex';
|
|
24
37
|
import { LivewireContourAnnotation } from '../../types/ToolSpecificAnnotationTypes';
|
|
25
38
|
import { ContourWindingDirection } from '../../types/ContourAnnotation';
|
|
@@ -32,6 +45,8 @@ import { LivewireScissors } from '../../utilities/livewire/LivewireScissors';
|
|
|
32
45
|
import { LivewirePath } from '../../utilities/livewire/LiveWirePath';
|
|
33
46
|
import { getViewportIdsWithToolToRender } from '../../utilities/viewportFilters';
|
|
34
47
|
import ContourSegmentationBaseTool from '../base/ContourSegmentationBaseTool';
|
|
48
|
+
import { AnnotationModifiedEventDetail } from '../../types/EventTypes';
|
|
49
|
+
import { getTextBoxCoordsCanvas } from '../../utilities/drawing';
|
|
35
50
|
|
|
36
51
|
const CLICK_CLOSE_CURVE_SQR_DIST = 10 ** 2; // px
|
|
37
52
|
|
|
@@ -43,10 +58,12 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
43
58
|
|
|
44
59
|
touchDragCallback: any;
|
|
45
60
|
mouseDragCallback: any;
|
|
61
|
+
_throttledCalculateCachedStats: any;
|
|
46
62
|
editData: {
|
|
47
63
|
annotation: LivewireContourAnnotation;
|
|
48
64
|
viewportIdsToRender: Array<string>;
|
|
49
65
|
handleIndex?: number;
|
|
66
|
+
movingTextBox?: boolean;
|
|
50
67
|
newAnnotation?: boolean;
|
|
51
68
|
hasMoved?: boolean;
|
|
52
69
|
lastCanvasPoint?: Types.Point2;
|
|
@@ -68,6 +85,8 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
68
85
|
defaultToolProps: ToolProps = {
|
|
69
86
|
supportedInteractionTypes: ['Mouse', 'Touch'],
|
|
70
87
|
configuration: {
|
|
88
|
+
getTextLines: defaultGetTextLines,
|
|
89
|
+
calculateStats: true,
|
|
71
90
|
preventHandleOutsideImage: false,
|
|
72
91
|
/**
|
|
73
92
|
* Specify which modifier key is used to add a hole to a contour. The
|
|
@@ -135,6 +154,11 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
135
154
|
}
|
|
136
155
|
) {
|
|
137
156
|
super(toolProps, defaultToolProps);
|
|
157
|
+
this._throttledCalculateCachedStats = throttle(
|
|
158
|
+
this._calculateCachedStats,
|
|
159
|
+
100,
|
|
160
|
+
{ trailing: true }
|
|
161
|
+
);
|
|
138
162
|
}
|
|
139
163
|
|
|
140
164
|
protected setupBaseEditData(
|
|
@@ -365,6 +389,7 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
365
389
|
this.editData = {
|
|
366
390
|
annotation,
|
|
367
391
|
viewportIdsToRender,
|
|
392
|
+
movingTextBox: false,
|
|
368
393
|
};
|
|
369
394
|
|
|
370
395
|
const enabledElement = getEnabledElement(element);
|
|
@@ -386,8 +411,16 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
386
411
|
|
|
387
412
|
annotation.highlighted = true;
|
|
388
413
|
|
|
389
|
-
|
|
390
|
-
|
|
414
|
+
let movingTextBox = false;
|
|
415
|
+
let handleIndex;
|
|
416
|
+
|
|
417
|
+
if ((handle as TextBoxHandle).worldPosition) {
|
|
418
|
+
movingTextBox = true;
|
|
419
|
+
} else {
|
|
420
|
+
const { points } = data.handles;
|
|
421
|
+
|
|
422
|
+
handleIndex = points.findIndex((p) => p === handle);
|
|
423
|
+
}
|
|
391
424
|
|
|
392
425
|
// Find viewports to render on drag.
|
|
393
426
|
const viewportIdsToRender = getViewportIdsWithToolToRender(
|
|
@@ -399,6 +432,7 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
399
432
|
annotation,
|
|
400
433
|
viewportIdsToRender,
|
|
401
434
|
handleIndex,
|
|
435
|
+
movingTextBox,
|
|
402
436
|
};
|
|
403
437
|
this._activateModify(element);
|
|
404
438
|
|
|
@@ -719,6 +753,7 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
719
753
|
|
|
720
754
|
annotation.invalidated = true;
|
|
721
755
|
editData.hasMoved = true;
|
|
756
|
+
editData.closed = true;
|
|
722
757
|
}
|
|
723
758
|
|
|
724
759
|
private _dragCallback = (evt: EventTypes.InteractionEventType): void => {
|
|
@@ -726,10 +761,25 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
726
761
|
const eventDetail = evt.detail;
|
|
727
762
|
const { element } = eventDetail;
|
|
728
763
|
|
|
729
|
-
const { annotation, viewportIdsToRender, handleIndex } =
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
764
|
+
const { annotation, viewportIdsToRender, handleIndex, movingTextBox } =
|
|
765
|
+
this.editData;
|
|
766
|
+
const { data } = annotation;
|
|
767
|
+
|
|
768
|
+
if (movingTextBox) {
|
|
769
|
+
// Drag mode - moving text box
|
|
770
|
+
const { deltaPoints } = eventDetail as EventTypes.MouseDragEventDetail;
|
|
771
|
+
const worldPosDelta = deltaPoints.world;
|
|
772
|
+
|
|
773
|
+
const { textBox } = data.handles;
|
|
774
|
+
const { worldPosition } = textBox;
|
|
775
|
+
|
|
776
|
+
worldPosition[0] += worldPosDelta[0];
|
|
777
|
+
worldPosition[1] += worldPosDelta[1];
|
|
778
|
+
worldPosition[2] += worldPosDelta[2];
|
|
779
|
+
|
|
780
|
+
textBox.hasMoved = true;
|
|
781
|
+
} else if (handleIndex === undefined) {
|
|
782
|
+
console.warn('Drag annotation not implemented');
|
|
733
783
|
} else {
|
|
734
784
|
// Move mode - after double click, and mouse move to draw
|
|
735
785
|
const { currentPoints } = eventDetail;
|
|
@@ -737,6 +787,8 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
737
787
|
this.editHandle(worldPos, element, annotation, handleIndex);
|
|
738
788
|
}
|
|
739
789
|
|
|
790
|
+
this.editData.hasMoved = true;
|
|
791
|
+
|
|
740
792
|
const enabledElement = getEnabledElement(element);
|
|
741
793
|
const { renderingEngine } = enabledElement;
|
|
742
794
|
|
|
@@ -879,10 +931,16 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
879
931
|
annotationStyle: Record<string, any>;
|
|
880
932
|
svgDrawingHelper: SVGDrawingHelper;
|
|
881
933
|
}): boolean {
|
|
882
|
-
const {
|
|
883
|
-
|
|
934
|
+
const {
|
|
935
|
+
annotation,
|
|
936
|
+
enabledElement,
|
|
937
|
+
svgDrawingHelper,
|
|
938
|
+
annotationStyle,
|
|
939
|
+
targetId,
|
|
940
|
+
} = renderContext;
|
|
884
941
|
|
|
885
942
|
const { viewport } = enabledElement;
|
|
943
|
+
const { element } = viewport;
|
|
886
944
|
const { worldToCanvas } = viewport;
|
|
887
945
|
const { annotationUID, data, highlighted } = annotation;
|
|
888
946
|
const { handles } = data;
|
|
@@ -916,9 +974,201 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
916
974
|
// Let the base class render the contour
|
|
917
975
|
super.renderAnnotationInstance(renderContext);
|
|
918
976
|
|
|
977
|
+
if (
|
|
978
|
+
!data.cachedStats[targetId] ||
|
|
979
|
+
data.cachedStats[targetId].areaUnit == null
|
|
980
|
+
) {
|
|
981
|
+
data.cachedStats[targetId] = {
|
|
982
|
+
Modality: null,
|
|
983
|
+
area: null,
|
|
984
|
+
areaUnit: null,
|
|
985
|
+
};
|
|
986
|
+
|
|
987
|
+
this._calculateCachedStats(annotation, element);
|
|
988
|
+
} else if (annotation.invalidated) {
|
|
989
|
+
this._throttledCalculateCachedStats(annotation, element);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
this._renderStats(
|
|
993
|
+
annotation,
|
|
994
|
+
viewport,
|
|
995
|
+
svgDrawingHelper,
|
|
996
|
+
annotationStyle.textbox
|
|
997
|
+
);
|
|
998
|
+
|
|
919
999
|
return true;
|
|
920
1000
|
}
|
|
921
1001
|
|
|
1002
|
+
private _calculateCachedStats = (
|
|
1003
|
+
annotation: LivewireContourAnnotation,
|
|
1004
|
+
element: HTMLDivElement
|
|
1005
|
+
) => {
|
|
1006
|
+
if (!this.configuration.calculateStats) {
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
const data = annotation.data;
|
|
1010
|
+
|
|
1011
|
+
if (!data.contour.closed) {
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
const enabledElement = getEnabledElement(element);
|
|
1016
|
+
const { viewport, renderingEngine } = enabledElement;
|
|
1017
|
+
const { cachedStats } = data;
|
|
1018
|
+
const { polyline: points } = data.contour;
|
|
1019
|
+
const targetIds = Object.keys(cachedStats);
|
|
1020
|
+
|
|
1021
|
+
for (let i = 0; i < targetIds.length; i++) {
|
|
1022
|
+
const targetId = targetIds[i];
|
|
1023
|
+
const image = this.getTargetIdImage(targetId, renderingEngine);
|
|
1024
|
+
|
|
1025
|
+
if (!image) {
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
const { metadata } = image;
|
|
1030
|
+
const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
|
|
1031
|
+
|
|
1032
|
+
const canvasPoint = canvasCoordinates[0];
|
|
1033
|
+
const originalWorldPoint = viewport.canvasToWorld(canvasPoint);
|
|
1034
|
+
const deltaXPoint = viewport.canvasToWorld([
|
|
1035
|
+
canvasPoint[0] + 1,
|
|
1036
|
+
canvasPoint[1],
|
|
1037
|
+
]);
|
|
1038
|
+
const deltaYPoint = viewport.canvasToWorld([
|
|
1039
|
+
canvasPoint[0],
|
|
1040
|
+
canvasPoint[1] + 1,
|
|
1041
|
+
]);
|
|
1042
|
+
|
|
1043
|
+
const deltaInX = vec3.distance(originalWorldPoint, deltaXPoint);
|
|
1044
|
+
const deltaInY = vec3.distance(originalWorldPoint, deltaYPoint);
|
|
1045
|
+
|
|
1046
|
+
const { imageData } = image;
|
|
1047
|
+
const { scale, areaUnits } = getCalibratedLengthUnitsAndScale(
|
|
1048
|
+
image,
|
|
1049
|
+
() => {
|
|
1050
|
+
const {
|
|
1051
|
+
maxX: canvasMaxX,
|
|
1052
|
+
maxY: canvasMaxY,
|
|
1053
|
+
minX: canvasMinX,
|
|
1054
|
+
minY: canvasMinY,
|
|
1055
|
+
} = math.polyline.getAABB(canvasCoordinates);
|
|
1056
|
+
|
|
1057
|
+
const topLeftBBWorld = viewport.canvasToWorld([
|
|
1058
|
+
canvasMinX,
|
|
1059
|
+
canvasMinY,
|
|
1060
|
+
]);
|
|
1061
|
+
|
|
1062
|
+
const topLeftBBIndex = utilities.transformWorldToIndex(
|
|
1063
|
+
imageData,
|
|
1064
|
+
topLeftBBWorld
|
|
1065
|
+
);
|
|
1066
|
+
|
|
1067
|
+
const bottomRightBBWorld = viewport.canvasToWorld([
|
|
1068
|
+
canvasMaxX,
|
|
1069
|
+
canvasMaxY,
|
|
1070
|
+
]);
|
|
1071
|
+
|
|
1072
|
+
const bottomRightBBIndex = utilities.transformWorldToIndex(
|
|
1073
|
+
imageData,
|
|
1074
|
+
bottomRightBBWorld
|
|
1075
|
+
);
|
|
1076
|
+
|
|
1077
|
+
return [topLeftBBIndex, bottomRightBBIndex];
|
|
1078
|
+
}
|
|
1079
|
+
);
|
|
1080
|
+
let area = math.polyline.getArea(canvasCoordinates) / scale / scale;
|
|
1081
|
+
|
|
1082
|
+
// Convert from canvas_pixels ^2 to mm^2
|
|
1083
|
+
area *= deltaInX * deltaInY;
|
|
1084
|
+
|
|
1085
|
+
cachedStats[targetId] = {
|
|
1086
|
+
Modality: metadata.Modality,
|
|
1087
|
+
area,
|
|
1088
|
+
areaUnit: areaUnits,
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
this.triggerAnnotationModified(
|
|
1093
|
+
annotation,
|
|
1094
|
+
enabledElement,
|
|
1095
|
+
ChangeTypes.StatsUpdated
|
|
1096
|
+
);
|
|
1097
|
+
|
|
1098
|
+
return cachedStats;
|
|
1099
|
+
};
|
|
1100
|
+
|
|
1101
|
+
private _renderStats = (
|
|
1102
|
+
annotation,
|
|
1103
|
+
viewport,
|
|
1104
|
+
svgDrawingHelper,
|
|
1105
|
+
textboxStyle
|
|
1106
|
+
) => {
|
|
1107
|
+
const data = annotation.data;
|
|
1108
|
+
const targetId = this.getTargetId(viewport);
|
|
1109
|
+
|
|
1110
|
+
if (!data.contour.closed || !textboxStyle.visibility) {
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
const textLines = this.configuration.getTextLines(data, targetId);
|
|
1115
|
+
if (!textLines || textLines.length === 0) {
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
const canvasCoordinates = data.handles.points.map((p) =>
|
|
1120
|
+
viewport.worldToCanvas(p)
|
|
1121
|
+
);
|
|
1122
|
+
if (!data.handles.textBox.hasMoved) {
|
|
1123
|
+
const canvasTextBoxCoords = getTextBoxCoordsCanvas(canvasCoordinates);
|
|
1124
|
+
|
|
1125
|
+
data.handles.textBox.worldPosition =
|
|
1126
|
+
viewport.canvasToWorld(canvasTextBoxCoords);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
const textBoxPosition = viewport.worldToCanvas(
|
|
1130
|
+
data.handles.textBox.worldPosition
|
|
1131
|
+
);
|
|
1132
|
+
|
|
1133
|
+
const textBoxUID = 'textBox';
|
|
1134
|
+
const boundingBox = drawLinkedTextBoxSvg(
|
|
1135
|
+
svgDrawingHelper,
|
|
1136
|
+
annotation.annotationUID ?? '',
|
|
1137
|
+
textBoxUID,
|
|
1138
|
+
textLines,
|
|
1139
|
+
textBoxPosition,
|
|
1140
|
+
canvasCoordinates,
|
|
1141
|
+
{},
|
|
1142
|
+
textboxStyle
|
|
1143
|
+
);
|
|
1144
|
+
|
|
1145
|
+
const { x: left, y: top, width, height } = boundingBox;
|
|
1146
|
+
|
|
1147
|
+
data.handles.textBox.worldBoundingBox = {
|
|
1148
|
+
topLeft: viewport.canvasToWorld([left, top]),
|
|
1149
|
+
topRight: viewport.canvasToWorld([left + width, top]),
|
|
1150
|
+
bottomLeft: viewport.canvasToWorld([left, top + height]),
|
|
1151
|
+
bottomRight: viewport.canvasToWorld([left + width, top + height]),
|
|
1152
|
+
};
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1155
|
+
triggerAnnotationModified = (
|
|
1156
|
+
annotation: LivewireContourAnnotation,
|
|
1157
|
+
enabledElement: Types.IEnabledElement,
|
|
1158
|
+
changeType = ChangeTypes.StatsUpdated
|
|
1159
|
+
): void => {
|
|
1160
|
+
const { viewportId, renderingEngineId } = enabledElement;
|
|
1161
|
+
const eventType = Events.ANNOTATION_MODIFIED;
|
|
1162
|
+
const eventDetail: AnnotationModifiedEventDetail = {
|
|
1163
|
+
annotation,
|
|
1164
|
+
viewportId,
|
|
1165
|
+
renderingEngineId,
|
|
1166
|
+
changeType,
|
|
1167
|
+
};
|
|
1168
|
+
|
|
1169
|
+
triggerEvent(eventTarget, eventType, eventDetail);
|
|
1170
|
+
};
|
|
1171
|
+
|
|
922
1172
|
protected updateAnnotation(livewirePath: LivewirePath) {
|
|
923
1173
|
if (!this.editData || !livewirePath) {
|
|
924
1174
|
return;
|
|
@@ -954,3 +1204,17 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
954
1204
|
|
|
955
1205
|
LivewireContourTool.toolName = 'LivewireContour';
|
|
956
1206
|
export default LivewireContourTool;
|
|
1207
|
+
|
|
1208
|
+
function defaultGetTextLines(data, targetId): string[] {
|
|
1209
|
+
const cachedVolumeStats = data.cachedStats[targetId];
|
|
1210
|
+
const { area, areaUnit } = cachedVolumeStats;
|
|
1211
|
+
const textLines: string[] = [];
|
|
1212
|
+
|
|
1213
|
+
if (area) {
|
|
1214
|
+
const areaLine = `Area: ${roundNumber(area)} ${areaUnit}`;
|
|
1215
|
+
|
|
1216
|
+
textLines.push(areaLine);
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
return textLines;
|
|
1220
|
+
}
|