1 | {"version":3,"sources":["webpack://cornerstoneTools/webpack/universalModuleDefinition","webpack://cornerstoneTools/webpack/bootstrap","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/classCallCheck.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/createClass.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/possibleConstructorReturn.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/getPrototypeOf.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/inherits.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/assertThisInitialized.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/toConsumableArray.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/slicedToArray.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/typeof.js","webpack://cornerstoneTools/./util/debugLib/index.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/defineProperty.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/regenerator/index.js","webpack://cornerstoneTools/./util/debugLib/common.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/asyncToGenerator.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/setPrototypeOf.js","webpack://cornerstoneTools/../node_modules/process/browser.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/arrayWithoutHoles.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/iterableToArray.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/nonIterableSpread.js","webpack://cornerstoneTools/../node_modules/ms/index.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/arrayWithHoles.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/iterableToArrayLimit.js","webpack://cornerstoneTools/../node_modules/@babel/runtime/helpers/nonIterableRest.js","webpack://cornerstoneTools/../node_modules/regenerator-runtime/runtime-module.js","webpack://cornerstoneTools/../node_modules/regenerator-runtime/runtime.js","webpack://cornerstoneTools/./externalModules.js","webpack://cornerstoneTools/./events.js","webpack://cornerstoneTools/./util/triggerEvent.js","webpack://cornerstoneTools/./store/modules/segmentationModule/getElement.js","webpack://cornerstoneTools/./store/modules/segmentationModule/addLabelmap3D.js","webpack://cornerstoneTools/./stateManagement/imageIdSpecificStateManager.js","webpack://cornerstoneTools/./stateManagement/toolState.js","webpack://cornerstoneTools/./util/logger.js","webpack://cornerstoneTools/./store/modules/segmentationModule/state.js","webpack://cornerstoneTools/./store/modules/segmentationModule/metadata.js","webpack://cornerstoneTools/./store/modules/segmentationModule/activeSegmentIndex.js","webpack://cornerstoneTools/./store/modules/segmentationModule/segmentVisibility.js","webpack://cornerstoneTools/./store/modules/segmentationModule/getLabelmaps3D.js","webpack://cornerstoneTools/./store/modules/segmentationModule/getLabelmapBuffers.js","webpack://cornerstoneTools/./store/modules/segmentationModule/getSegmentsOnPixeldata.js","webpack://cornerstoneTools/./util/segmentation/eraseIfSegmentIndex.js","webpack://cornerstoneTools/./util/segmentation/drawBrush.js","webpack://cornerstoneTools/./util/segmentation/eraseOutsideBoundingBox.js","webpack://cornerstoneTools/./util/segmentation/isSameSegment.js","webpack://cornerstoneTools/./util/segmentation/eraseShape.js","webpack://cornerstoneTools/./util/segmentation/fillOutsideBoundingBox.js","webpack://cornerstoneTools/./util/segmentation/fillShape.js","webpack://cornerstoneTools/./util/segmentation/floodFill.js","webpack://cornerstoneTools/./util/getCircleCoords.js","webpack://cornerstoneTools/./util/segmentation/getBoundingBoxAroundCircle.js","webpack://cornerstoneTools/./util/segmentation/getBoundingBoxAroundPolygon.js","webpack://cornerstoneTools/./util/segmentation/getCircle.js","webpack://cornerstoneTools/./util/segmentation/getPixelPathBetweenPixels.js","webpack://cornerstoneTools/./util/segmentation/triggerLabelmapModifiedEvent.js","webpack://cornerstoneTools/./util/segmentation/getDiffBetweenPixelData.js","webpack://cornerstoneTools/./store/modules/segmentationModule/setLabelmap3D.js","webpack://cornerstoneTools/./store/modules/segmentationModule/getLabelmapStats.js","webpack://cornerstoneTools/./store/modules/segmentationModule/addLabelmap2D.js","webpack://cornerstoneTools/./store/modules/segmentationModule/getLabelmap2D.js","webpack://cornerstoneTools/./util/isPointInImage.js","webpack://cornerstoneTools/./store/modules/segmentationModule/getSegmentOfActiveLabelmapAtEvent.js","webpack://cornerstoneTools/./store/modules/segmentationModule/colorLUT.js","webpack://cornerstoneTools/./store/modules/segmentationModule/getBrushColor.js","webpack://cornerstoneTools/./store/modules/segmentationModule/defaultConfiguration.js","webpack://cornerstoneTools/./store/modules/segmentationModule/history.js","webpack://cornerstoneTools/./store/modules/segmentationModule/index.js","webpack://cornerstoneTools/./store/modules/segmentationModule/activeLabelmapIndex.js","webpack://cornerstoneTools/./store/modules/segmentationModule/deleteSegment.js","webpack://cornerstoneTools/./store/modules/segmentationModule/setRadius.js","webpack://cornerstoneTools/./store/modules/cursorModule.js","webpack://cornerstoneTools/./store/modules/globalConfigurationModule.js","webpack://cornerstoneTools/./store/index.js","webpack://cornerstoneTools/./store/getToolForElement.js","webpack://cornerstoneTools/./store/setToolCursor.js","webpack://cornerstoneTools/./store/setToolMode.js","webpack://cornerstoneTools/./mixins/activeOrDisabledBinaryTool.js","webpack://cornerstoneTools/./mixins/enabledOrDisabledBinaryTool.js","webpack://cornerstoneTools/./drawing/draw.js","webpack://cornerstoneTools/./stateManagement/toolStyle.js","webpack://cornerstoneTools/./drawing/path.js","webpack://cornerstoneTools/./drawing/drawLine.js","webpack://cornerstoneTools/./drawing/drawJoinedLines.js","webpack://cornerstoneTools/./drawing/drawArrow.js","webpack://cornerstoneTools/./drawing/drawCircle.js","webpack://cornerstoneTools/./util/convertToVector3.js","webpack://cornerstoneTools/./util/pointProjector.js","webpack://cornerstoneTools/./drawing/drawEllipse.js","webpack://cornerstoneTools/./stateManagement/toolColors.js","webpack://cornerstoneTools/./drawing/drawHandles.js","webpack://cornerstoneTools/./drawing/drawLines.js","webpack://cornerstoneTools/./drawing/drawLink.js","webpack://cornerstoneTools/./stateManagement/textStyle.js","webpack://cornerstoneTools/./drawing/fillTextLines.js","webpack://cornerstoneTools/./drawing/fillBox.js","webpack://cornerstoneTools/./drawing/drawTextBox.js","webpack://cornerstoneTools/./drawing/drawLinkedTextBox.js","webpack://cornerstoneTools/./drawing/drawRect.js","webpack://cornerstoneTools/./drawing/getNewContext.js","webpack://cornerstoneTools/./util/getDefault.js","webpack://cornerstoneTools/./drawing/setShadow.js","webpack://cornerstoneTools/./drawing/transformCanvasContext.js","webpack://cornerstoneTools/./drawing/resetCanvasContextTransform.js","webpack://cornerstoneTools/./util/isEmptyObject.js","webpack://cornerstoneTools/./mixins/segmentation/circleSegmentationMixin.js","webpack://cornerstoneTools/./mixins/segmentation/freehandSegmentationMixin.js","webpack://cornerstoneTools/./mixins/segmentation/polylineSegmentationMixin.js","webpack://cornerstoneTools/./mixins/segmentation/rectangleSegmentationMixin.js","webpack://cornerstoneTools/./mixins/segmentation/renderBrushMixin.js","webpack://cornerstoneTools/./mixins/index.js","webpack://cornerstoneTools/./util/deepmerge.js","webpack://cornerstoneTools/./tools/base/BaseTool.js","webpack://cornerstoneTools/./util/pointInsideBoundingBox.js","webpack://cornerstoneTools/./manipulators/getHandleNearImagePoint.js","webpack://cornerstoneTools/./manipulators/handleActivator.js","webpack://cornerstoneTools/./manipulators/anyHandlesOutsideImage.js","webpack://cornerstoneTools/./util/clip.js","webpack://cornerstoneTools/./store/getActiveToolsForElement.js","webpack://cornerstoneTools/./store/isToolActiveForElement.js","webpack://cornerstoneTools/./tools/base/BaseBrushTool.js","webpack://cornerstoneTools/./store/filterToolsUsableWithMultiPartTools.js","webpack://cornerstoneTools/./util/getActiveTool.js","webpack://cornerstoneTools/./manipulators/moveAllHandles.js","webpack://cornerstoneTools/./manipulators/moveHandle.js","webpack://cornerstoneTools/./manipulators/moveNewHandle.js","webpack://cornerstoneTools/./util/findAndMoveHelpers.js","webpack://cornerstoneTools/./tools/base/BaseAnnotationTool.js","webpack://cornerstoneTools/./util/lineSegDistance.js","webpack://cornerstoneTools/./util/roundToDecimal.js","webpack://cornerstoneTools/./tools/cursors/MouseCursor.js","webpack://cornerstoneTools/./tools/cursors/index.js","webpack://cornerstoneTools/./util/getPixelSpacing.js","webpack://cornerstoneTools/./util/isObject.js","webpack://cornerstoneTools/./util/debounce.js","webpack://cornerstoneTools/./util/throttle.js","webpack://cornerstoneTools/./tools/annotation/AngleTool.js","webpack://cornerstoneTools/./tools/annotation/ArrowAnnotateTool.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/createNewMeasurement.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/pointNearTool.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/utils/getLineVector.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/renderToolData.js","webpack://cornerstoneTools/./stateManagement/toolCoordinates.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/utils/updatePerpendicularLineHandles.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/addNewMeasurement.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/mouseMoveCallback.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/handleSelectedCallback.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/utils/getDistanceWithPixelSpacing.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/getBaseData.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/moveLongLine/moveLongLine.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/moveLongLine/updatePerpendicularLine.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/movePerpendicularLine/isPerpendicularEndFixed.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/movePerpendicularLine/getDirectionMultiplier.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/movePerpendicularLine/updatePerpendicularLine.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/movePerpendicularLine/getMovingPoint.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/movePerpendicularLine/movePerpendicularLine.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/movePerpendicularLine/lineHasLength.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/movePerpendicularLine/getHelperLine.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/setHandlesPosition.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/invertHandles.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/handleSelectedMouseCallback.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/moveHandle.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/moveHandle/touchMoveHandle.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/handleSelectedTouchCallback.js","webpack://cornerstoneTools/./tools/annotation/BidirectionalTool.js","webpack://cornerstoneTools/./tools/annotation/bidirectionalTool/utils/calculateLongestAndShortestDiameters.js","webpack://cornerstoneTools/./util/calculateSUV.js","webpack://cornerstoneTools/./util/ellipse/pointInEllipse.js","webpack://cornerstoneTools/./util/ellipse/calculateEllipseStatistics.js","webpack://cornerstoneTools/./util/ellipse/index.js","webpack://cornerstoneTools/./util/getROITextBoxCoords.js","webpack://cornerstoneTools/./util/numbersWithCommas.js","webpack://cornerstoneTools/./tools/annotation/CircleRoiTool.js","webpack://cornerstoneTools/./tools/annotation/CobbAngleTool.js","webpack://cornerstoneTools/./tools/annotation/EllipticalRoiTool.js","webpack://cornerstoneTools/./util/freehand/pointInFreehand.js","webpack://cornerstoneTools/./util/freehand/calculateFreehandStatistics.js","webpack://cornerstoneTools/./util/freehand/ClickedLineData.js","webpack://cornerstoneTools/./util/freehand/FreehandHandleData.js","webpack://cornerstoneTools/./util/freehand/freehandIntersect.js","webpack://cornerstoneTools/./util/freehand/FreehandLineFinder.js","webpack://cornerstoneTools/./util/freehand/addLine.js","webpack://cornerstoneTools/./util/freehand/insertOrDelete.js","webpack://cornerstoneTools/./util/freehand/index.js","webpack://cornerstoneTools/./util/freehand/freehandArea.js","webpack://cornerstoneTools/./tools/annotation/FreehandRoiTool.js","webpack://cornerstoneTools/./tools/annotation/LengthTool.js","webpack://cornerstoneTools/./util/getRGBPixels.js","webpack://cornerstoneTools/./tools/annotation/ProbeTool.js","webpack://cornerstoneTools/./tools/annotation/RectangleRoiTool.js","webpack://cornerstoneTools/./tools/annotation/TextMarkerTool.js","webpack://cornerstoneTools/./tools/segmentation/BrushTool.js","webpack://cornerstoneTools/./tools/segmentation/SphericalBrushTool.js","webpack://cornerstoneTools/./tools/segmentation/strategies/correction.js","webpack://cornerstoneTools/./util/isPointInPolygon.js","webpack://cornerstoneTools/./tools/segmentation/strategies/eraseFreehand.js","webpack://cornerstoneTools/./tools/segmentation/strategies/eraseRectangle.js","webpack://cornerstoneTools/./tools/segmentation/strategies/fillFreehand.js","webpack://cornerstoneTools/./tools/segmentation/strategies/fillRectangle.js","webpack://cornerstoneTools/./tools/segmentation/strategies/fillCircle.js","webpack://cornerstoneTools/./tools/segmentation/strategies/eraseCircle.js","webpack://cornerstoneTools/./tools/segmentation/FreehandScissorsTool.js","webpack://cornerstoneTools/./tools/segmentation/RectangleScissorsTool.js","webpack://cornerstoneTools/./tools/segmentation/CircleScissorsTool.js","webpack://cornerstoneTools/./tools/segmentation/CorrectionScissorsTool.js","webpack://cornerstoneTools/./stateManagement/loadHandlerManager.js","webpack://cornerstoneTools/./toolOptions.js","webpack://cornerstoneTools/./tools/CrosshairsTool.js","webpack://cornerstoneTools/./tools/DoubleTapFitToWindowTool.js","webpack://cornerstoneTools/./tools/DragProbeTool.js","webpack://cornerstoneTools/./tools/EraserTool.js","webpack://cornerstoneTools/./tools/FreehandRoiSculptorTool.js","webpack://cornerstoneTools/./tools/MagnifyTool.js","webpack://cornerstoneTools/./orientation/index.js","webpack://cornerstoneTools/./orientation/getOrientationString.js","webpack://cornerstoneTools/./orientation/invertOrientationString.js","webpack://cornerstoneTools/./tools/OrientationMarkersTool.js","webpack://cornerstoneTools/./tools/PanMultiTouchTool.js","webpack://cornerstoneTools/./tools/PanTool.js","webpack://cornerstoneTools/./tools/referenceLines/renderActiveReferenceLine.js","webpack://cornerstoneTools/./tools/referenceLines/calculateReferenceLine.js","webpack://cornerstoneTools/./util/wait.js","webpack://cornerstoneTools/./tools/ReferenceLinesTool.js","webpack://cornerstoneTools/./util/angleBetweenPoints.js","webpack://cornerstoneTools/./tools/RotateTool.js","webpack://cornerstoneTools/./util/getMaxSimultaneousRequests.js","webpack://cornerstoneTools/./tools/RotateTouchTool.js","webpack://cornerstoneTools/./tools/ScaleOverlayTool.js","webpack://cornerstoneTools/./requestPool/requestPoolManager.js","webpack://cornerstoneTools/./util/scrollToIndex.js","webpack://cornerstoneTools/./util/scroll.js","webpack://cornerstoneTools/./tools/StackScrollMouseWheelTool.js","webpack://cornerstoneTools/./tools/StackScrollMultiTouchTool.js","webpack://cornerstoneTools/./tools/StackScrollTool.js","webpack://cornerstoneTools/./util/getLuminance.js","webpack://cornerstoneTools/./tools/WwwcRegionTool.js","webpack://cornerstoneTools/./tools/WwwcTool.js","webpack://cornerstoneTools/./util/zoom/changeViewportScale.js","webpack://cornerstoneTools/./util/zoom/index.js","webpack://cornerstoneTools/./util/zoom/correctShift.js","webpack://cornerstoneTools/./tools/ZoomMouseWheelTool.js","webpack://cornerstoneTools/./tools/ZoomTool.js","webpack://cornerstoneTools/./tools/ZoomTouchPinchTool.js","webpack://cornerstoneTools/./util/copyPoints.js","webpack://cornerstoneTools/./eventListeners/mouseEventListeners.js","webpack://cornerstoneTools/./eventListeners/internals/normalizeWheel.js","webpack://cornerstoneTools/./eventListeners/wheelEventListener.js","webpack://cornerstoneTools/./eventListeners/preventGhostClick.js","webpack://cornerstoneTools/./eventListeners/touchEventListeners.js","webpack://cornerstoneTools/./eventListeners/internals/renderSegmentationFill.js","webpack://cornerstoneTools/./eventListeners/internals/renderSegmentationOutline.js","webpack://cornerstoneTools/./eventListeners/internals/renderSegmentation.js","webpack://cornerstoneTools/./eventListeners/onImageRenderedBrushEventHandler.js","webpack://cornerstoneTools/./eventDispatchers/imageRenderedEventDispatcher.js","webpack://cornerstoneTools/./eventDispatchers/shared/customCallbackHandler.js","webpack://cornerstoneTools/./store/getToolsWithMoveableHandles.js","webpack://cornerstoneTools/./store/getInteractiveToolsForElement.js","webpack://cornerstoneTools/./store/getToolsWithDataForElement.js","webpack://cornerstoneTools/./eventDispatchers/mouseEventHandlers/mouseDown.js","webpack://cornerstoneTools/./eventDispatchers/mouseEventHandlers/addNewMeasurement.js","webpack://cornerstoneTools/./eventDispatchers/mouseEventHandlers/mouseDownActivate.js","webpack://cornerstoneTools/./eventDispatchers/mouseEventHandlers/mouseDrag.js","webpack://cornerstoneTools/./eventDispatchers/mouseEventHandlers/mouseMove.js","webpack://cornerstoneTools/./eventDispatchers/mouseEventHandlers/index.js","webpack://cornerstoneTools/./eventDispatchers/mouseToolEventDispatcher.js","webpack://cornerstoneTools/./eventDispatchers/newImageEventDispatcher.js","webpack://cornerstoneTools/./eventDispatchers/touchEventHandlers/multiTouchDrag.js","webpack://cornerstoneTools/./eventDispatchers/touchEventHandlers/addNewMeasurement.js","webpack://cornerstoneTools/./eventDispatchers/touchEventHandlers/touchStartActive.js","webpack://cornerstoneTools/./eventDispatchers/touchEventHandlers/shared/deactivateAllToolInstances.js","webpack://cornerstoneTools/./eventDispatchers/touchEventHandlers/tap.js","webpack://cornerstoneTools/./eventDispatchers/touchEventHandlers/touchStart.js","webpack://cornerstoneTools/./eventDispatchers/touchEventHandlers/index.js","webpack://cornerstoneTools/./eventDispatchers/touchToolEventDispatcher.js","webpack://cornerstoneTools/./store/addTool.js","webpack://cornerstoneTools/./store/internals/addEnabledElement.js","webpack://cornerstoneTools/./store/internals/removeEnabledElement.js","webpack://cornerstoneTools/./eventListeners/windowResizeHandler.js","webpack://cornerstoneTools/./init.js","webpack://cornerstoneTools/./stackTools/stackPrefetch.js","webpack://cornerstoneTools/./stackTools/fusionRenderer.js","webpack://cornerstoneTools/./stackTools/stackRenderers.js","webpack://cornerstoneTools/./stackTools/playClip.js","webpack://cornerstoneTools/./store/removeTool.js","webpack://cornerstoneTools/./store/setToolOptions.js","webpack://cornerstoneTools/./stateManagement/stackSpecificStateManager.js","webpack://cornerstoneTools/./stateManagement/frameOfReferenceStateManager.js","webpack://cornerstoneTools/./util/SaveAs.js","webpack://cornerstoneTools/./thirdParty/registerModule.js","webpack://cornerstoneTools/./util/setContextToDisplayFontSize.js","webpack://cornerstoneTools/./lib.js","webpack://cornerstoneTools/./drawing/fillOutsideRect.js","webpack://cornerstoneTools/./util/makeUnselectable.js","webpack://cornerstoneTools/./util/getKeyPressData.js","webpack://cornerstoneTools/./thirdParty/registerMixin.js","webpack://cornerstoneTools/./thirdParty/registerItem.js","webpack://cornerstoneTools/./thirdParty/register.js","webpack://cornerstoneTools/./thirdParty/registerSome.js","webpack://cornerstoneTools/./synchronization/wwwcSynchronizer.js","webpack://cornerstoneTools/./synchronization/updateImageSynchronizer.js","webpack://cornerstoneTools/./synchronization/Synchronizer.js","webpack://cornerstoneTools/./synchronization/stackScrollSynchronizer.js","webpack://cornerstoneTools/./synchronization/stackImagePositionSynchronizer.js","webpack://cornerstoneTools/./synchronization/stackImagePositionOffsetSynchronizer.js","webpack://cornerstoneTools/./synchronization/stackImageIndexSynchronizer.js","webpack://cornerstoneTools/./synchronization/panZoomSynchronizer.js","webpack://cornerstoneTools/./importInternal.js","webpack://cornerstoneTools/./index.js","webpack://cornerstoneTools/./version.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","instance","Constructor","TypeError","_defineProperties","target","props","length","descriptor","configurable","writable","protoProps","staticProps","_typeof","assertThisInitialized","self","_getPrototypeOf","setPrototypeOf","getPrototypeOf","__proto__","subClass","superClass","constructor","ReferenceError","arrayWithoutHoles","iterableToArray","nonIterableSpread","arr","arrayWithHoles","iterableToArrayLimit","nonIterableRest","_typeof2","obj","iterator","debugLib","formatArgs","args","this","useColors","namespace","humanize","diff","color","splice","index","lastC","replace","match","save","namespaces","storage","setItem","removeItem","error","load","getItem","process","env","DEBUG","type","__nwjs","navigator","userAgent","toLowerCase","document","documentElement","style","WebkitAppearance","console","firebug","exception","table","parseInt","RegExp","$1","localStorage","localstorage","colors","log","debug","setupDebug","setup","formatters","j","v","JSON","stringify","message","selectColor","hash","charCodeAt","createDebug","Math","abs","prevTime","enabled","curr","Number","Date","ms","prev","coerce","unshift","format","formatter","val","apply","destroy","extend","init","instances","push","indexOf","delimiter","newDebug","toNamespace","regexp","toString","substring","default","Error","stack","disable","names","map","skips","join","enable","split","len","substr","test","require","keys","forEach","asyncGeneratorStep","gen","resolve","reject","_next","_throw","arg","info","done","Promise","then","fn","arguments","err","undefined","_setPrototypeOf","cachedSetTimeout","cachedClearTimeout","defaultSetTimout","defaultClearTimeout","runTimeout","fun","setTimeout","e","clearTimeout","currentQueue","queue","draining","queueIndex","cleanUpNextTick","concat","drainQueue","timeout","run","marker","runClearTimeout","Item","array","noop","nextTick","Array","title","browser","argv","version","versions","on","addListener","once","off","removeListener","removeAllListeners","emit","prependListener","prependOnceListener","listeners","binding","cwd","chdir","dir","umask","isArray","arr2","iter","from","h","w","y","plural","msAbs","isPlural","round","options","str","String","exec","parseFloat","parse","isNaN","long","fmtLong","fmtShort","_arr","_n","_d","_e","_s","_i","next","g","Function","hadRuntime","regeneratorRuntime","getOwnPropertyNames","oldRuntime","global","Op","hasOwn","$Symbol","iteratorSymbol","asyncIteratorSymbol","asyncIterator","toStringTagSymbol","inModule","runtime","wrap","GenStateSuspendedStart","GenStateSuspendedYield","GenStateExecuting","GenStateCompleted","ContinueSentinel","IteratorPrototype","getProto","NativeIteratorPrototype","values","Gp","GeneratorFunctionPrototype","Generator","GeneratorFunction","displayName","isGeneratorFunction","genFun","ctor","mark","awrap","__await","defineIteratorMethods","AsyncIterator","async","innerFn","outerFn","tryLocsList","result","reverse","pop","Context","reset","skipTempReset","sent","_sent","delegate","method","tryEntries","resetTryEntry","charAt","slice","stop","rootRecord","completion","rval","dispatchException","context","handle","loc","caught","record","entry","tryLoc","hasCatch","hasFinally","catchLoc","finallyLoc","abrupt","finallyEntry","complete","afterLoc","finish","thrown","delegateYield","iterable","resultName","nextLoc","protoGenerator","generator","_invoke","state","doneResult","delegateResult","maybeInvokeDelegate","tryCatch","makeInvokeMethod","previousPromise","callInvokeWithMethodAndArg","invoke","unwrapped","return","pushTryEntry","locs","iteratorMethod","cornerstone","cornerstoneMath","Hammer","cs","cm","EVENTS","MOUSE_DOWN","MOUSE_UP","MOUSE_DOWN_ACTIVATE","MOUSE_DRAG","MOUSE_MOVE","MOUSE_CLICK","MOUSE_DOUBLE_CLICK","MOUSE_WHEEL","TOUCH_START","TOUCH_START_ACTIVE","TOUCH_END","TOUCH_DRAG","TOUCH_DRAG_END","TOUCH_PINCH","TOUCH_ROTATE","TOUCH_PRESS","TAP","DOUBLE_TAP","MULTI_TOUCH_START","MULTI_TOUCH_START_ACTIVE","MULTI_TOUCH_DRAG","KEY_DOWN","KEY_UP","KEY_PRESS","MEASUREMENT_ADDED","MEASUREMENT_MODIFIED","MEASUREMENT_COMPLETED","MEASUREMENT_REMOVED","TOOL_DEACTIVATED","CLIP_STOPPED","STACK_SCROLL","STACK_PREFETCH_IMAGE_LOADED","STACK_PREFETCH_DONE","LABELMAP_MODIFIED","triggerEvent","el","event","detail","CustomEvent","cancelable","createEvent","initCustomEvent","dispatchEvent","_getElement","elementOrEnabledElementUID","HTMLElement","storeGetters","enabledElementByUID","addLabelmap3D","brushStackState","labelmapIndex","size","labelmaps3D","buffer","ArrayBuffer","labelmaps2D","metadata","activeSegmentIndex","colorLUTIndex","segmentsHidden","undo","redo","newImageIdSpecificToolStateManager","toolState","element","toolType","enabledElement","external","getEnabledElement","image","imageId","imageIdToolState","add","data","clear","saveImageIdToolState","restoreImageIdToolState","saveToolState","restoreToolState","savedToolState","globalImageIdSpecificToolStateManager","getElementToolStateManager","toolStateManager","addToolState","measurementData","getToolState","removeToolState","toolData","indexOfData","clearToolState","setElementToolStateManager","baseLogger","getLogger","scope","warn","series","colorLutTables","logger","_changeActiveSegmentIndex","increaseOrDecrease","configuration","getModule","firstImageId","imageIds","activeLabelmapIndex","labelmap3D","segmentsPerLabelmap","getLabelmaps3D","getElement","stackState","stackData","currentImageIdIndex","getLabelmap3D","getLabelmapBuffers","bytesPerVoxel","colorLUT","labelmapBuffers","getSegmentsOnPixelData","pixelData","Set","segmentsOnLabelmap","eraseIfSegmentIndex","pixelIndex","segmentIndex","drawBrushPixels","pointerArray","columns","shouldErase","getPixelIndex","x","point","spIndex","eraseOutsideBoundingBox","evt","operationData","topLeft","bottomRight","eventData","width","height","isSameSegment","eraseShape","pointInShape","insideOrOutside","xMin","yMin","xMax","yMax","eraseInsideShape","eraseOutsideShape","fillOutsideBoundingBox","fillShape","fillInsideShape","fillOutsideShape","seed","onFlood","onBoundary","equals","defaultEquals","diagonals","startNode","permutations","prunedPermutations","flooded","visits","bounds","currentArgs","flood","boundaries","job","getArgs","prevArgs","previousArgs","visited","markAsVisited","member","markAsFlooded","pushAdjacent","markAsBoundary","node","safely","perm","nextArgs","f","permute","filter","count","countNonZeroes","perms","permutation","string","pow","lpad","a","b","character","getCircleCoords","startHandle","endHandle","radius","distance","left","floor","min","top","getBoundingBoxAroundCircle","handles","imageWidth","imageHeight","circleCoordinates","start","end","max","getBoundingBoxAroundPolygon","vertices","Infinity","getCircle","rows","xCoord","yCoord","x0","y0","circleArray","oneOverRoot2","sqrt","DIRECTIONS","up","upRight","right","downRight","down","downLeft","upLeft","p1","p2","path","moveUpRight","moveUpLeft","moveDownRight","moveDownLeft","unitVector","unitVectorFromPtoP2","getIndexOfLargestInLengthThreeArray","dotProduct2D","largestIndex","triggerLabelmapModifiedEvent","getters","getDiffBetweenPixelData","previousPixelData","newPixelData","setLabelmap3DByFirstImageId","numberOfFrames","segmentsOnLabelmapArray","slicelengthInBytes","byteLength","sliceLengthInUint16","Uint16Array","some","segment","_getSliceThickness","images","imagePlanes","frameIndex","numberOfSlices","ipp","imagePositionPatient","distanceBetweenSlices","ippBelow","ippAbove","ipp1","ipp2","addLabelmap2D","imageIdIndex","sliceLength","byteOffset","isPointInImage","cols","setColorLUT","_checkColorLUTLength","_generateNewColorLUT","getColorLUT","labelmap3DOrColorLUTIndex","numberOfColors","rgbArr","getRGBAfromHSLA","getNextHue","getNextL","goldenAngle","hueValue","maxL","minL","incL","hue","alpha","defaultConfiguration","renderOutline","renderFill","shouldRenderInactiveLabelmaps","minRadius","maxRadius","fillAlpha","fillAlphaInactive","outlineAlpha","outlineAlphaInactive","outlineWidth","storeHistory","applyState","operations","replaceIndex","operation","diffI","onRegisterCallback","isSegmentVisible","labelmap2D","labelmap2DByImageIdIndex","labelmapStats","metadataProvider","metaData","sufficientMetadata","imagePlaneModule","_getImagePlanes","imagePromises","loadAndCacheImage","all","stats","voxelsPerFrame","rowPixelSpacing","columnPixelSpacing","includes","voxelInMM3","segmentationPixelData","imagePixelData","getPixelData","_getVoxelsPerFrameForSegment","volumeWeightedMean","volume","sum","volumeWeightedStDev","stdDevSum","mean","stdDev","_calculateLabelmapStats","segmentOfActiveLabelmapAtEvent","currentPoints","brushColor","drawing","activeLabelmapBuffer","colorForSegmentIndexColorLUT","setters","labelmap3DForElement","labelmap3DByFirstImageId","incrementActiveSegmentIndex","decrementActiveSegmentIndex","toggleSegmentVisibility","updateSegmentsOnLabelmap2D","deleteSegment","indexOfSegment","updateImage","colorLUTIndexForLabelmap3D","colorForSegmentIndexOfColorLUT","colorArray","newRadius","pushState","iconSize","viewBox","mousePoint","mousePointerGroupString","defaultOptions","newOptions","assign","mouseEnabled","touchEnabled","globalToolSyncEnabled","showSVGCursors","autoResizeViewports","globalTools","globalToolChangeHistory","enabledElements","tools","isToolLocked","activeMultiPartTool","mousePositionImage","clickProximity","touchProximity","handleRadius","deleteIfHandleOutsideImage","preventHandleOutsideImage","svgCursorUrl","mouseTools","tool","supportedInteractionTypes","touchTools","enabledElementUID","find","uuid","segmentation","cursor","globalConfiguration","moduleName","setToolCursor","svgCursor","cursorBlob","getIconWithPointerSVG","URL","createObjectURL","hideToolCursor","_clearStateAndSetCursor","cursorSeting","revokeObjectURL","setToolActiveForElement","toolName","interactionTypes","getToolForElement","interactionType","inputResolver","_inputResolvers","store","toolHasAnyActiveInteractionType","setToolPassiveForElement","_resolveInputConflicts","mouseButtonMask","hideDefaultCursor","resetToolCursor","_setToolCursorIfPrimary","setToolModeForElement","setToolActive","_trackGlobalToolModeChange","setToolDisabledForElement","setToolDisabled","setToolMode","setToolEnabledForElement","setToolEnabled","setToolPassive","changeEvent","newMask","oldMask","_getNormalizedOptions","reduce","acc","mergeOptions","_resolveGenericInputConflicts","interactionTypeFlag","activeToolWithActiveInteractionType","historyEvent","shift","globalTool","stringBindings","mouseButtonMasks","mask","touchPointers","_determineStringBindings","activeBindings","Mouse","activeToolWithMatchingMouseButtonMask","isMouseActive","MouseWheel","Touch","activeTouchTool","isTouchActive","activeMultiTouchToolWithOneTouchPointer","isMultiTouchActive","TouchPinch","TouchRotate","DoubleTap","MultiTouch","activeMultiTouchTool","passiveCallback","enabledCallback","activeCallback","restore","defaultWidth","activeWidth","toolStyle","setToolWidth","getToolWidth","setActiveWidth","getActiveWidth","lineWidth","fillStyle","lineDash","shouldDrawLines","beginPath","strokeStyle","setLineDash","fill","stroke","drawLine","coordSystem","pixelToCanvas","moveTo","lineTo","points","angle","atan2","cos","PI","sin","drawJoinedLines","center","arc","convertToVector3","arrayOrVector3","Vector3","projectPatientPointToImagePlane","patientPoint","imagePlane","rowCosines","columnCosines","clone","sub","dot","imagePointToPatientPoint","imagePoint","multiplyScalar","planePlaneIntersection","targetImagePlane","referenceImagePlane","targetRowCosines","targetColumnCosines","targetImagePositionPatient","referenceRowCosines","referenceColumnCosines","referenceImagePositionPatient","targetNormal","cross","targetPlane","Plane","setFromNormalAndCoplanarPoint","referenceNormal","referencePlane","originDirection","intersectPlane","origin","direction","distanceTo","line","Line3","intersections","rect","side","intersection","intersectLine","lineRectangleIntersection","topRight","bottomLeft","bottom","getRectangleFromImagePlane","rotatePoint","angleRadians","corner1","corner2","initialRotation","viewport","getViewport","clientWidth","clientHeight","scale","translation","rotation","centerPoint","ellipse","closePath","defaultColor","activeColor","fillColor","toolColors","setFillColor","getFillColor","setToolColor","getToolColor","setActiveColor","getActiveColor","getColorIfActive","active","evtDetail","handleKeys","handleKey","drawnIndependently","drawHandlesIfActive","handleCanvasCoords","lines","linkAnchorPoints","refPoint","boundingBox","findClosestPoint","boundingBoxPoints","defaultFontSize","defaultFont","defaultBackgroundColor","textStyle","setFont","font","getFont","setFontSize","fontSize","getFontSize","setBackgroundColor","backgroundColor","getBackgroundColor","textLines","padding","textBaseline","text","fillText","fillRect","textBoxWidth","origFont","measureText","maxWidth","draw","centering","fillBox","fillTextLines","textBox","textBoxAnchorPoints","xOffset","yCenter","textCoords","drawTextBox","hasMoved","drawLink","corner3","corner4","canvas","getContext","setTransform","defaultValue","shadow","shadowColor","getDefault","shadowBlur","shadowOffsetX","shadowOffsetY","hflip","vflip","translate","rotate","isEmptyObject","_resetHandles","_startOutliningRegion","_isEmptyObject","_applyStrategy","_setHandlesAndUpdate","previousPixeldata","segmentationMixinType","applyActiveStrategy","postTouchStartCallback","postMouseDownCallback","mouseClickCallback","touchDragCallback","mouseDragCallback","mouseMoveCallback","touchEndCallback","mouseUpCallback","initializeMixin","renderToolData","getNewContext","canvasContext","startCanvas","endCanvas","drawCircle","currentHandle","_addPoint","polylineSegmentationMixin","freehandSegmentationMixin","activeOrDisabledBinaryTool","enabledOrDisabledBinaryTool","circleSegmentationMixin","rectangleSegmentationMixin","drawRect","renderBrushMixin","renderBrush","mousePosition","_drawing","_lastImageCoords","_mouseUpRender","circleRadius","mouseCoordsCanvas","isMergeableObject","cloneIfNecessary","optionsArgument","deepmerge","defaultArrayMerge","source","destination","mergeObject","arrayMerge","globalConfigurationModule","BaseTool","defaultProps","initialConfiguration","strategies","defaultStrategy","mixins","activeStrategy","_options","_configuration","updateOnMouseMove","_applyMixins","_cursors","cursors","defaultCursor","mixinsArray","mixin","strategy","changeCursor","coords","insideRect","_isHandleNearImagePoint","distanceThreshold","pointNearHandle","hasBoundingBox","pointInsideBoundingBox","handleCanvas","getHandleNearImagePoint","nearbyHandle","handleName","canvasPoint","activeHandle","_getActiveHandle","renderData","imageRect","handleOutsideImage","allowedOutsideImage","clip","low","high","clipToBox","box","handlerType","segmentationModule","BaseBrushTool","alwaysEraseOnClick","_drawingMouseUpCallback","_paint","_startPainting","_startListeningForMouseUp","_isCtrlDown","paintEventData","isToolActiveForElement","_endPainting","_stopListeningForMouseUp","removeEventListener","addEventListener","oldRadius","ctrlKey","isMultiPartTool","BaseAnnotationTool","getActiveTool","buttons","getActiveToolsForElement","isMultiPartToolActive","filterToolsUseableWithMultiPartTools","_dragEvents","mouse","touch","_upOrEndEvents","annotation","doneMovingCallback","dragHandler","_dragHandler","upOrEndHandler","_upOrEndHandler","eventType","deltaPoints","invalidated","movesIndependently","activeTool","updateCachedStats","preventDefault","stopPropagation","anyHandlesOutsideImage","runAnimation","fingerDistance","aboveFinger","page","targetLocation","pageToPixel","_animate","handlePressed","distanceRemaining","linearDistEachFrame","requestAnimationFrame","_moveEvents","_moveEndEvents","moveHandler","_moveHandler","moveEndHandler","_moveEndHandler","_stopImmediatePropagation","stopImmediatePropagation","moveHandleNearImagePoint","moveHandle","findHandleDataNearImagePoint","moveAnnotation","moveAllHandles","imageNeedsUpdate","handleActivator","nearToolAndNotMarkedActive","pointNearTool","notNearToolAndMarkedActive","lineSegment","distanceToPoint","precision","multiplier","cursorModule","MouseCursor","iconGroupString","svgString","_generateIconSVGString","Blob","_generateIconWithPointerSVGString","svgOptions","svgSize","_injectColors","toolColor","angleCursor","arrowAnnotateCursor","bidirectionalCursor","cobbAngleCursor","circleRoiCursor","ellipticalRoiCursor","freehandRoiCursor","freehandRoiSculptorCursor","lengthCursor","probeCursor","rectangleRoiCursor","textMarkerCursor","crosshairsCursor","eraserCursor","magnifyCursor","panCursor","rotateCursor","stackScrollCursor","wwwcRegionCursor","wwwcCursor","zoomCursor","segToolCursorBoundaries","minusRect","plusRect","scissorIcon","rectangleIcon","circleIcon","freehandEraseInsideCursor","freehandFillInsideCursor","freehandEraseOutsideCursor","freehandFillOutsideCursor","segRectangleEraseInsideCursor","segRectangleFillInsideCursor","segRectangleEraseOutsideCursor","segRectangleFillOutsideCursor","segCircleEraseInsideCursor","segCircleFillInsideCursor","segCircleEraseOutsideCursor","segCircleFillOutsideCursor","getPixelSpacing","rowImagePixelSpacing","colPixelSpacing","colImagePixelSpacing","isObject","debounce","func","wait","lastArgs","lastThis","maxWait","timerId","lastCallTime","lastInvokeTime","leading","maxing","trailing","useRAF","invokeFunc","time","thisArg","startTimer","pendingFunc","shouldInvoke","timeSinceLastCall","timerExpired","now","trailingEdge","timeSinceLastInvoke","timeWaiting","remainingWait","debounced","isInvoking","leadingEdge","Boolean","cancel","id","cancelAnimationFrame","cancelTimer","flush","pending","throttle","AngleTool","preventNewMeasurement","throttledUpdateCachedStats","visible","highlight","middle","lineSegDistance","sideA","sideB","sideC","sideALength","sideBLength","sideCLength","acos","rAngle","roundToDecimal","drawHandlesOnHover","currentTarget","setShadow","handleStartCanvas","handleMiddleCanvas","handleOptions","drawHandles","suffix","fromCharCode","textBoxText","textWidth","transform","internal","getTransform","invert","transformPoint","drawLinkedTextBox","createNewMeasurement","moveNewHandle","vector","ArrowAnnotateTool","getTextCallback","changeTextCallback","arrowFirst","handleEndCanvas","drawArrow","textHeight","midpoint","_updateTextForNearbyAnnotation","_doneChangingTextCallback","updatedText","deleteTool","doneChangingTextCallback","prompt","getHandle","extraAttributes","mouseEventData","isCreating","perpendicularStart","locked","perpendicularEnd","longestDiameter","shortestDiameter","pointNearPerpendicular","getLineVector","startPoint","endPoint","dx","dy","coordsData","strokeWidth","startX","startY","endX","endY","mid","perpendicularLineLength","rowMultiplier","columnMultiplier","updatePerpendicularLineHandles","getTextBoxText","lengthText","widthText","labels","config","checkPixelSpacing","doneCallback","timestamp","getTime","hasHandlesOutside","longestDiameterSize","shortestDiameterSize","isTooSmal","isTooFast","cancelled","getMeasurementLocationCallback","modifiedEventData","toolCoordinates","setCoords","getCoords","handleActivatorChanged","newActiveState","hover","nearTool","nearToolAndInactive","notNearToolAndActive","handleSelectedTouchCallback","handleSelectedMouseCallback","getDistanceWithPixelSpacing","calcX","calcY","createLine","getBaseData","fixedPoint","longLine","perpendicularLine","distanceToFixed","moveLongLine","proposedPoint","baseData","newLineLength","distanceRatio","newLine","distancePS","distancePE","updatePerpendicularLine","isPerpendicularEndFixed","getDirectionMultiplier","helperLine","isMovingStart","getMovingPoint","movingKey","fixedKey","movePerpendicularLine","lineHasLength","highNumber","MAX_SAFE_INTEGER","getHelperLine","newIntersection","distanceFromTool","outOfBounds","d1","d2","swapAttribute","attribute","originalA","originalB","swapHandles","handleDoneMove","moving","selected","_moveCallback","startPoints","handleParams","unselectAllHandles","wx","wy","invertHandles","_dragCallback","setHandlesPosition","currentImage","getImage","imageRenderedHandler","interactionEndCallback","IMAGE_RENDERED","preventPropagation","getDoneMovingCallback","setHandlesMovingState","touchEndEvents","touchMoveHandle","emptyLocationCallback","BidirectionalTool","changeMeasurementLocationCallback","additionalData","addNewMeasurement","handleSelectedCallback","pixelSpacing","tempL","toFixed","calculateLongestAndShortestDiameters","storedPixelValue","skipRescale","patientStudyModule","seriesModule","modality","modalityPixelValue","slope","intercept","patientWeight","petSequenceModule","radiopharmaceuticalInfo","startTime","radiopharmaceuticalStartTime","totalDose","radionuclideTotalDose","halfLife","radionuclideHalfLife","seriesAcquisitionTime","seriesTime","acquisitionTimeInSeconds","fracToDec","fractionalSeconds","seconds","minutes","hours","injectionStartTimeInSeconds","durationInSeconds","correctedDose","exp","suv","fractionalValue","location","xRadius","yRadius","normalized","sp","sumSquared","pointInEllipse","variance","calculateEllipseStatistics","getROITextBoxCoords","corners","handlesLeftToRight","sort","handlesTopToBottom","_determineCorners","centerX","centerY","parts","CircleRoiTool","hasStartAndEndHandles","getDistance","distanceFromCenter","meanStdDevSUV","pixels","getPixels","ellipseMeanStdDev","calculateSUV","area","_calculateStats","cachedStats","newContext","hasPixelSpacing","defaultCoords","textBoxContent","_createTextBoxContent","unit","_getUnit","showHounsfieldUnits","isColorImage","showMinMax","otherLines","hasStandardUptakeValues","meanString","numbersWithCommas","stdDevString","meanSuvString","stdDevSuvString","targetStringLength","minString","maxString","_formatArea","CobbAngleTool","hasIncomplete","start2","end2","dx1","ceil","dy1","dx2","dy2","toMoveHandle","pendingMeasurement","getIncomplete","ev","onMeasureModified","EllipticalRoiTool","validParameters","minorEllipse","majorEllipse","pointInMinorEllipse","ellipseCoordinates","_getEllipseImageCoordinates","drawEllipse","dataHandles","inROI","rayFromPointCrosssesLine","handleI","handleJ","yp","y1","y2","lp1","lp2","lptemp","lPointY","dydx","gradient","lineSegmentAtPoint","sign","isLineRightOfPoint","sumPointIfInFreehand","workingSum","pixelValue","pointInFreehand","squared","ClickedLineData","toolIndex","handleIndexArray","FreehandHandleData","position","doesIntersectOtherLines","q1","ignoredHandleIds","doesIntersect","q2","orient","orientation","onSegment","dataHandle","q","orientationValue","newHandle","candidateHandle","lastHandleId","modify","modifiedHandleId","modifiedHandle","neighborHandleId","neighborHandle","FreehandLineFinder","_eventData","_toolName","closestToolIndex","findTool","closeLines","_getCloseLinesInTool","_findCorrectLine","_toolData","_mousePoint","_nearestHandleToPointAllTools","closestHandle","handleIndex","closestHandleForToolI","_nearestHandleToPoint","closest","handleDistanceFromMousePoint","nextIndex","getNextHandleIndex","_distanceOfPointfromLine","_pointProjectsToLineSegment","handle1","handle2","getCanvasPointsFromHandles","getLineAsVector","_getLineOriginToMouseAsVector","mProj","magnitude","pMouse","currentIndex","insertIndex","_deletePoint","deleteInfo","deleteHandle","_insertPoint","insertInfo","arrayContainsZero","_getInsertionIndex","handleData","addLine","calculateFreehandStatistics","statisticsObj","getSum","freehandArea","scaling","freeHandArea","freehandIntersect","insertOrDelete","nearby","handleNearby","findLine","freehandUtils","FreehandRoiTool","mouseLocation","spacing","activeHandleRadius","completeHandleRadius","completeHandleRadiusTouch","alwaysShowHandles","invalidColor","currentTool","_dragging","_modifying","_drawingMouseDownCallback","_drawingMouseMoveCallback","_drawingMouseDragCallback","_drawingMouseDoubleClickCallback","_editMouseUpCallback","_editMouseDragCallback","_drawingTouchStartCallback","_drawingTouchDragCallback","_drawingDoubleTapClickCallback","_editTouchDragCallback","_pointNearHandle","distanceI","canvasCoords","meanStdDev","polyBoundingBox","invalidHandlePlacement","canComplete","firstHandle","freehand","moSuffix","meanText","stdDevText","areaText","_startDrawing","_pointNearHandleAllTools","dragOrigin","_activateModify","_getMouseLocation","_checkInvalidHandleLocation","_drawingDrag","_addPointPencilMode","lastHandlePlaced","_endDrawing","completeDrawing","_getPrevHandleIndex","lastLineIndex","lastLine","_deactivateModify","_dropHandle","previousHandleData","currentHandleData","_activateDraw","_activeDrawingToolReference","newHandleData","fireModifiedEvent","every","_isDistanceLargerThanSpacing","_deactivateDraw","fireCompletedEvent","_checkHandlesPencilMode","_checkHandlesPolygonMode","_isDistanceSmallerThanCompleteSpacingCanvas","_invalidHandlePencilMode","_isDistanceSmallerThanSpacing","p1Canvas","p2Canvas","_drawingInteractionType","_compareDistanceToSpacing","comparison","_closeToolIfDrawing","LengthTool","row","column","storedPixelData","red","green","blue","ProbeTool","probeCoords","storedPixels","getRGBPixels","getStoredPixels","mo","fontHeight","RectangleRoiTool","roiCoordinates","_getRectangleImageCoordinates","roiMeanStdDev","rectangle","_calculateRectangleStats","TextMarkerTool","markers","current","ascending","loop","touchPressCallback","_changeText","doubleClickCallback","insideBoundingBox","BrushTool","SphericalBrushTool","imagesInRange","imagePlaneOfCurrentImage","ippOfCurrentImage","_getImagesInRange","radiusOnImage","previousPixeldataForImagesInRange","radiusInMM","_getRadiusOnImage","correction","nodes","lastNode","snapPointsToGrid","scissorOperation","allInside","allOutside","isScissorOperation","checkIfSimpleScissorOperation","fillInsideFreehand","eraseInsideFreehand","workingLabelMap","Uint8Array","isLabel","additive","operationIndex","splitLineIntoSeperateOperations","shouldFillOver","pixelCoord","getPixelCoordinateFromPixelIndex","pixelPath","getPixelPathBetweenPixels","leftPath","rightPath","getNodesPerpendicularToPathPixel","getPixelPaths","firstPixelOnPath","pixel","expandBoundingBox","clipBoundingBox","leftArea","rightArea","leftPixel","fillFromPixel","rightPixel","replaceValue","fillValue","performOperation","floodFill","floodedI","pathPixel","nextPathPixel","isPointInPolygon","vs","inside","xi","yi","xj","yj","eraseFreehand","eraseOutsideFreehand","eraseRectangle","eraseInsideRectangle","eraseOutsideRectangle","fillFreehand","fillOutsideFreehand","fillRectangle","fillInsideRectangle","fillOutsideRectangle","fillCircle","fillInsideCircle","fillOutsideCircle","eraseCircle","eraseInsideCircle","eraseOutsideCircle","FreehandScissorsTool","FILL_INSIDE","FILL_OUTSIDE","ERASE_OUTSIDE","ERASE_INSIDE","RectangleScissorsTool","CircleScissorsTool","CorrectionScissorsTool","CORRECTION","_DEFAULT_LOAD_HANDLER","defaultStartLoadHandler","defaultEndLoadHandler","defaultErrorLoadingHandler","_getUUIDFromElement","loadHandlerManager","setStartLoadHandler","handler","getStartLoadHandler","setEndLoadHandler","getEndLoadHandler","setErrorLoadingHandler","getErrorLoadingHandler","removeHandlers","elementToolOptions","getToolOptions","optionsObject","toolOptionObject","setToolOptions","findIndex","elementOptions","CrosshairsTool","mouseDownCallback","_chooseLocation","sourceElement","sourceImageId","sourceImagePlane","synchronizationContext","getSourceElements","targetElement","minDistance","MAX_VALUE","newImageIdIndex","stackToolDataSource","imagePosition","normal","startLoadingHandler","endLoadingHandler","errorLoadingHandler","preventCache","loadImage","displayImage","DoubleTapFitToWindowTool","fitToWindow","DragProbeTool","minimal","minimalStrategy","_movingEventCallback","_endMovingEventCallback","dragEventData","isTouchEvent","pageCoordY","toolCoords","modalityPixelValueText","EraserTool","preMouseDownCallback","_deleteAllNearbyTools","preTouchStartCallback","FreehandRoiSculptorTool","referencedToolName","minSpacing","dragColor","hoverColor","showCursorOnHover","limitRadiusOutsideRegion","hoverCursorFadeAlpha","hoverCursorFadeDistance","_active","activeMouseUpCallback","activeTouchEndCallback","activeMouseDragCallback","_toolSizeCanvas","_recentTouchEnd","_renderHoverCursor","_selectFreehandTool","_initialiseSculpting","_sculpt","_activeEnd","_deselectAllTools","_invalidateToolData","mouseUpRender","_deactivateSculpt","radiusCanvas","distanceFromPointCanvas","unlimitedRadius","_limitCursorRadiusCanvas","globalAlpha","_getClosestFreehandToolOnElement","_configureToolSize","_activateFreehandTool","_activateSculpt","_sculptData","toolSize","_toolSizeImage","maxSpacing","pushedHandles","_pushHandles","first","_insertNewHandles","_consolidateHandles","distanceToHandle","_pushOneHandle","last","directionUnitVector","lastHandleIndex","_getPreviousHandleIndex","indiciesToInsertAfter","_findNewHandleIndicies","newIndexModifier","_insertHandleRadially","_checkSpacing","pointAfterLast","_getNextHandleIndex","pointBeforeFirst","nextHandleIndex","previousIndex","_getNextHandleIndexBeforeInsert","insertPosition","_getInsertPosition","closePairs","_findCloseHandlePairs","_mergeCloseHandles","pair","removedIndexModifier","_getCorrectedPair","_combineHandles","newClosePairs","handlePair","midPoint","handleAfterPairIndex","freehandRoiTool","radiusImage","distanceFromPoint","_limitCursorRadiusImage","TOUCH_TAP","_limitCursorRadius","areaModifier","canvasArea","pixelCoords","distanceFromToolI","distanceToMidPoint","correctedPair","MagnifyTool","magnifySize","magnificationLevel","zoomCanvas","zoomElement","_createMagnificationCanvas","disabledCallback","_destroyMagnificationCanvas","_addMagnifyingGlass","_updateMagnifyingGlass","_removeMagnifyingGlass","touchDragEndCallback","newImageCallback","_drawMagnificationTool","_removeZoomElement","_drawZoomedElement","querySelector","display","magnifyCanvas","canvasLocation","copyFrom","drawImage","touchOffset","magnifyPosition","magnifierBox","getBoundingClientRect","origCanvas","createElement","zoomEnabledElement","setViewport","classList","appendChild","removeChild","getOrientationString","vec3","orientationX","orientationY","orientationZ","z","invertOrientationString","orientationString","inverted","toUpperCase","OrientationMarkersTool","drawAllMarkers","forceImageUpdate","getOrientationMarkers","getOrientationMarkerPositions","textWidths","drawTopLeftText","drawBottomRightText","oppositeRow","PanMultiTouchTool","multiTouchDragCallback","numPointers","_getTranslation","_applyTranslation","widthScale","heightScale","PanTool","referenceElement","targetImage","referenceImage","frameOfReferenceUID","angleInRadians","angleTo","referenceLine","calculateReferenceLine","waitForEnabledElementImageToLoad","ex","ReferenceLinesTool","renderer","renderActiveReferenceLine","setToPixelCoordinateSystem","referenceEnabledElement","p0","p12","p13","p23","RotateTool","horizontal","horizontalStrategy","vertical","verticalStrategy","dragCallback","initialPoints","client","centerPoints","angleInfo","angleBetweenPoints","configMaxSimultaneousRequests","RotateTouchTool","ScaleOverlayTool","minorTickLength","majorTickLength","canvasSize","verticalIntervalScale","horizontalIntervalScale","hscaleBounds","computeScaleBounds","vscaleBounds","imageAttributes","verticalMinorTick","horizontalMinorTick","verticalLine","horizontalLine","drawVerticalScalebarIntervals","drawHorizontalScalebarIntervals","horizontalReduction","verticalReduction","hReduction","vReduction","canvasBounds","maxSimultaneousRequests","IE","9","10","Firefox","Opera","11","12","Chrome","Safari","getBrowserInfo","tem","ua","M","appName","appVersion","getMaxSimultaneousRequests","getDefaultSimultaneousRequests","browserName","browserVersion","browserData","requestPool","interaction","thumbnail","prefetch","numRequests","maxNumRequests","awake","grabDelay","startAgain","startGrabbing","sendRequest","requestDetails","failCallback","imageLoadObject","imageCache","getImageLoadObject","promise","priority","requestTypeToLoadPriority","requestsToSend","getNextRequest","addRequest","addToBeginning","clearRequestStack","getRequestPool","stackRenderer","stackRendererData","newImageId","render","requestPoolManager","allowSkipping","nbImages","scrollToIndex","pendingEvent","scrollWithoutSkipping","NEW_IMAGE","newImageHandler","StackScrollMouseWheelTool","scroll","StackScrollMultiTouchTool","pixelsPerImage","_getPixelPerImage","deltaY","_getDeltaY","imageIdIndexOffset","deltaPointsY","stackScrollSpeed","offsetHeight","StackScrollTool","luminance","WwwcRegionTool","minWindowWidth","_applyWWWCRegion","pixelLuminanceData","getLuminance","minMaxMean","_calculateMinMaxMean","minPixelValue","maxPixelValue","voi","windowWidth","windowCenter","pixelLuminance","globalMin","globalMax","numPixels","spv","WwwcTool","basicLevelingStrategy","deltaX","ticks","scaleLimits","maxScale","minScale","factor","changeViewportScale","correctShift","viewportOrientation","cosA","sinA","newX","newY","ZoomMouseWheelTool","spinY","updatedViewport","zoomUtils","ZoomTool","translateStrategy","zoomToCenter","zoomToCenterStrategy","preventZoomOutsideImage","imageX","imageY","newCoords","desiredTranslation","distanceToDesired","ZoomTouchPinchTool","scaleChange","pageStartX","pageStartY","imageStartX","imageStartY","_copy","preventClickTimeout","isClickEvent","clickDelay","getEventButtons","which","preventClickHandler","mouseDoubleClick","pageToPoint","pageX","pageY","clientX","clientY","lastPoints","copyPoints","mouseDown","mouseMove","onMouseMove","onMouseUp","subtract","metaKey","shiftKey","spinX","pixelX","pixelY","wheelDelta","wheelDeltaY","wheelDeltaX","deltaMode","wheelEventHandler","startingCoords","normalizeWheel","mouseWheelData","passive","lastInteractionType","lastInteractionTime","antiGhostDelay","pointerType","handleTap","handleTapMouse","handleTapTouch","attachEvents","eventList","tapHandler","eventName","removeEvents","mouseEvents","touchEvents","touchStartDelay","pressTimeout","pageDistanceMoved","lastDelta","lastScale","lastRotation","preventNextPinch","isPress","pressDelay","pressMaxDistance","onTouch","srcEvent","delta","pointers","touches","changedTouches","changedPointers","preventGhostClick","mc","hammer","touchInput","hammerOptions","inputClass","SUPPORT_POINTER_EVENTS","PointerEventInput","TouchInput","Manager","panOptions","DIRECTION_ALL","threshold","pan","Pan","pinch","Pinch","Rotate","recognizeWith","doubleTap","Tap","taps","interval","posThreshold","renderSegmentationFill","isActiveLabelMap","labelmapCanvas","canvasTopLeft","canvasTopRight","canvasBottomRight","cornerstoneCanvasWidth","cornerstoneCanvasHeight","previousImageSmoothingEnabled","imageSmoothingEnabled","previousGlobalAlpha","transformCanvasContext","canvasViewportTranslation","resetCanvasContextTransform","colorLutTable","canvasElement","ctx","imageData","ImageData","putImageData","getLabelmapCanvas","renderSegmentationOutline","outline","previousAlpha","drawLines","lineSegments","offset","halfLineWidth","theta","cosTheta","sinTheta","unitVectorI","unitVectorJ","getOutlineOffset","coord","_getPixelIndiciesAroundPixel","_addTopOutline","_addBottomOutline","_addLeftOutline","_addRightOutline","_addTopLeftCorner","_addTopRightCorner","_addBottomLeftCorner","_addBottomRightCorner","getOutline","hasPixelToTop","hasPixelToBotoom","hasPixelToLeft","hasPixelToRight","lineSegmentsForSegment","renderSegmentation","shouldRenderFill","shouldRenderOutline","renderInactiveLabelMaps","renderActiveLabelMap","onImageRendered","toolsToRender","stackToolState","segmentationConfiguration","onImageRenderedBrushEventHandler","customFunction","proximity","activeAndPassiveTools","getInteractiveToolsForElement","activeTools","firstActiveToolWithCallback","annotationTools","getToolsWithDataForElement","annotationToolsWithMoveableHandles","getToolsWithMoveableHandles","firstToolWithMoveableHandles","annotationToolsWithPointNearClick","firstToolNearPoint","firstAnnotationNearPoint","toolSelectedCallback","preMouseDownActivateCallback","mouseClick","customCallbackHandler","mouseUp","mouseWheel","mouseDownActivate","mouseDrag","onNewImage","touchEventData","deactivateAllHandles","toolsWithMoveableHandles","moveableHandle","deactivateAllToolInstances","toolsNearPoint","allActiveTools","touchStartActiveCallback","touchStartActive","annotationToolsWithPointNearTouch","touchDrag","touchEnd","touchPinch","touchPress","touchRotate","tap","touchStart","multiTouchDrag","addToolForElement","ApiTool","addTool","_addToolGlobally","elementEnabledEvt","imageRenderedEventDispatcher","newImageEventDispatcher","mouseEventListeners","wheelEventListener","mouseToolEventDispatcher","touchEventListeners","touchToolEventDispatcher","_addEnabledElement","enabledElementCallback","_initModulesOnElement","_addGlobalToolsToElement","setToolModeFns","disabled","_repeatGlobalToolHistory","elementDisabledEvt","_removeAllToolsForElement","_removeEnabledElement","_removeLoadHandlers","removeEnabledElementCallback","_cleanModulesOnElement","foundElementIndex","resizeTimeout","resizeThrottler","forceEnabledElementResize","resize","_addCornerstoneEventListeners","_initModules","configurationEntry","windowResizeHandler","elementEnabledEvent","ELEMENT_ENABLED","elementDisabledEvent","ELEMENT_DISABLED","events","addEnabledElement","removeEnabledElement","_removeCornerstoneEventListeners","resetPrefetchTimeout","requestType","maxImagesToPrefetch","preserveExistingPool","resetPrefetchDelay","range","lowEnd","highEnd","stackPrefetchData","stackPrefetch","indicesToRequest","removeFromList","nextImageIdIndex","nearest","nearestIndex","lowerIndex","higherIndex","imageIdsToPrefetch","shouldLoadLower","shouldLoadHigher","imageToLoad","imageIndex","getPromiseRemovedHandler","onImageUpdated","indexOfCurrentImage","promiseRemovedHandler","IMAGE_CACHE_PROMISE_REMOVED","getConfiguration","setConfiguration","newMaxSimultaneousRequests","FusionRenderer","layerIds","findImageFn","imageStacks","isInteger","baseImageObject","currentImageId","overlayImageStacks","baseImage","baseLayerId","setLayerImage","addLayer","imgObj","overlayLayerIndex","layerIndex","currentLayerId","setActiveLayer","stackRenderers","stopClipWithData","playClipData","intervalId","usingFrameTimeVector","clearInterval","playClip","framesPerSecond","playClipTimeouts","stackToolData","playClipToolData","lastFrameTimeStamp","frameRate","frameTimeVector","ignoreFrameTimeVector","speed","sample","delay","limit","timeouts","isTimeVarying","getPlayClipTimeouts","playClipAction","imageCount","eventDetail","triggerStopEvent","playClipTimeoutHandler","setInterval","stopClip","removeToolForElement","removeTool","_removeToolGlobally","setToolOptionsForElement","newStackSpecificToolStateManager","toolTypes","oldStateManager","stackStateManagers","addStackStateManager","otherTools","stackTools","stackSpecificStateManager","newFrameOfReferenceSpecificToolStateManager","frameOfReference","frameOfReferenceToolState","remove","globalFrameOfReferenceSpecificToolStateManager","filename","mimetype","msToBlob","blob","msSaveBlob","lnk","download","href","toDataURL","initMouseEvent","fireEvent","newModule","overwrite","alreadyRegistered","isModuleNameRegistered","lib","lineHeight","fontScale","ignorePointerEvents","webkitUserSelect","webkitTouchCallout","mozUserSelect","msUserSelect","oUserSelect","khtmlUserSelect","userSelect","unselectable","oncontextmenu","pointerEvents","currentPointsImage","keyCode","ellipseUtils","segmentationUtils","isMixinRegistered","item","itemKey","isItemNameRegistered","isValidInput","registerModule","registerMixin","registerItem","items","register","synchronizer","sourceViewport","targetViewport","unique","Synchronizer","that","sourceElements","targetElements","ignoreFiredEvents","initialData","eventHandler","isDisabled","noElements","targetIndex","targetImageId","sourceIndex","positionDifference","distances","onEvent","disableHandler","clearToolOptionsByElement","setHandler","getHandler","getDistances","sourceEnabledElement","sourceImagePosition","targetEnabledElement","targetImagePosition","addSource","oneEvent","updateDisableHandlers","addTarget","removeSource","removeTarget","getTargetElements","sourceStackData","distanceToSquared","finalPosition","targetStackData","uri","cornerstoneTools","SaveAs","enableLogger","disableLogger","importInternal","import","registerSome","wwwcSynchronizer","updateImageSynchronizer","stackScrollSynchronizer","stackImagePositionSynchronizer","stackImagePositionOffsetSynchronizer","stackImageIndexSynchronizer","panZoomSynchronizer"],"mappings":"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AkMF,SAAcC,GACZ,IACMA,EACFf,EAASgB,QAAQC,QAAQ,QAASF,GAElCf,EAASgB,QAAQE,WAAW,SAE9B,MAAOC,MAxMTC,KAoNF,WACE,IAAIvE,EAEJ,IACEA,EAAImD,EAASgB,QAAQK,QAAQ,SAC7B,MAAOF,KAMJtE,QAAwB,IAAZyE,GAA2B,QAASA,IACnDzE,EAAIyE,EAAQC,IAAIC,OAGlB,OAAO3E,GAlOPuD,UA8FF,WAIE,GACoB,oBAAXzE,QACPA,OAAO2F,UACkB,aAAxB3F,OAAO2F,QAAQG,MAAuB9F,OAAO2F,QAAQI,QAEtD,OAAO,EAGT,GACuB,oBAAdC,WACPA,UAAUC,WACVD,UAAUC,UAAUC,cAAchB,MAAM,yBAExC,OAAO,EAIT,MACuB,oBAAbiB,UACNA,SAASC,iBACTD,SAASC,gBAAgBC,OACzBF,SAASC,gBAAgBC,MAAMC,kBACd,oBAAXtG,QACNA,OAAOuG,UACNvG,OAAOuG,QAAQC,SACbxG,OAAOuG,QAAQE,WAAazG,OAAOuG,QAAQG,QAE1B,oBAAdV,WACNA,UAAUC,WACVD,UAAUC,UAAUC,cAAchB,MAAM,mBACxCyB,SAASC,OAAOC,GAAI,KAAO,IACP,oBAAdb,WACNA,UAAUC,WACVD,UAAUC,UAAUC,cAAchB,MAAM,uBAlI5CG,QA8OF,WACE,IAGE,OAAOyB,aACP,MAAOtB,KA1PKuB,IAahB1C,EAAS2C,OAAS,CAChB,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,WAqGF3C,EAAS4C,IAAMV,QAAQW,OAA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AGrC,SAAS1V,GACP,IAAM2V,EAAU6nE,EAAgB5lE,SAAS42C,GAErCM,GACFA,EAAoBT,EAAe14C,EAAS3V,SCjErC,YAASk7E,EAAcltB,EAAeK,GAEnD,GAAIA,IAAkBL,EAAtB,CAIA,IAAMj9C,EAAcyE,EAASzE,YAEvBoqE,EAAiBpqE,EAAY+iB,YAAYk6B,GACzCotB,EAAiBrqE,EAAY+iB,YAAYu6B,GAI7C+sB,EAAennD,QAAUknD,EAAelnD,OACxCmnD,EAAelnD,YAAY5a,IAAM6hE,EAAejnD,YAAY5a,GAC5D8hE,EAAelnD,YAAY7qB,IAAM8xE,EAAejnD,YAAY7qB,IAM9D+xE,EAAennD,MAAQknD,EAAelnD,MACtCmnD,EAAelnD,YAAY5a,EAAI6hE,EAAejnD,YAAY5a,EAC1D8hE,EAAelnD,YAAY7qB,EAAI8xE,EAAejnD,YAAY7qB,EAC1D6xE,EAAa/jB,YAAY9I,EAAe+sB,MChC3B,YAASqC,GACtB,OAAOnE,GAAImE,ICRb,i5JCAe,WDAf,wCAoNA,IAAMC,GAAmB,CAGvBp0C,aACAoC,qBACAmI,qBACA0D,iBACAiC,iBACAc,qBACA0G,mBACAuE,cACAO,aACAO,oBACAM,kBAEAS,aACAC,sBACA+E,yBACAL,wBACAM,sBACAC,0BAEAuB,kBACAqB,4BACAE,iBACAU,cACAI,2BACAoF,eACA2C,0BACAS,qBACAO,WACAW,sBACAS,cACAY,mBACAC,oBACA+E,6BACAE,6BACAS,mBACAE,kBACAiB,YACAe,sBACAI,YACAU,sBACApgE,QACA2vE,iBACAsC,kBACAM,YACAsB,YACAhsD,SACA3T,aACAuT,qBACAilD,WACAF,qBACAuH,cACAD,wBACA5pB,kBACA+pB,4BACAj4C,0BACA1T,iBACAhB,2BACAsB,kBACAD,4BACAF,mBACAD,6BACAK,kBACAd,4BACA/U,eACAE,eACAC,kBACAG,iBACAC,6BACAT,6BACA4f,aACArH,aACA6F,cACAya,mBACA8oC,6BACAP,oCACAI,wBACAjrB,sBACA13C,qCACAkB,wCACA6hE,+CACAI,kDACA1G,6BACA70B,eACA4gC,UACAC,eACAC,gBACAC,kBACAC,OAAQD,GACR7C,YACA+C,gBACAC,oBACAC,2BACA5C,gBACA6C,2BACAC,kCACAC,wCACAC,+BACAC,uBACA9e,sBACAjqD,WACApE,SACAtJ,QC5Ta,SD4aA41E","file":"cornerstoneTools.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"cornerstone-tools\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"cornerstone-tools\"] = factory();\n\telse\n\t\troot[\"cornerstoneTools\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 25);\n","function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}\n\nmodule.exports = _classCallCheck;","function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\n\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}\n\nmodule.exports = _createClass;","var _typeof = require(\"../helpers/typeof\");\n\nvar assertThisInitialized = require(\"./assertThisInitialized\");\n\nfunction _possibleConstructorReturn(self, call) {\n if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) {\n return call;\n }\n\n return assertThisInitialized(self);\n}\n\nmodule.exports = _possibleConstructorReturn;","function _getPrototypeOf(o) {\n module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {\n return o.__proto__ || Object.getPrototypeOf(o);\n };\n return _getPrototypeOf(o);\n}\n\nmodule.exports = _getPrototypeOf;","var setPrototypeOf = require(\"./setPrototypeOf\");\n\nfunction _inherits(subClass, superClass) {\n if (typeof superClass !== \"function\" && superClass !== null) {\n throw new TypeError(\"Super expression must either be null or a function\");\n }\n\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n value: subClass,\n writable: true,\n configurable: true\n }\n });\n if (superClass) setPrototypeOf(subClass, superClass);\n}\n\nmodule.exports = _inherits;","function _assertThisInitialized(self) {\n if (self === void 0) {\n throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n }\n\n return self;\n}\n\nmodule.exports = _assertThisInitialized;","var arrayWithoutHoles = require(\"./arrayWithoutHoles\");\n\nvar iterableToArray = require(\"./iterableToArray\");\n\nvar nonIterableSpread = require(\"./nonIterableSpread\");\n\nfunction _toConsumableArray(arr) {\n return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread();\n}\n\nmodule.exports = _toConsumableArray;","var arrayWithHoles = require(\"./arrayWithHoles\");\n\nvar iterableToArrayLimit = require(\"./iterableToArrayLimit\");\n\nvar nonIterableRest = require(\"./nonIterableRest\");\n\nfunction _slicedToArray(arr, i) {\n return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || nonIterableRest();\n}\n\nmodule.exports = _slicedToArray;","function _typeof2(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof2 = function _typeof2(obj) { return typeof obj; }; } else { _typeof2 = function _typeof2(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof2(obj); }\n\nfunction _typeof(obj) {\n if (typeof Symbol === \"function\" && _typeof2(Symbol.iterator) === \"symbol\") {\n module.exports = _typeof = function _typeof(obj) {\n return _typeof2(obj);\n };\n } else {\n module.exports = _typeof = function _typeof(obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : _typeof2(obj);\n };\n }\n\n return _typeof(obj);\n}\n\nmodule.exports = _typeof;","/* eslint-env browser */\n\nimport setup from './common.js';\n\n/**\n * This is the web browser implementation of `debug()`.\n */\nconst storage = localstorage();\n\nconst debugLib = {\n formatArgs,\n save,\n load,\n useColors,\n storage,\n};\n/**\n * Colors.\n */\n\ndebugLib.colors = [\n '#0000CC',\n '#0000FF',\n '#0033CC',\n '#0033FF',\n '#0066CC',\n '#0066FF',\n '#0099CC',\n '#0099FF',\n '#00CC00',\n '#00CC33',\n '#00CC66',\n '#00CC99',\n '#00CCCC',\n '#00CCFF',\n '#3300CC',\n '#3300FF',\n '#3333CC',\n '#3333FF',\n '#3366CC',\n '#3366FF',\n '#3399CC',\n '#3399FF',\n '#33CC00',\n '#33CC33',\n '#33CC66',\n '#33CC99',\n '#33CCCC',\n '#33CCFF',\n '#6600CC',\n '#6600FF',\n '#6633CC',\n '#6633FF',\n '#66CC00',\n '#66CC33',\n '#9900CC',\n '#9900FF',\n '#9933CC',\n '#9933FF',\n '#99CC00',\n '#99CC33',\n '#CC0000',\n '#CC0033',\n '#CC0066',\n '#CC0099',\n '#CC00CC',\n '#CC00FF',\n '#CC3300',\n '#CC3333',\n '#CC3366',\n '#CC3399',\n '#CC33CC',\n '#CC33FF',\n '#CC6600',\n '#CC6633',\n '#CC9900',\n '#CC9933',\n '#CCCC00',\n '#CCCC33',\n '#FF0000',\n '#FF0033',\n '#FF0066',\n '#FF0099',\n '#FF00CC',\n '#FF00FF',\n '#FF3300',\n '#FF3333',\n '#FF3366',\n '#FF3399',\n '#FF33CC',\n '#FF33FF',\n '#FF6600',\n '#FF6633',\n '#FF9900',\n '#FF9933',\n '#FFCC00',\n '#FFCC33',\n];\n/**\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\n * and the Firebug extension (any Firefox version) are known\n * to support \"%c\" CSS customizations.\n *\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\n */\n// eslint-disable-next-line complexity\n\nfunction useColors() {\n // NB: In an Electron preload script, document will be defined but not fully\n // initialized. Since we know we're in Chrome, we'll just detect this case\n // explicitly\n if (\n typeof window !== 'undefined' &&\n window.process &&\n (window.process.type === 'renderer' || window.process.__nwjs)\n ) {\n return true;\n } // Internet Explorer and Edge do not support colors.\n\n if (\n typeof navigator !== 'undefined' &&\n navigator.userAgent &&\n navigator.userAgent.toLowerCase().match(/(edge|trident)\\/(\\d+)/)\n ) {\n return false;\n } // Is webkit? http://stackoverflow.com/a/16459606/376773\n // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\n\n return (\n (typeof document !== 'undefined' &&\n document.documentElement &&\n document.documentElement.style &&\n document.documentElement.style.WebkitAppearance) || // Is firebug? http://stackoverflow.com/a/398120/376773\n (typeof window !== 'undefined' &&\n window.console &&\n (window.console.firebug ||\n (window.console.exception && window.console.table))) || // Is firefox >= v31?\n // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\n (typeof navigator !== 'undefined' &&\n navigator.userAgent &&\n navigator.userAgent.toLowerCase().match(/firefox\\/(\\d+)/) &&\n parseInt(RegExp.$1, 10) >= 31) || // Double check webkit in userAgent just in case we are in a worker\n (typeof navigator !== 'undefined' &&\n navigator.userAgent &&\n navigator.userAgent.toLowerCase().match(/applewebkit\\/(\\d+)/))\n );\n}\n/**\n * Colorize log arguments if enabled.\n *\n * @api public\n */\n\nfunction formatArgs(args) {\n args[0] = `${(this.useColors ? '%c' : '') +\n this.namespace +\n (this.useColors ? ' %c' : ' ') +\n args[0] +\n (this.useColors ? '%c ' : ' ')}+${debugLib.humanize(this.diff)}`;\n\n if (!this.useColors) {\n return;\n }\n\n const c = `color: ${this.color}`;\n\n args.splice(1, 0, c, 'color: inherit'); // The final \"%c\" is somewhat tricky, because there could be other\n // arguments passed either before or after the %c, so we need to\n // figure out the correct index to insert the CSS into\n\n let index = 0;\n let lastC = 0;\n\n args[0].replace(/%[a-zA-Z%]/g, function(match) {\n if (match === '%%') {\n return;\n }\n\n index++;\n\n if (match === '%c') {\n // We only are interested in the *last* %c\n // (the user may have provided their own)\n lastC = index;\n }\n });\n args.splice(lastC, 0, c);\n}\n/**\n * Invokes `console.debug()` when available.\n * No-op when `console.debug` is not a \"function\".\n * If `console.debug` is not available, falls back\n * to `console.log`.\n *\n * @api public\n */\n\ndebugLib.log = console.debug || console.log || function() {};\n/**\n * Save `namespaces`.\n *\n * @param {String} namespaces\n * @api private\n */\n\nfunction save(namespaces) {\n try {\n if (namespaces) {\n debugLib.storage.setItem('debug', namespaces);\n } else {\n debugLib.storage.removeItem('debug');\n }\n } catch (error) {\n // Swallow\n // XXX (@Qix-) should we be logging these?\n }\n}\n/**\n * Load `namespaces`.\n *\n * @return {String} returns the previously persisted debug modes\n * @api private\n */\n\nfunction load() {\n let r;\n\n try {\n r = debugLib.storage.getItem('debug');\n } catch (error) {\n console.warn(error);\n } // Swallow\n // XXX (@Qix-) should we be logging these?\n // If debug isn't set in LS, and we're in Electron, try to load $DEBUG\n\n if (!r && typeof process !== 'undefined' && 'env' in process) {\n r = process.env.DEBUG;\n }\n\n return r;\n}\n/**\n * Localstorage attempts to return the localstorage.\n *\n * This is necessary because safari throws\n * when a user disables cookies/localstorage\n * and you attempt to access it.\n *\n * @return {LocalStorage}\n * @api private\n */\n\nfunction localstorage() {\n try {\n // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context\n // The Browser also has localStorage in the global context.\n return localStorage;\n } catch (error) {\n // Swallow\n // XXX (@Qix-) should we be logging these?\n }\n}\n\nconst setupDebug = setup(debugLib);\nconst formatters = setupDebug.formatters;\n/**\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\n */\n\nformatters.j = function(v) {\n try {\n return JSON.stringify(v);\n } catch (error) {\n return `[UnexpectedJSONParseError]: ${error.message}`;\n }\n};\n\nexport default setupDebug;\n","function _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\nmodule.exports = _defineProperty;","module.exports = require(\"regenerator-runtime\");\n","/**\n * This is the common logic for both the Node.js and web browser\n * implementations of `debug()`.\n */\n\nfunction setup(env) {\n createDebug.debug = createDebug;\n createDebug.default = createDebug;\n createDebug.coerce = coerce;\n createDebug.disable = disable;\n createDebug.enable = enable;\n createDebug.enabled = enabled;\n createDebug.humanize = require('ms');\n\n Object.keys(env).forEach(key => {\n createDebug[key] = env[key];\n });\n\n /**\n * Active `debug` instances.\n */\n createDebug.instances = [];\n\n /**\n * The currently active debug mode names, and names to skip.\n */\n\n createDebug.names = [];\n createDebug.skips = [];\n\n /**\n * Map of special \"%n\" handling functions, for the debug \"format\" argument.\n *\n * Valid key names are a single, lower or upper-case letter, i.e. \"n\" and \"N\".\n */\n createDebug.formatters = {};\n\n /**\n * Selects a color for a debug namespace\n * @param {String} namespace The namespace string for the for the debug instance to be colored\n * @returns {Number|String} An ANSI color code for the given namespace\n * @api private\n */\n function selectColor(namespace) {\n let hash = 0;\n\n for (let i = 0; i < namespace.length; i++) {\n hash = (hash << 5) - hash + namespace.charCodeAt(i);\n hash |= 0; // Convert to 32bit integer\n }\n\n return createDebug.colors[Math.abs(hash) % createDebug.colors.length];\n }\n createDebug.selectColor = selectColor;\n\n /**\n * Create a debugger with the given `namespace`.\n *\n * @param {String} namespace\n * @returns {Function}\n * @api public\n */\n function createDebug(namespace) {\n let prevTime;\n\n function debug(...args) {\n // Disabled?\n if (!debug.enabled) {\n return;\n }\n\n const self = debug;\n\n // Set `diff` timestamp\n const curr = Number(new Date());\n const ms = curr - (prevTime || curr);\n\n self.diff = ms;\n self.prev = prevTime;\n self.curr = curr;\n prevTime = curr;\n\n args[0] = createDebug.coerce(args[0]);\n\n if (typeof args[0] !== 'string') {\n // Anything else let's inspect with %O\n args.unshift('%O');\n }\n\n // Apply any `formatters` transformations\n let index = 0;\n\n args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {\n // If we encounter an escaped % then don't increase the array index\n if (match === '%%') {\n return match;\n }\n index++;\n const formatter = createDebug.formatters[format];\n\n if (typeof formatter === 'function') {\n const val = args[index];\n\n match = formatter.call(self, val);\n\n // Now we need to remove `args[index]` since it's inlined in the `format`\n args.splice(index, 1);\n index--;\n }\n\n return match;\n });\n\n // Apply env-specific formatting (colors, etc.)\n createDebug.formatArgs.call(self, args);\n\n const logFn = self.log || createDebug.log;\n\n logFn.apply(self, args);\n }\n\n debug.namespace = namespace;\n debug.enabled = createDebug.enabled(namespace);\n debug.useColors = createDebug.useColors();\n debug.color = selectColor(namespace);\n debug.destroy = destroy;\n debug.extend = extend;\n // Debug.formatArgs = formatArgs;\n // debug.rawLog = rawLog;\n\n // env-specific initialization logic for debug instances\n if (typeof createDebug.init === 'function') {\n createDebug.init(debug);\n }\n\n createDebug.instances.push(debug);\n\n return debug;\n }\n\n function destroy() {\n const index = createDebug.instances.indexOf(this);\n\n if (index !== -1) {\n createDebug.instances.splice(index, 1);\n\n return true;\n }\n\n return false;\n }\n\n function extend(namespace, delimiter) {\n const newDebug = createDebug(\n this.namespace +\n (typeof delimiter === 'undefined' ? ':' : delimiter) +\n namespace\n );\n\n newDebug.log = this.log;\n\n return newDebug;\n }\n\n /**\n * Enables a debug mode by namespaces. This can include modes\n * separated by a colon and wildcards.\n *\n * @param {String} namespaces\n * @api public\n */\n function enable(namespaces) {\n createDebug.save(namespaces);\n\n createDebug.names = [];\n createDebug.skips = [];\n\n let i;\n const split = (typeof namespaces === 'string' ? namespaces : '').split(\n /[\\s,]+/\n );\n const len = split.length;\n\n for (i = 0; i < len; i++) {\n if (!split[i]) {\n // Ignore empty strings\n continue;\n }\n\n namespaces = split[i].replace(/\\*/g, '.*?');\n\n if (namespaces[0] === '-') {\n createDebug.skips.push(new RegExp(`^${namespaces.substr(1)}$`));\n } else {\n createDebug.names.push(new RegExp(`^${namespaces}$`));\n }\n }\n\n for (i = 0; i < createDebug.instances.length; i++) {\n const instance = createDebug.instances[i];\n\n instance.enabled = createDebug.enabled(instance.namespace);\n }\n }\n\n /**\n * Disable debug output.\n *\n * @returns {String} namespaces\n * @api public\n */\n function disable() {\n const namespaces = [\n ...createDebug.names.map(toNamespace),\n ...createDebug.skips.map(toNamespace).map(namespace => `-${namespace}`),\n ].join(',');\n\n createDebug.enable('');\n\n return namespaces;\n }\n\n /**\n * Returns true if the given mode name is enabled, false otherwise.\n *\n * @param {String} name\n * @returns {Boolean}\n * @api public\n */\n function enabled(name) {\n if (name[name.length - 1] === '*') {\n return true;\n }\n\n let i;\n let len;\n\n for (i = 0, len = createDebug.skips.length; i < len; i++) {\n if (createDebug.skips[i].test(name)) {\n return false;\n }\n }\n\n for (i = 0, len = createDebug.names.length; i < len; i++) {\n if (createDebug.names[i].test(name)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Convert regexp to namespace\n *\n * @param {RegExp} regxep\n * @returns {String} namespace\n * @api private\n */\n function toNamespace(regexp) {\n return regexp\n .toString()\n .substring(2, regexp.toString().length - 2)\n .replace(/\\.\\*\\?$/, '*');\n }\n\n /**\n * Coerce `val`.\n *\n * @param {Mixed} val\n * @returns {Mixed}\n * @api private\n */\n function coerce(val) {\n if (val instanceof Error) {\n return val.stack || val.message;\n }\n\n return val;\n }\n\n createDebug.enable(createDebug.load());\n\n return createDebug;\n}\n\nexport default setup;\n","function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {\n try {\n var info = gen[key](arg);\n var value = info.value;\n } catch (error) {\n reject(error);\n return;\n }\n\n if (info.done) {\n resolve(value);\n } else {\n Promise.resolve(value).then(_next, _throw);\n }\n}\n\nfunction _asyncToGenerator(fn) {\n return function () {\n var self = this,\n args = arguments;\n return new Promise(function (resolve, reject) {\n var gen = fn.apply(self, args);\n\n function _next(value) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"next\", value);\n }\n\n function _throw(err) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"throw\", err);\n }\n\n _next(undefined);\n });\n };\n}\n\nmodule.exports = _asyncToGenerator;","function _setPrototypeOf(o, p) {\n module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n\n return _setPrototypeOf(o, p);\n}\n\nmodule.exports = _setPrototypeOf;","// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ())\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n runTimeout(drainQueue);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n","function _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) {\n for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {\n arr2[i] = arr[i];\n }\n\n return arr2;\n }\n}\n\nmodule.exports = _arrayWithoutHoles;","function _iterableToArray(iter) {\n if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter);\n}\n\nmodule.exports = _iterableToArray;","function _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance\");\n}\n\nmodule.exports = _nonIterableSpread;","/**\n * Helpers.\n */\n\nvar s = 1000;\nvar m = s * 60;\nvar h = m * 60;\nvar d = h * 24;\nvar w = d * 7;\nvar y = d * 365.25;\n\n/**\n * Parse or format the given `val`.\n *\n * Options:\n *\n * - `long` verbose formatting [false]\n *\n * @param {String|Number} val\n * @param {Object} [options]\n * @throws {Error} throw an error if val is not a non-empty string or a number\n * @return {String|Number}\n * @api public\n */\n\nmodule.exports = function(val, options) {\n options = options || {};\n var type = typeof val;\n if (type === 'string' && val.length > 0) {\n return parse(val);\n } else if (type === 'number' && isNaN(val) === false) {\n return options.long ? fmtLong(val) : fmtShort(val);\n }\n throw new Error(\n 'val is not a non-empty string or a valid number. val=' +\n JSON.stringify(val)\n );\n};\n\n/**\n * Parse the given `str` and return milliseconds.\n *\n * @param {String} str\n * @return {Number}\n * @api private\n */\n\nfunction parse(str) {\n str = String(str);\n if (str.length > 100) {\n return;\n }\n var match = /^((?:\\d+)?\\-?\\d?\\.?\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(\n str\n );\n if (!match) {\n return;\n }\n var n = parseFloat(match[1]);\n var type = (match[2] || 'ms').toLowerCase();\n switch (type) {\n case 'years':\n case 'year':\n case 'yrs':\n case 'yr':\n case 'y':\n return n * y;\n case 'weeks':\n case 'week':\n case 'w':\n return n * w;\n case 'days':\n case 'day':\n case 'd':\n return n * d;\n case 'hours':\n case 'hour':\n case 'hrs':\n case 'hr':\n case 'h':\n return n * h;\n case 'minutes':\n case 'minute':\n case 'mins':\n case 'min':\n case 'm':\n return n * m;\n case 'seconds':\n case 'second':\n case 'secs':\n case 'sec':\n case 's':\n return n * s;\n case 'milliseconds':\n case 'millisecond':\n case 'msecs':\n case 'msec':\n case 'ms':\n return n;\n default:\n return undefined;\n }\n}\n\n/**\n * Short format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtShort(ms) {\n var msAbs = Math.abs(ms);\n if (msAbs >= d) {\n return Math.round(ms / d) + 'd';\n }\n if (msAbs >= h) {\n return Math.round(ms / h) + 'h';\n }\n if (msAbs >= m) {\n return Math.round(ms / m) + 'm';\n }\n if (msAbs >= s) {\n return Math.round(ms / s) + 's';\n }\n return ms + 'ms';\n}\n\n/**\n * Long format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtLong(ms) {\n var msAbs = Math.abs(ms);\n if (msAbs >= d) {\n return plural(ms, msAbs, d, 'day');\n }\n if (msAbs >= h) {\n return plural(ms, msAbs, h, 'hour');\n }\n if (msAbs >= m) {\n return plural(ms, msAbs, m, 'minute');\n }\n if (msAbs >= s) {\n return plural(ms, msAbs, s, 'second');\n }\n return ms + ' ms';\n}\n\n/**\n * Pluralization helper.\n */\n\nfunction plural(ms, msAbs, n, name) {\n var isPlural = msAbs >= n * 1.5;\n return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');\n}\n","function _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}\n\nmodule.exports = _arrayWithHoles;","function _iterableToArrayLimit(arr, i) {\n var _arr = [];\n var _n = true;\n var _d = false;\n var _e = undefined;\n\n try {\n for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n _arr.push(_s.value);\n\n if (i && _arr.length === i) break;\n }\n } catch (err) {\n _d = true;\n _e = err;\n } finally {\n try {\n if (!_n && _i[\"return\"] != null) _i[\"return\"]();\n } finally {\n if (_d) throw _e;\n }\n }\n\n return _arr;\n}\n\nmodule.exports = _iterableToArrayLimit;","function _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance\");\n}\n\nmodule.exports = _nonIterableRest;","/**\n * Copyright (c) 2014-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This method of obtaining a reference to the global object needs to be\n// kept identical to the way it is obtained in runtime.js\nvar g = (function() {\n return this || (typeof self === \"object\" && self);\n})() || Function(\"return this\")();\n\n// Use `getOwnPropertyNames` because not all browsers support calling\n// `hasOwnProperty` on the global `self` object in a worker. See #183.\nvar hadRuntime = g.regeneratorRuntime &&\n Object.getOwnPropertyNames(g).indexOf(\"regeneratorRuntime\") >= 0;\n\n// Save the old regeneratorRuntime in case it needs to be restored later.\nvar oldRuntime = hadRuntime && g.regeneratorRuntime;\n\n// Force reevalutation of runtime.js.\ng.regeneratorRuntime = undefined;\n\nmodule.exports = require(\"./runtime\");\n\nif (hadRuntime) {\n // Restore the original runtime.\n g.regeneratorRuntime = oldRuntime;\n} else {\n // Remove the global property added by runtime.js.\n try {\n delete g.regeneratorRuntime;\n } catch(e) {\n g.regeneratorRuntime = undefined;\n }\n}\n","/**\n * Copyright (c) 2014-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n!(function(global) {\n \"use strict\";\n\n var Op = Object.prototype;\n var hasOwn = Op.hasOwnProperty;\n var undefined; // More compressible than void 0.\n var $Symbol = typeof Symbol === \"function\" ? Symbol : {};\n var iteratorSymbol = $Symbol.iterator || \"@@iterator\";\n var asyncIteratorSymbol = $Symbol.asyncIterator || \"@@asyncIterator\";\n var toStringTagSymbol = $Symbol.toStringTag || \"@@toStringTag\";\n\n var inModule = typeof module === \"object\";\n var runtime = global.regeneratorRuntime;\n if (runtime) {\n if (inModule) {\n // If regeneratorRuntime is defined globally and we're in a module,\n // make the exports object identical to regeneratorRuntime.\n module.exports = runtime;\n }\n // Don't bother evaluating the rest of this file if the runtime was\n // already defined globally.\n return;\n }\n\n // Define the runtime globally (as expected by generated code) as either\n // module.exports (if we're in a module) or a new, empty object.\n runtime = global.regeneratorRuntime = inModule ? module.exports : {};\n\n function wrap(innerFn, outerFn, self, tryLocsList) {\n // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.\n var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;\n var generator = Object.create(protoGenerator.prototype);\n var context = new Context(tryLocsList || []);\n\n // The ._invoke method unifies the implementations of the .next,\n // .throw, and .return methods.\n generator._invoke = makeInvokeMethod(innerFn, self, context);\n\n return generator;\n }\n runtime.wrap = wrap;\n\n // Try/catch helper to minimize deoptimizations. Returns a completion\n // record like context.tryEntries[i].completion. This interface could\n // have been (and was previously) designed to take a closure to be\n // invoked without arguments, but in all the cases we care about we\n // already have an existing method we want to call, so there's no need\n // to create a new function object. We can even get away with assuming\n // the method takes exactly one argument, since that happens to be true\n // in every case, so we don't have to touch the arguments object. The\n // only additional allocation required is the completion record, which\n // has a stable shape and so hopefully should be cheap to allocate.\n function tryCatch(fn, obj, arg) {\n try {\n return { type: \"normal\", arg: fn.call(obj, arg) };\n } catch (err) {\n return { type: \"throw\", arg: err };\n }\n }\n\n var GenStateSuspendedStart = \"suspendedStart\";\n var GenStateSuspendedYield = \"suspendedYield\";\n var GenStateExecuting = \"executing\";\n var GenStateCompleted = \"completed\";\n\n // Returning this object from the innerFn has the same effect as\n // breaking out of the dispatch switch statement.\n var ContinueSentinel = {};\n\n // Dummy constructor functions that we use as the .constructor and\n // .constructor.prototype properties for functions that return Generator\n // objects. For full spec compliance, you may wish to configure your\n // minifier not to mangle the names of these two functions.\n function Generator() {}\n function GeneratorFunction() {}\n function GeneratorFunctionPrototype() {}\n\n // This is a polyfill for %IteratorPrototype% for environments that\n // don't natively support it.\n var IteratorPrototype = {};\n IteratorPrototype[iteratorSymbol] = function () {\n return this;\n };\n\n var getProto = Object.getPrototypeOf;\n var NativeIteratorPrototype = getProto && getProto(getProto(values([])));\n if (NativeIteratorPrototype &&\n NativeIteratorPrototype !== Op &&\n hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {\n // This environment has a native %IteratorPrototype%; use it instead\n // of the polyfill.\n IteratorPrototype = NativeIteratorPrototype;\n }\n\n var Gp = GeneratorFunctionPrototype.prototype =\n Generator.prototype = Object.create(IteratorPrototype);\n GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;\n GeneratorFunctionPrototype.constructor = GeneratorFunction;\n GeneratorFunctionPrototype[toStringTagSymbol] =\n GeneratorFunction.displayName = \"GeneratorFunction\";\n\n // Helper for defining the .next, .throw, and .return methods of the\n // Iterator interface in terms of a single ._invoke method.\n function defineIteratorMethods(prototype) {\n [\"next\", \"throw\", \"return\"].forEach(function(method) {\n prototype[method] = function(arg) {\n return this._invoke(method, arg);\n };\n });\n }\n\n runtime.isGeneratorFunction = function(genFun) {\n var ctor = typeof genFun === \"function\" && genFun.constructor;\n return ctor\n ? ctor === GeneratorFunction ||\n // For the native GeneratorFunction constructor, the best we can\n // do is to check its .name property.\n (ctor.displayName || ctor.name) === \"GeneratorFunction\"\n : false;\n };\n\n runtime.mark = function(genFun) {\n if (Object.setPrototypeOf) {\n Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);\n } else {\n genFun.__proto__ = GeneratorFunctionPrototype;\n if (!(toStringTagSymbol in genFun)) {\n genFun[toStringTagSymbol] = \"GeneratorFunction\";\n }\n }\n genFun.prototype = Object.create(Gp);\n return genFun;\n };\n\n // Within the body of any async function, `await x` is transformed to\n // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test\n // `hasOwn.call(value, \"__await\")` to determine if the yielded value is\n // meant to be awaited.\n runtime.awrap = function(arg) {\n return { __await: arg };\n };\n\n function AsyncIterator(generator) {\n function invoke(method, arg, resolve, reject) {\n var record = tryCatch(generator[method], generator, arg);\n if (record.type === \"throw\") {\n reject(record.arg);\n } else {\n var result = record.arg;\n var value = result.value;\n if (value &&\n typeof value === \"object\" &&\n hasOwn.call(value, \"__await\")) {\n return Promise.resolve(value.__await).then(function(value) {\n invoke(\"next\", value, resolve, reject);\n }, function(err) {\n invoke(\"throw\", err, resolve, reject);\n });\n }\n\n return Promise.resolve(value).then(function(unwrapped) {\n // When a yielded Promise is resolved, its final value becomes\n // the .value of the Promise<{value,done}> result for the\n // current iteration.\n result.value = unwrapped;\n resolve(result);\n }, function(error) {\n // If a rejected Promise was yielded, throw the rejection back\n // into the async generator function so it can be handled there.\n return invoke(\"throw\", error, resolve, reject);\n });\n }\n }\n\n var previousPromise;\n\n function enqueue(method, arg) {\n function callInvokeWithMethodAndArg() {\n return new Promise(function(resolve, reject) {\n invoke(method, arg, resolve, reject);\n });\n }\n\n return previousPromise =\n // If enqueue has been called before, then we want to wait until\n // all previous Promises have been resolved before calling invoke,\n // so that results are always delivered in the correct order. If\n // enqueue has not been called before, then it is important to\n // call invoke immediately, without waiting on a callback to fire,\n // so that the async generator function has the opportunity to do\n // any necessary setup in a predictable way. This predictability\n // is why the Promise constructor synchronously invokes its\n // executor callback, and why async functions synchronously\n // execute code before the first await. Since we implement simple\n // async functions in terms of async generators, it is especially\n // important to get this right, even though it requires care.\n previousPromise ? previousPromise.then(\n callInvokeWithMethodAndArg,\n // Avoid propagating failures to Promises returned by later\n // invocations of the iterator.\n callInvokeWithMethodAndArg\n ) : callInvokeWithMethodAndArg();\n }\n\n // Define the unified helper method that is used to implement .next,\n // .throw, and .return (see defineIteratorMethods).\n this._invoke = enqueue;\n }\n\n defineIteratorMethods(AsyncIterator.prototype);\n AsyncIterator.prototype[asyncIteratorSymbol] = function () {\n return this;\n };\n runtime.AsyncIterator = AsyncIterator;\n\n // Note that simple async functions are implemented on top of\n // AsyncIterator objects; they just return a Promise for the value of\n // the final result produced by the iterator.\n runtime.async = function(innerFn, outerFn, self, tryLocsList) {\n var iter = new AsyncIterator(\n wrap(innerFn, outerFn, self, tryLocsList)\n );\n\n return runtime.isGeneratorFunction(outerFn)\n ? iter // If outerFn is a generator, return the full iterator.\n : iter.next().then(function(result) {\n return result.done ? result.value : iter.next();\n });\n };\n\n function makeInvokeMethod(innerFn, self, context) {\n var state = GenStateSuspendedStart;\n\n return function invoke(method, arg) {\n if (state === GenStateExecuting) {\n throw new Error(\"Generator is already running\");\n }\n\n if (state === GenStateCompleted) {\n if (method === \"throw\") {\n throw arg;\n }\n\n // Be forgiving, per 25.3.3.3.3 of the spec:\n // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume\n return doneResult();\n }\n\n context.method = method;\n context.arg = arg;\n\n while (true) {\n var delegate = context.delegate;\n if (delegate) {\n var delegateResult = maybeInvokeDelegate(delegate, context);\n if (delegateResult) {\n if (delegateResult === ContinueSentinel) continue;\n return delegateResult;\n }\n }\n\n if (context.method === \"next\") {\n // Setting context._sent for legacy support of Babel's\n // function.sent implementation.\n context.sent = context._sent = context.arg;\n\n } else if (context.method === \"throw\") {\n if (state === GenStateSuspendedStart) {\n state = GenStateCompleted;\n throw context.arg;\n }\n\n context.dispatchException(context.arg);\n\n } else if (context.method === \"return\") {\n context.abrupt(\"return\", context.arg);\n }\n\n state = GenStateExecuting;\n\n var record = tryCatch(innerFn, self, context);\n if (record.type === \"normal\") {\n // If an exception is thrown from innerFn, we leave state ===\n // GenStateExecuting and loop back for another invocation.\n state = context.done\n ? GenStateCompleted\n : GenStateSuspendedYield;\n\n if (record.arg === ContinueSentinel) {\n continue;\n }\n\n return {\n value: record.arg,\n done: context.done\n };\n\n } else if (record.type === \"throw\") {\n state = GenStateCompleted;\n // Dispatch the exception by looping back around to the\n // context.dispatchException(context.arg) call above.\n context.method = \"throw\";\n context.arg = record.arg;\n }\n }\n };\n }\n\n // Call delegate.iterator[context.method](context.arg) and handle the\n // result, either by returning a { value, done } result from the\n // delegate iterator, or by modifying context.method and context.arg,\n // setting context.delegate to null, and returning the ContinueSentinel.\n function maybeInvokeDelegate(delegate, context) {\n var method = delegate.iterator[context.method];\n if (method === undefined) {\n // A .throw or .return when the delegate iterator has no .throw\n // method always terminates the yield* loop.\n context.delegate = null;\n\n if (context.method === \"throw\") {\n if (delegate.iterator.return) {\n // If the delegate iterator has a return method, give it a\n // chance to clean up.\n context.method = \"return\";\n context.arg = undefined;\n maybeInvokeDelegate(delegate, context);\n\n if (context.method === \"throw\") {\n // If maybeInvokeDelegate(context) changed context.method from\n // \"return\" to \"throw\", let that override the TypeError below.\n return ContinueSentinel;\n }\n }\n\n context.method = \"throw\";\n context.arg = new TypeError(\n \"The iterator does not provide a 'throw' method\");\n }\n\n return ContinueSentinel;\n }\n\n var record = tryCatch(method, delegate.iterator, context.arg);\n\n if (record.type === \"throw\") {\n context.method = \"throw\";\n context.arg = record.arg;\n context.delegate = null;\n return ContinueSentinel;\n }\n\n var info = record.arg;\n\n if (! info) {\n context.method = \"throw\";\n context.arg = new TypeError(\"iterator result is not an object\");\n context.delegate = null;\n return ContinueSentinel;\n }\n\n if (info.done) {\n // Assign the result of the finished delegate to the temporary\n // variable specified by delegate.resultName (see delegateYield).\n context[delegate.resultName] = info.value;\n\n // Resume execution at the desired location (see delegateYield).\n context.next = delegate.nextLoc;\n\n // If context.method was \"throw\" but the delegate handled the\n // exception, let the outer generator proceed normally. If\n // context.method was \"next\", forget context.arg since it has been\n // \"consumed\" by the delegate iterator. If context.method was\n // \"return\", allow the original .return call to continue in the\n // outer generator.\n if (context.method !== \"return\") {\n context.method = \"next\";\n context.arg = undefined;\n }\n\n } else {\n // Re-yield the result returned by the delegate method.\n return info;\n }\n\n // The delegate iterator is finished, so forget it and continue with\n // the outer generator.\n context.delegate = null;\n return ContinueSentinel;\n }\n\n // Define Generator.prototype.{next,throw,return} in terms of the\n // unified ._invoke helper method.\n defineIteratorMethods(Gp);\n\n Gp[toStringTagSymbol] = \"Generator\";\n\n // A Generator should always return itself as the iterator object when the\n // @@iterator function is called on it. Some browsers' implementations of the\n // iterator prototype chain incorrectly implement this, causing the Generator\n // object to not be returned from this call. This ensures that doesn't happen.\n // See https://github.com/facebook/regenerator/issues/274 for more details.\n Gp[iteratorSymbol] = function() {\n return this;\n };\n\n Gp.toString = function() {\n return \"[object Generator]\";\n };\n\n function pushTryEntry(locs) {\n var entry = { tryLoc: locs[0] };\n\n if (1 in locs) {\n entry.catchLoc = locs[1];\n }\n\n if (2 in locs) {\n entry.finallyLoc = locs[2];\n entry.afterLoc = locs[3];\n }\n\n this.tryEntries.push(entry);\n }\n\n function resetTryEntry(entry) {\n var record = entry.completion || {};\n record.type = \"normal\";\n delete record.arg;\n entry.completion = record;\n }\n\n function Context(tryLocsList) {\n // The root entry object (effectively a try statement without a catch\n // or a finally block) gives us a place to store values thrown from\n // locations where there is no enclosing try statement.\n this.tryEntries = [{ tryLoc: \"root\" }];\n tryLocsList.forEach(pushTryEntry, this);\n this.reset(true);\n }\n\n runtime.keys = function(object) {\n var keys = [];\n for (var key in object) {\n keys.push(key);\n }\n keys.reverse();\n\n // Rather than returning an object with a next method, we keep\n // things simple and return the next function itself.\n return function next() {\n while (keys.length) {\n var key = keys.pop();\n if (key in object) {\n next.value = key;\n next.done = false;\n return next;\n }\n }\n\n // To avoid creating an additional object, we just hang the .value\n // and .done properties off the next function object itself. This\n // also ensures that the minifier will not anonymize the function.\n next.done = true;\n return next;\n };\n };\n\n function values(iterable) {\n if (iterable) {\n var iteratorMethod = iterable[iteratorSymbol];\n if (iteratorMethod) {\n return iteratorMethod.call(iterable);\n }\n\n if (typeof iterable.next === \"function\") {\n return iterable;\n }\n\n if (!isNaN(iterable.length)) {\n var i = -1, next = function next() {\n while (++i < iterable.length) {\n if (hasOwn.call(iterable, i)) {\n next.value = iterable[i];\n next.done = false;\n return next;\n }\n }\n\n next.value = undefined;\n next.done = true;\n\n return next;\n };\n\n return next.next = next;\n }\n }\n\n // Return an iterator with no values.\n return { next: doneResult };\n }\n runtime.values = values;\n\n function doneResult() {\n return { value: undefined, done: true };\n }\n\n Context.prototype = {\n constructor: Context,\n\n reset: function(skipTempReset) {\n this.prev = 0;\n this.next = 0;\n // Resetting context._sent for legacy support of Babel's\n // function.sent implementation.\n this.sent = this._sent = undefined;\n this.done = false;\n this.delegate = null;\n\n this.method = \"next\";\n this.arg = undefined;\n\n this.tryEntries.forEach(resetTryEntry);\n\n if (!skipTempReset) {\n for (var name in this) {\n // Not sure about the optimal order of these conditions:\n if (name.charAt(0) === \"t\" &&\n hasOwn.call(this, name) &&\n !isNaN(+name.slice(1))) {\n this[name] = undefined;\n }\n }\n }\n },\n\n stop: function() {\n this.done = true;\n\n var rootEntry = this.tryEntries[0];\n var rootRecord = rootEntry.completion;\n if (rootRecord.type === \"throw\") {\n throw rootRecord.arg;\n }\n\n return this.rval;\n },\n\n dispatchException: function(exception) {\n if (this.done) {\n throw exception;\n }\n\n var context = this;\n function handle(loc, caught) {\n record.type = \"throw\";\n record.arg = exception;\n context.next = loc;\n\n if (caught) {\n // If the dispatched exception was caught by a catch block,\n // then let that catch block handle the exception normally.\n context.method = \"next\";\n context.arg = undefined;\n }\n\n return !! caught;\n }\n\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n var record = entry.completion;\n\n if (entry.tryLoc === \"root\") {\n // Exception thrown outside of any try block that could handle\n // it, so set the completion value of the entire function to\n // throw the exception.\n return handle(\"end\");\n }\n\n if (entry.tryLoc <= this.prev) {\n var hasCatch = hasOwn.call(entry, \"catchLoc\");\n var hasFinally = hasOwn.call(entry, \"finallyLoc\");\n\n if (hasCatch && hasFinally) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n } else if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else if (hasCatch) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n }\n\n } else if (hasFinally) {\n if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else {\n throw new Error(\"try statement without catch or finally\");\n }\n }\n }\n },\n\n abrupt: function(type, arg) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc <= this.prev &&\n hasOwn.call(entry, \"finallyLoc\") &&\n this.prev < entry.finallyLoc) {\n var finallyEntry = entry;\n break;\n }\n }\n\n if (finallyEntry &&\n (type === \"break\" ||\n type === \"continue\") &&\n finallyEntry.tryLoc <= arg &&\n arg <= finallyEntry.finallyLoc) {\n // Ignore the finally entry if control is not jumping to a\n // location outside the try/catch block.\n finallyEntry = null;\n }\n\n var record = finallyEntry ? finallyEntry.completion : {};\n record.type = type;\n record.arg = arg;\n\n if (finallyEntry) {\n this.method = \"next\";\n this.next = finallyEntry.finallyLoc;\n return ContinueSentinel;\n }\n\n return this.complete(record);\n },\n\n complete: function(record, afterLoc) {\n if (record.type === \"throw\") {\n throw record.arg;\n }\n\n if (record.type === \"break\" ||\n record.type === \"continue\") {\n this.next = record.arg;\n } else if (record.type === \"return\") {\n this.rval = this.arg = record.arg;\n this.method = \"return\";\n this.next = \"end\";\n } else if (record.type === \"normal\" && afterLoc) {\n this.next = afterLoc;\n }\n\n return ContinueSentinel;\n },\n\n finish: function(finallyLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.finallyLoc === finallyLoc) {\n this.complete(entry.completion, entry.afterLoc);\n resetTryEntry(entry);\n return ContinueSentinel;\n }\n }\n },\n\n \"catch\": function(tryLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc === tryLoc) {\n var record = entry.completion;\n if (record.type === \"throw\") {\n var thrown = record.arg;\n resetTryEntry(entry);\n }\n return thrown;\n }\n }\n\n // The context.catch method must only be called with a location\n // argument that corresponds to a known catch block.\n throw new Error(\"illegal catch attempt\");\n },\n\n delegateYield: function(iterable, resultName, nextLoc) {\n this.delegate = {\n iterator: values(iterable),\n resultName: resultName,\n nextLoc: nextLoc\n };\n\n if (this.method === \"next\") {\n // Deliberately forget the last sent value so that we don't\n // accidentally pass it on to the delegate.\n this.arg = undefined;\n }\n\n return ContinueSentinel;\n }\n };\n})(\n // In sloppy mode, unbound `this` refers to the global object, fallback to\n // Function constructor if we're in global strict mode. That is sadly a form\n // of indirect eval which violates Content Security Policy.\n (function() {\n return this || (typeof self === \"object\" && self);\n })() || Function(\"return this\")()\n);\n","let cornerstone = window.cornerstone;\nlet cornerstoneMath = window.cornerstoneMath;\nlet Hammer = window.Hammer;\n\nexport default {\n set cornerstone(cs) {\n cornerstone = cs;\n },\n get cornerstone() {\n return cornerstone;\n },\n set cornerstoneMath(cm) {\n cornerstoneMath = cm;\n },\n get cornerstoneMath() {\n return cornerstoneMath;\n },\n set Hammer(module) {\n Hammer = module;\n },\n get Hammer() {\n return Hammer;\n },\n};\n","/**\n * Enumerates the events for CornestoneTools. Native events are captured,\n * normalized, and re-triggered with a `cornerstonetools` prefix. This allows\n * us to handle events consistently across different browsers.\n *\n * @enum {String}\n * @memberof CornerstoneTools\n * @readonly\n */\nconst EVENTS = {\n //\n // MOUSE\n //\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/mousedown\n * @type {String}\n */\n MOUSE_DOWN: 'cornerstonetoolsmousedown',\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/mouseup\n * @type {String}\n */\n MOUSE_UP: 'cornerstonetoolsmouseup',\n\n /**\n * Is fired if a handled `MOUSE_DOWN` event does not `stopPropagation`. The hook\n * we use to create new measurement data for mouse events.\n * @type {String}\n */\n MOUSE_DOWN_ACTIVATE: 'cornerstonetoolsmousedownactivate',\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/drag\n * @type {String}\n */\n MOUSE_DRAG: 'cornerstonetoolsmousedrag',\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/mousemove\n * @type {String}\n */\n MOUSE_MOVE: 'cornerstonetoolsmousemove',\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/click\n * @type {String}\n */\n MOUSE_CLICK: 'cornerstonetoolsmouseclick',\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/dblclick\n * @type {String}\n */\n MOUSE_DOUBLE_CLICK: 'cornerstonetoolsmousedoubleclick',\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/wheel\n * @type {String}\n */\n MOUSE_WHEEL: 'cornerstonetoolsmousewheel',\n\n //\n // TOUCH\n //\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/touchstart\n * @type {String}\n */\n TOUCH_START: 'cornerstonetoolstouchstart',\n\n /**\n * Is fired if a handled `TOUCH_START` event does not `stopPropagation`. The hook\n * we use to create new measurement data for touch events.\n * @type {String}\n */\n TOUCH_START_ACTIVE: 'cornerstonetoolstouchstartactive',\n\n /**\n * @type {String}\n */\n TOUCH_END: 'cornerstonetoolstouchend',\n\n /**\n * @type {String}\n */\n TOUCH_DRAG: 'cornerstonetoolstouchdrag',\n\n /**\n * @type {String}\n */\n TOUCH_DRAG_END: 'cornerstonetoolstouchdragend',\n\n /**\n * http://hammerjs.github.io/recognizer-pinch/\n * @type {String}\n */\n TOUCH_PINCH: 'cornerstonetoolstouchpinch',\n\n /**\n * http://hammerjs.github.io/recognizer-rotate/\n * @type {String}\n */\n TOUCH_ROTATE: 'cornerstonetoolstouchrotate',\n\n /**\n * http://hammerjs.github.io/recognizer-press/\n * @type {String}\n */\n TOUCH_PRESS: 'cornerstonetoolstouchpress',\n\n /**\n * http://hammerjs.github.io/recognizer-tap/\n * @type {String}\n */\n TAP: 'cornerstonetoolstap',\n\n /**\n * @type {String}\n */\n DOUBLE_TAP: 'cornerstonetoolsdoubletap',\n\n /**\n * @type {String}\n */\n MULTI_TOUCH_START: 'cornerstonetoolsmultitouchstart',\n\n /**\n * @type {String}\n */\n MULTI_TOUCH_START_ACTIVE: 'cornerstonetoolsmultitouchstartactive',\n\n /**\n * @type {String}\n */\n MULTI_TOUCH_DRAG: 'cornerstonetoolsmultitouchdrag',\n\n //\n // KEYBOARD\n //\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/keydown\n * @type {String}\n */\n KEY_DOWN: 'cornerstonetoolskeydown',\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/keyup\n * @type {String}\n */\n KEY_UP: 'cornerstonetoolskeyup',\n\n /**\n * https://developer.mozilla.org/en-US/docs/Web/Events/keypress\n * @type {String}\n */\n KEY_PRESS: 'cornerstonetoolskeypress',\n\n //\n // CUSTOM\n //\n\n /**\n * @type {String}\n */\n MEASUREMENT_ADDED: 'cornerstonetoolsmeasurementadded',\n\n /**\n * @type {String}\n */\n MEASUREMENT_MODIFIED: 'cornerstonetoolsmeasurementmodified',\n\n /**\n * @type {String}\n */\n MEASUREMENT_COMPLETED: 'cornerstonetoolsmeasurementcompleted',\n\n /**\n * @type {String}\n */\n MEASUREMENT_REMOVED: 'cornerstonetoolsmeasurementremoved',\n\n /**\n * @type {String}\n */\n TOOL_DEACTIVATED: 'cornerstonetoolstooldeactivated',\n\n /**\n * @type {String}\n */\n CLIP_STOPPED: 'cornerstonetoolsclipstopped',\n\n /**\n * @type {String}\n */\n STACK_SCROLL: 'cornerstonetoolsstackscroll',\n\n /**\n * @type {String}\n */\n STACK_PREFETCH_IMAGE_LOADED: 'cornerstonetoolsstackprefetchimageloaded',\n\n /**\n * @type {String}\n */\n STACK_PREFETCH_DONE: 'cornerstonetoolsstackprefetchdone',\n\n /**\n * @type {String}\n */\n LABELMAP_MODIFIED: 'cornersontetoolslabelmapmodified',\n};\n\nexport default EVENTS;\n","/**\n * Triggers a CustomEvent.\n * @public\n * @method triggerEvent\n *\n * @param {EventTarget} el The element or EventTarget to trigger the event upon.\n * @param {String} type The event type name.\n * @param {Object|null} [detail=null] The event data to be sent.\n * @returns {Boolean} The return value is false if at least one event listener called preventDefault(). Otherwise it returns true.\n */\nexport default function triggerEvent(el, type, detail = null) {\n let event;\n\n // This check is needed to polyfill CustomEvent on IE11-\n if (typeof window.CustomEvent === 'function') {\n event = new CustomEvent(type, {\n detail,\n cancelable: true,\n });\n } else {\n event = document.createEvent('CustomEvent');\n event.initCustomEvent(type, true, true, detail);\n }\n\n return el.dispatchEvent(event);\n}\n","import { getters as storeGetters } from '../../index.js';\n\n/**\n * Returns the cornerstone enabled element given either the element or its enabledElement UUID.\n *\n * @param {string|HTMLElement} elementOrEnabledElementUID The enabledElement\n * or its UUID.\n * @returns {HTMLElement}\n */\nexport default function _getElement(elementOrEnabledElementUID) {\n if (elementOrEnabledElementUID instanceof HTMLElement) {\n return elementOrEnabledElementUID;\n }\n\n return storeGetters.enabledElementByUID(elementOrEnabledElementUID);\n}\n","/**\n * AddLabelmap3D - Adds a `Labelmap3D` object to the `BrushStackState` object.\n *\n * @param {BrushStackState} brushStackState The labelmap state for a particular stack.\n * @param {number} labelmapIndex The labelmapIndex to set.\n * @param {number} size The size of the ArrayBuffer in bytes/ 2.\n * @returns {null}\n */\nexport default function addLabelmap3D(brushStackState, labelmapIndex, size) {\n // Buffer size is multiplied by 2 as we are using 2 bytes/voxel for 65536 segments.\n brushStackState.labelmaps3D[labelmapIndex] = {\n buffer: new ArrayBuffer(size * 2),\n labelmaps2D: [],\n metadata: [],\n activeSegmentIndex: 1,\n colorLUTIndex: 0,\n segmentsHidden: [],\n undo: [],\n redo: [],\n };\n}\n","import external from '../externalModules.js';\n\n/**\n * Implements an imageId specific tool state management strategy. This means that\n * Measurements data is tied to a specific imageId and only visible for enabled elements\n * That are displaying that imageId.\n * @public\n * @constructor newImageIdSpecificToolStateManager\n * @memberof StateManagement\n *\n * @returns {Object} An imageIdSpecificToolStateManager instance.\n */\nfunction newImageIdSpecificToolStateManager() {\n let toolState = {};\n\n // Here we add tool state, this is done by tools as well\n // As modules that restore saved state\n\n function saveImageIdToolState(imageId) {\n return toolState[imageId];\n }\n\n function restoreImageIdToolState(imageId, imageIdToolState) {\n toolState[imageId] = imageIdToolState;\n }\n\n function saveToolState() {\n return toolState;\n }\n\n function restoreToolState(savedToolState) {\n toolState = savedToolState;\n }\n\n // Here we add tool state, this is done by tools as well\n // As modules that restore saved state\n function addImageIdSpecificToolState(element, toolType, data) {\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n // If we don't have an image for this element exit early\n if (!enabledElement.image) {\n return;\n }\n\n // If we don't have any tool state for this imageId, add an empty object\n if (toolState.hasOwnProperty(enabledElement.image.imageId) === false) {\n toolState[enabledElement.image.imageId] = {};\n }\n\n const imageIdToolState = toolState[enabledElement.image.imageId];\n\n // If we don't have tool state for this type of tool, add an empty object\n if (imageIdToolState.hasOwnProperty(toolType) === false) {\n imageIdToolState[toolType] = {\n data: [],\n };\n }\n\n const toolData = imageIdToolState[toolType];\n\n // Finally, add this new tool to the state\n toolData.data.push(data);\n }\n\n // Here you can get state - used by tools as well as modules\n // That save state persistently\n function getImageIdSpecificToolState(element, toolType) {\n const enabledElement = external.cornerstone.getEnabledElement(element);\n // If we don't have any tool state for this imageId, return undefined\n\n if (\n !enabledElement.image ||\n toolState.hasOwnProperty(enabledElement.image.imageId) === false\n ) {\n return;\n }\n\n const imageIdToolState = toolState[enabledElement.image.imageId];\n\n // If we don't have tool state for this type of tool, return undefined\n if (imageIdToolState.hasOwnProperty(toolType) === false) {\n return;\n }\n\n const toolData = imageIdToolState[toolType];\n\n return toolData;\n }\n\n // Clears all tool data from this toolStateManager.\n function clearImageIdSpecificToolStateManager(element) {\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n if (\n !enabledElement.image ||\n toolState.hasOwnProperty(enabledElement.image.imageId) === false\n ) {\n return;\n }\n\n delete toolState[enabledElement.image.imageId];\n }\n\n return {\n get: getImageIdSpecificToolState,\n add: addImageIdSpecificToolState,\n clear: clearImageIdSpecificToolStateManager,\n saveImageIdToolState,\n restoreImageIdToolState,\n saveToolState,\n restoreToolState,\n toolState,\n };\n}\n\n// A global imageIdSpecificToolStateManager - the most common case is to share state between all\n// Visible enabled images\nconst globalImageIdSpecificToolStateManager = newImageIdSpecificToolStateManager();\n\nexport {\n newImageIdSpecificToolStateManager,\n globalImageIdSpecificToolStateManager,\n};\n","import EVENTS from '../events.js';\nimport external from '../externalModules.js';\nimport { globalImageIdSpecificToolStateManager } from './imageIdSpecificStateManager.js';\nimport triggerEvent from '../util/triggerEvent.js';\n\n/**\n * Returns the toolstate for a specific element.\n * @public\n * @function getElementToolStateManager\n *\n * @param {HTMLElement} element The element.\n * @returns {Object} The toolState.\n */\nfunction getElementToolStateManager(element) {\n const enabledElement = external.cornerstone.getEnabledElement(element);\n // If the enabledElement has no toolStateManager, create a default one for it\n // NOTE: This makes state management element specific\n\n if (enabledElement.toolStateManager === undefined) {\n enabledElement.toolStateManager = globalImageIdSpecificToolStateManager;\n }\n\n return enabledElement.toolStateManager;\n}\n\n/**\n * Adds tool state to the toolStateManager, this is done by tools as well\n * as modules that restore saved state.\n * @public\n * @method addToolState\n *\n * @param {HTMLElement} element The element.\n * @param {string} toolType The toolType of the state.\n * @param {Object} measurementData The data to store in the state.\n * @returns {undefined}\n */\nfunction addToolState(element, toolType, measurementData) {\n const toolStateManager = getElementToolStateManager(element);\n\n toolStateManager.add(element, toolType, measurementData);\n\n const eventType = EVENTS.MEASUREMENT_ADDED;\n const eventData = {\n toolType,\n element,\n measurementData,\n };\n\n triggerEvent(element, eventType, eventData);\n}\n\n/**\n * Returns tool specific state of an element. Used by tools as well as modules\n * that save state persistently\n * @export\n * @public\n * @method\n * @name getToolState\n *\n * @param {HTMLElement} element The element.\n * @param {string} toolType The toolType of the state.\n * @returns {Object} The element's state for the given toolType.\n */\nfunction getToolState(element, toolType) {\n const toolStateManager = getElementToolStateManager(element);\n\n return toolStateManager.get(element, toolType);\n}\n\n/**\n * Removes specific tool state from the toolStateManager.\n * @public\n * @method removeToolState\n *\n * @param {HTMLElement} element The element.\n * @param {string} toolType The toolType of the state.\n * @param {Object} data The data to remove from the toolStateManager.\n * @returns {undefined}\n */\nfunction removeToolState(element, toolType, data) {\n const toolStateManager = getElementToolStateManager(element);\n const toolData = toolStateManager.get(element, toolType);\n // Find this tool data\n let indexOfData = -1;\n\n for (let i = 0; i < toolData.data.length; i++) {\n if (toolData.data[i] === data) {\n indexOfData = i;\n }\n }\n\n if (indexOfData !== -1) {\n toolData.data.splice(indexOfData, 1);\n\n const eventType = EVENTS.MEASUREMENT_REMOVED;\n const eventData = {\n toolType,\n element,\n measurementData: data,\n };\n\n triggerEvent(element, eventType, eventData);\n }\n}\n\n/**\n * Removes all toolState from the toolStateManager corresponding to\n * the toolType and element.\n * @public\n * @method clearToolState\n *\n * @param {HTMLElement} element The element.\n * @param {string} toolType The toolType of the state.\n * @returns {undefined}\n */\nfunction clearToolState(element, toolType) {\n const toolStateManager = getElementToolStateManager(element);\n const toolData = toolStateManager.get(element, toolType);\n\n // If any toolData actually exists, clear it\n if (toolData !== undefined) {\n toolData.data = [];\n }\n}\n\n/**\n * Sets the tool state manager for an element\n * @public\n * @method setElementToolStateManager\n *\n * @param {HTMLElement} element The element.\n * @param {Object} toolStateManager The toolStateManager.\n * @returns {undefined}\n */\nfunction setElementToolStateManager(element, toolStateManager) {\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n enabledElement.toolStateManager = toolStateManager;\n}\n\nexport {\n addToolState,\n getToolState,\n removeToolState,\n clearToolState,\n setElementToolStateManager,\n getElementToolStateManager,\n};\n","import debugLib from './debugLib/index.js';\n\nconst BASE_SCOPE = 'cornerstoneTools';\nconst baseLogger = debugLib(BASE_SCOPE);\n\n// eslint-disable-next-line no-process-env\nconst devMode = process.env.NODE_ENV === 'development';\n\n// If we're in dev-mode, tell the user how to get logs\nif (devMode && !baseLogger.enabled) {\n // eslint-disable-next-line no-console\n console.log(\n '%cCornerstone Tools',\n 'background: #339955; padding: 4px; font-weight: bold; color: white'\n );\n\n // eslint-disable-next-line no-console\n console.info(\n 'run %clocalStorage.setItem(\"debug\", \"cornerstoneTools\")%c to see console output',\n 'background: #eaeaea; color: #333; font-family: monospace',\n ''\n );\n}\n\n/**\n * @method debug\n * Create's a scoped debuging logger\n */\n\nexport const getLogger = scope => {\n const log = baseLogger.extend(scope);\n\n return {\n log,\n // eslint-disable-next-line no-console\n warn: devMode ? console.warn.bind(console) : log,\n // eslint-disable-next-line no-console\n error: console.error.bind(console),\n };\n};\n\n/**\n * @method enable\n * @param {string} scope The scope to enabled\n * @returns {void}\n */\nexport const enable = (scope = `${BASE_SCOPE}:*`) => debugLib.enable(scope);\n\n/**\n * @method disable\n * @param {string} scope\n * @returns {string} The previously enabled scope\n */\nexport const disable = () => debugLib.disable();\n","// Internal state of the brush module.\nconst state = {\n series: {},\n colorLutTables: [],\n};\n\nexport default state;\n","import getElement from './getElement';\nimport addLabelmap3D from './addLabelmap3D';\nimport { getToolState } from '../../../stateManagement/toolState.js';\nimport external from '../../../externalModules';\nimport { getLogger } from '../../../util/logger';\nimport state from './state';\n\nconst logger = getLogger('store:modules:segmentationModule:metadata');\n\n/**\n * GetMetadata - Returns the metadata object for a particular segment if\n * segmentIndex is specified, otherwise returns an array of all segment metadata\n * for the labelmap.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {number} [labelmapIndex] If undefined, defaults to the active\n * labelmap index.\n * @param {number} [segmentIndex] The segment index.\n * @returns {Object|Object[]} A metadata object or an array of\n * metadata objects.\n */\nfunction getMetadata(elementOrEnabledElementUID, labelmapIndex, segmentIndex) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const firstImageId = stackData.imageIds[0];\n\n const brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n logger.warn(`brushStackState is undefined`);\n\n return;\n }\n\n labelmapIndex =\n labelmapIndex === undefined\n ? brushStackState.activeLabelmapIndex\n : labelmapIndex;\n\n if (!brushStackState.labelmaps3D[labelmapIndex]) {\n logger.warn(`No labelmap3D of labelmap index ${labelmapIndex} on stack.`);\n\n return;\n }\n\n const labelmap3D = brushStackState.labelmaps3D[labelmapIndex];\n\n if (segmentIndex === undefined) {\n return labelmap3D.metadata;\n }\n\n return labelmap3D.metadata[segmentIndex];\n}\n\n/**\n * SetMetadata - Sets the metadata object for a particular segment of a\n * `Labelmap3D`.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {number} labelmapIndex = 0 The labelmap index.\n * @param {number} segmentIndex The segment index.\n * @param {Object} metadata The metadata object to set.\n * @returns {null}\n */\nfunction setMetadata(\n elementOrEnabledElementUID,\n labelmapIndex = 0,\n segmentIndex,\n metadata\n) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const firstImageId = stackData.imageIds[0];\n\n let brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n state.series[firstImageId] = {\n labelmapIndex,\n labelmaps3D: [],\n };\n\n brushStackState = state.series[firstImageId];\n }\n\n if (!brushStackState.labelmaps3D[labelmapIndex]) {\n const enabledElement = cornerstone.getEnabledElement(element);\n\n const { rows, columns } = enabledElement.image;\n const numberOfFrames = stackData.imageIds.length;\n const size = rows * columns * numberOfFrames;\n\n addLabelmap3D(brushStackState, labelmapIndex, size);\n }\n\n const labelmap3D = brushStackState.labelmaps3D[labelmapIndex];\n\n labelmap3D.metadata[segmentIndex] = metadata;\n}\n\nexport { getMetadata, setMetadata };\n","import getElement from './getElement';\nimport { getToolState } from '../../../stateManagement/toolState.js';\nimport state from './state';\nimport { getModule } from '../../index.js';\n\n/**\n * Returns the `activeSegmentIndex` for the active `Labelmap3D` for the `BrushStackState` displayed on the element.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {number} [labelmapIndex] The labelmap index, defaults to the active labelmap index.\n * @returns {number} The active segment index.\n */\nfunction getActiveSegmentIndex(elementOrEnabledElementUID, labelmapIndex) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const firstImageId = stackData.imageIds[0];\n\n const brushStackState = state.series[firstImageId];\n\n if (brushStackState) {\n labelmapIndex =\n labelmapIndex === undefined\n ? brushStackState.activeLabelmapIndex\n : labelmapIndex;\n\n const labelmap3D = brushStackState.labelmaps3D[labelmapIndex];\n\n if (labelmap3D) {\n return labelmap3D.activeSegmentIndex;\n }\n }\n\n return 1;\n}\n\n/**\n * Sets the `activeSegmentIndex` for the active `Labelmap3D` on the element.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {number} segmentIndex The segmentIndex to set active.\n * @returns {null}\n */\nfunction setActiveSegmentIndex(elementOrEnabledElementUID, segmentIndex) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const firstImageId = stackData.imageIds[0];\n\n const brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n return;\n }\n\n const activeLabelmapIndex = brushStackState.activeLabelmapIndex;\n const labelmap3D = brushStackState.labelmaps3D[activeLabelmapIndex];\n\n const { configuration } = getModule('segmentation');\n\n if (segmentIndex <= 0) {\n segmentIndex = 1;\n } else if (segmentIndex > configuration.segmentsPerLabelmap) {\n segmentIndex = configuration.segmentsPerLabelmap;\n }\n\n labelmap3D.activeSegmentIndex = segmentIndex;\n}\n\n/**\n * Increment the `activeSegmentIndex` for the active `Labelmap3D` on the element.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @returns {null}\n */\nfunction incrementActiveSegmentIndex(elementOrEnabledElementUID) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n _changeActiveSegmentIndex(element, 'increase');\n}\n\n/**\n * Decrement the `activeSegmentIndex` for the active `Labelmap3D` on the element.\n *\n * @param {HTMLElement} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @returns {null}\n */\nfunction decrementActiveSegmentIndex(elementOrEnabledElementUID) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n _changeActiveSegmentIndex(element, 'decrease');\n}\n\n/**\n * Changes the `activeSegmentIndex` for the active `Labelmap3D` on the element.\n *\n * @param {HTMLElement} element The cornerstone enabled element.\n * @param {string} increaseOrDecrease = Whether to increase/decrease the activeLabelmapIndex.\n * @returns {null}\n */\nfunction _changeActiveSegmentIndex(element, increaseOrDecrease = 'increase') {\n const { configuration } = getModule('segmentation');\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const firstImageId = stackData.imageIds[0];\n\n const brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n return;\n }\n\n const activeLabelmapIndex = brushStackState.activeLabelmapIndex;\n const labelmap3D = brushStackState.labelmaps3D[activeLabelmapIndex];\n\n switch (increaseOrDecrease) {\n case 'increase':\n labelmap3D.activeSegmentIndex++;\n\n if (labelmap3D.activeSegmentIndex > configuration.segmentsPerLabelmap) {\n labelmap3D.activeSegmentIndex = 1;\n }\n break;\n case 'decrease':\n labelmap3D.activeSegmentIndex--;\n\n if (labelmap3D.activeSegmentIndex <= 0) {\n labelmap3D.activeSegmentIndex = configuration.segmentsPerLabelmap;\n }\n break;\n }\n}\n\nexport {\n getActiveSegmentIndex,\n setActiveSegmentIndex,\n incrementActiveSegmentIndex,\n decrementActiveSegmentIndex,\n};\n","import getElement from './getElement';\nimport { getToolState } from '../../../stateManagement/toolState.js';\nimport state from './state';\n\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger('store:modules:segmentationModule:segmentVisibility');\n\n/**\n * Returns if a segment is visible.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {number} segmentIndex The segment index.\n * @param {number} [labelmapIndex] If undefined, defaults to the active\n * labelmap index.\n * @returns {boolean} True if the segment is visible.\n */\nfunction isSegmentVisible(\n elementOrEnabledElementUID,\n segmentIndex,\n labelmapIndex\n) {\n if (!segmentIndex) {\n return;\n }\n\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const firstImageId = stackData.imageIds[0];\n\n const brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n logger.warn(`brushStackState is undefined`);\n\n return;\n }\n\n labelmapIndex =\n labelmapIndex === undefined\n ? brushStackState.activeLabelmapIndex\n : labelmapIndex;\n\n if (!brushStackState.labelmaps3D[labelmapIndex]) {\n logger.warn(`No labelmap3D of labelmap index ${labelmapIndex} on stack.`);\n\n return;\n }\n\n const labelmap3D = brushStackState.labelmaps3D[labelmapIndex];\n const visible = !labelmap3D.segmentsHidden[segmentIndex];\n\n return visible;\n}\n\n/**\n * Toggles the visability of a segment.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {number} segmentIndex The segment index.\n * @param {number} [labelmapIndex] If undefined, defaults to the active\n * labelmap index.\n * @returns {boolean} True if the segment is now visible.\n */\nfunction toggleSegmentVisibility(\n elementOrEnabledElementUID,\n segmentIndex,\n labelmapIndex\n) {\n if (!segmentIndex) {\n return;\n }\n\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const firstImageId = stackData.imageIds[0];\n\n const brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n logger.warn(`brushStackState is undefined`);\n\n return;\n }\n\n labelmapIndex =\n labelmapIndex === undefined\n ? brushStackState.activeLabelmapIndex\n : labelmapIndex;\n\n if (!brushStackState.labelmaps3D[labelmapIndex]) {\n logger.warn(`No labelmap3D of labelmap index ${labelmapIndex} on stack.`);\n\n return;\n }\n\n const labelmap3D = brushStackState.labelmaps3D[labelmapIndex];\n const segmentsHidden = labelmap3D.segmentsHidden;\n\n segmentsHidden[segmentIndex] = !segmentsHidden[segmentIndex];\n\n return !segmentsHidden[segmentIndex];\n}\n\nexport { isSegmentVisible, toggleSegmentVisibility };\n","import { getToolState } from '../../../stateManagement/toolState.js';\nimport getElement from './getElement';\nimport state from './state';\n\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger('store:modules:segmentationModule:getLabelmaps3D');\n\n/**\n * Returns the `Labelmap3D` objects associated with the series displayed\n * in the element, the `activeLabelmapIndex` and the `currentImageIdIndex`.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @returns {Object} An object containing `Labelmap3D` objects,\n * the `activeLabelmapIndex` amd the `currentImageIdIndex`.\n */\nexport default function getLabelmaps3D(elementOrEnabledElementUID) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n\n if (!stackState) {\n logger.error(\n 'Consumers must define stacks in their application if using segmentations in cornerstoneTools.'\n );\n\n return;\n }\n\n const stackData = stackState.data[0];\n\n const firstImageId = stackData.imageIds[0];\n const brushStackState = state.series[firstImageId];\n\n let labelmaps3D;\n let activeLabelmapIndex;\n\n if (brushStackState) {\n labelmaps3D = brushStackState.labelmaps3D;\n activeLabelmapIndex = brushStackState.activeLabelmapIndex;\n }\n\n return {\n labelmaps3D,\n activeLabelmapIndex,\n currentImageIdIndex: stackData.currentImageIdIndex,\n };\n}\n\n/**\n * Returns a single `Labelmap3D` object associated with the series displayed\n * in the element.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {number} [labelmapIndex] The index of the `Labelmap3D` to retrieve. Defaults to\n * the `activeLabelmapIndex`.\n * @returns {Object} A `Labelmap3D` object.\n */\nexport function getLabelmap3D(elementOrEnabledElementUID, labelmapIndex) {\n const { labelmaps3D, activeLabelmapIndex } = getLabelmaps3D(\n elementOrEnabledElementUID\n );\n\n labelmapIndex =\n labelmapIndex !== undefined ? labelmapIndex : activeLabelmapIndex;\n\n return labelmaps3D[labelmapIndex];\n}\n","import getElement from './getElement';\nimport { getToolState } from '../../../stateManagement/toolState.js';\nimport getLabelmaps3D from './getLabelmaps3D';\nimport state from './state';\n\n/**\n * GetLabelmapBuffers - Returns the `buffer` of each `Labelmap3D` associated\n * with the `BrushStackState` displayed on the element, or a specific\n * one if `labelmapIndex` is defined.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {type} [labelmapIndex] Optional filtering to only return one labelmap.\n * @returns {Object|Object[]} An array of objects containing the `labelmapIndex`, and the corresponding buffer and `colorLUT`.\n * Only one object if `labelmapIndex` was specified.\n *\n */\nfunction getLabelmapBuffers(elementOrEnabledElementUID, labelmapIndex) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const { labelmaps3D } = getLabelmaps3D(element);\n\n if (!labelmaps3D) {\n return [];\n }\n\n const colorLutTables = state.colorLutTables;\n\n if (labelmapIndex !== undefined) {\n const labelmap3D = labelmaps3D[labelmapIndex];\n\n if (labelmap3D) {\n return {\n labelmapIndex,\n bytesPerVoxel: 2,\n buffer: labelmap3D.buffer,\n colorLUT: colorLutTables[labelmap3D.colorLUTIndex],\n };\n }\n\n return;\n }\n\n const labelmapBuffers = [];\n\n for (let i = 0; i < labelmaps3D.length; i++) {\n const labelmap3D = labelmaps3D[i];\n\n if (labelmap3D) {\n labelmapBuffers.push({\n labelmapIndex: i,\n bytesPerVoxel: 2,\n buffer: labelmap3D.buffer,\n colorLUT: colorLutTables[labelmap3D.colorLUTIndex],\n });\n }\n }\n\n return labelmapBuffers;\n}\n\n/**\n * Returns the `buffer` corresponding to the active `Labelmap3D` associated with the\n * `BrushStackState` displayed onv the element.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @returns {Object} An object containing the `labelmapIndex` and\n * corresponding `buffer`.\n */\nfunction getActiveLabelmapBuffer(elementOrEnabledElementUID) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n const imageIds = stackState.data[0].imageIds;\n const firstImageId = imageIds[0];\n\n const brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n return;\n }\n\n const activeLabelmapIndex = brushStackState.activeLabelmapIndex;\n\n return getLabelmapBuffers(element, activeLabelmapIndex);\n}\n\nexport { getLabelmapBuffers, getActiveLabelmapBuffer };\n","/**\n * Returns an array of the segment indicies present on the `pixelData`.\n * @param {UInt16Array} pixelData The pixel data array.\n */\nexport default function getSegmentsOnPixelData(pixelData) {\n const segmentSet = new Set(pixelData);\n const iterator = segmentSet.values();\n\n const segmentsOnLabelmap = [];\n let done = false;\n\n while (!done) {\n const next = iterator.next();\n\n done = next.done;\n\n if (!done) {\n segmentsOnLabelmap.push(next.value);\n }\n }\n\n return segmentsOnLabelmap;\n}\n","/**\n * If the pixelData for the given pixelIndex is equal to the segmentIndex\n * erase it (set it to 0).\n * @param {number} pixelIndex The index of the pixel.\n * @param {UInt16Array} pixelData The pixelData array.\n * @param {number} segmentIndex The segment Index to erase.\n */\nexport default function eraseIfSegmentIndex(\n pixelIndex,\n pixelData,\n segmentIndex\n) {\n if (pixelData[pixelIndex] === segmentIndex) {\n pixelData[pixelIndex] = 0;\n }\n}\n","import eraseIfSegmentIndex from './eraseIfSegmentIndex.js';\n\n/**\n * DrawBrushPixels - Adds or removes labels to a labelmap.\n *\n * @param {number[]} pointerArray The array of pixels to paint.\n * @param {Object} labelmap2D The `pixelData` array to paint to.\n * @param {number} segmentIndex The segment being drawn.\n * @param {number} columns The number of columns in the image.\n * @param {boolean} shouldErase = false Whether we should erase rather than color pixels.\n * @returns {null}\n */\nfunction drawBrushPixels(\n pointerArray,\n pixelData,\n segmentIndex,\n columns,\n shouldErase = false\n) {\n const getPixelIndex = (x, y) => y * columns + x;\n\n pointerArray.forEach(point => {\n const spIndex = getPixelIndex(...point);\n\n if (shouldErase) {\n eraseIfSegmentIndex(spIndex, pixelData, segmentIndex);\n } else {\n pixelData[spIndex] = segmentIndex;\n }\n });\n}\n\nexport { drawBrushPixels };\n","import eraseIfSegmentIndex from './eraseIfSegmentIndex';\n\n/**\n * EraseOutsideBoundingBox - Erase all pixels labeled with the activeSegmentIndex,\n * outside the bouding box defined by the `topLeft` and `topRight`.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @param {number[]} topLeft The top left of the bounding box.\n * @param {number[]} bottomRight The bottom right of the bounding box.\n * @returns {null}\n */\nexport default function eraseOutsideBoundingBox(\n evt,\n operationData,\n topLeft,\n bottomRight\n) {\n const eventData = evt.detail;\n const { pixelData, segmentIndex } = operationData;\n const { image } = eventData;\n const { width, height } = image;\n\n // Loop until top of bounding box from top of image, color the entire row\n for (let i = 0; i < width; i++) {\n for (let j = 0; j < topLeft[1]; j++) {\n eraseIfSegmentIndex(j * width + i, pixelData, segmentIndex);\n }\n }\n\n // Loop within rows of bounding box, to the left of the box\n for (let i = 0; i < topLeft[0]; i++) {\n for (let j = topLeft[1]; j < bottomRight[1]; j++) {\n eraseIfSegmentIndex(j * width + i, pixelData, segmentIndex);\n }\n }\n\n // Loop within rows of bounding box, to the right of the box\n for (let i = bottomRight[0]; i < width; i++) {\n for (let j = topLeft[1]; j < bottomRight[1]; j++) {\n eraseIfSegmentIndex(j * width + i, pixelData, segmentIndex);\n }\n }\n\n // Loop from bottom of bounding box until bottom of image, color entire row\n for (let i = 0; i < width; i++) {\n for (let j = bottomRight[1]; j < height; j++) {\n eraseIfSegmentIndex(j * width + i, pixelData, segmentIndex);\n }\n }\n}\n","/**\n * Returns true if the pixelIndex of pixelData is the same as the segmentIndex.\n *\n * @param {number} pixelIndex The index of the pixel.\n * @param {UInt16Array} pixelData The pixelData array.\n * @param {number} segmentIndex The segment Index to erase.\n *\n * @returns {boolean}\n */\nexport default function isSameSegment(pixelIndex, pixelData, segmentIndex) {\n return pixelData[pixelIndex] === segmentIndex;\n}\n","import eraseOutsideBoundingBox from './eraseOutsideBoundingBox';\nimport isSameSegment from './isSameSegment.js';\n\nimport { getLogger } from '../logger.js';\n\nconst logger = getLogger('util:segmentation:operations:eraseOutsideCircle');\n\n/**\n * Erase all pixels labeled with the activeSegmentIndex,\n * inside/outside the region defined by the shape.\n * @param {Object} evt The Cornerstone event.\n * @param {Object} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @param {Object} pointInShape - A function that checks if a point, x,y is within a shape.\n * @param {number[]} topLeft The top left of the bounding box.\n * @param {number[]} bottomRight The bottom right of the bounding box.\n * @returns {null}\n */\nfunction eraseShape(\n evt,\n operationData,\n pointInShape,\n topLeft,\n bottomRight,\n insideOrOutside = 'inside'\n) {\n const { width } = evt.detail.image;\n const { pixelData, segmentIndex } = operationData;\n const [xMin, yMin] = topLeft;\n const [xMax, yMax] = bottomRight;\n\n if (insideOrOutside === 'outside') {\n eraseOutsideBoundingBox(evt, operationData, topLeft, bottomRight);\n }\n\n for (let x = xMin; x < xMax; x++) {\n for (let y = yMin; y < yMax; y++) {\n const pixelIndex = y * width + x;\n\n // If the pixel is the same segmentIndex and is inside the\n // Region defined by the array of points, set their value to segmentIndex.\n if (\n isSameSegment(pixelIndex, pixelData, segmentIndex) &&\n pointInShape({\n x,\n y,\n })\n ) {\n pixelData[pixelIndex] = 0;\n }\n }\n }\n}\n\n/**\n * Erase all pixels labeled with the activeSegmentIndex,\n * inside the region defined by the shape.\n * @param {Object} evt The Cornerstone event.\n * @param {Object} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @param {Object} pointInShape - A function that checks if a point, x,y is within a shape.\n * @param {number[]} topLeft The top left of the bounding box.\n * @param {number[]} bottomRight The bottom right of the bounding box.\n * @returns {null}\n */\nexport function eraseInsideShape(\n evt,\n operationData,\n pointInShape,\n topLeft,\n bottomRight\n) {\n eraseShape(evt, operationData, pointInShape, topLeft, bottomRight, 'inside');\n}\n\n/**\n * Erase all pixels labeled with the activeSegmentIndex,\n * outside the region defined by the shape.\n * @param {Object} evt The Cornerstone event.\n * @param {Object} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @param {Object} pointInShape - A function that checks if a point, x,y is within a shape.\n * @param {number[]} topLeft The top left of the bounding box.\n * @param {number[]} bottomRight The bottom right of the bounding box.\n * @returns {null}\n */\nexport function eraseOutsideShape(\n evt,\n operationData,\n pointInShape,\n topLeft,\n bottomRight\n) {\n eraseShape(\n evt,\n operationData,\n point => !pointInShape(point),\n topLeft,\n bottomRight,\n 'outside'\n );\n}\n","/**\n * EraseInside - fill all pixels labeled with the activeSegmentIndex,\n * outside the bouding box defined by the `topLeft` and `topRight`.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @param {number[]} topLeft The top left of the bounding box.\n * @param {number[]} bottomRight The bottom right of the bounding box.\n * @returns {null}\n */\nexport default function fillOutsideBoundingBox(\n evt,\n operationData,\n topLeft,\n bottomRight\n) {\n const { pixelData, segmentIndex } = operationData;\n const { width, height } = evt.detail.image;\n\n // Loop until top of bounding box from top of image, color the entire row\n for (let i = 0; i < width; i++) {\n for (let j = 0; j < topLeft[1]; j++) {\n pixelData[j * width + i] = segmentIndex;\n }\n }\n\n // Loop within rows of bounding box, to the left of the box\n for (let i = 0; i < topLeft[0]; i++) {\n for (let j = topLeft[1]; j < bottomRight[1]; j++) {\n pixelData[j * width + i] = segmentIndex;\n }\n }\n\n // Loop within rows of bounding box, to the right of the box\n for (let i = bottomRight[0]; i < width; i++) {\n for (let j = topLeft[1]; j < bottomRight[1]; j++) {\n pixelData[j * width + i] = segmentIndex;\n }\n }\n\n // Loop from bottom of bounding box until bottom of image, color entire row\n for (let i = 0; i < width; i++) {\n for (let j = bottomRight[1]; j < height; j++) {\n pixelData[j * width + i] = segmentIndex;\n }\n }\n}\n","import fillOutsideBoundingBox from './fillOutsideBoundingBox';\nimport { getLogger } from '../logger.js';\n\nconst logger = getLogger('util:segmentation:operations:helpers:fillShape');\n\n/**\n * Fill all pixels labeled with the activeSegmentIndex,\n * inside/outside the region defined by the shape.\n * @param {Object} evt The Cornerstone event.\n * @param {Object} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @param {Object} pointInShape - A function that checks if a point, x,y is within a shape.\n * @param {number[]} topLeft The top left of the bounding box.\n * @param {number[]} bottomRight The bottom right of the bounding box.\n * @returns {null}\n */\nfunction fillShape(\n evt,\n operationData,\n pointInShape,\n topLeft,\n bottomRight,\n insideOrOutside = 'inside'\n) {\n const { pixelData, segmentIndex } = operationData;\n\n if (pixelData === undefined || segmentIndex === undefined) {\n logger.error(\n `fillInsideShape requires operationData to contain pixelData and segmentIndex`\n );\n\n return;\n }\n\n const { width } = evt.detail.image;\n const [xMin, yMin] = topLeft;\n const [xMax, yMax] = bottomRight;\n\n if (insideOrOutside === 'outside') {\n fillOutsideBoundingBox(evt, operationData, topLeft, bottomRight);\n }\n\n for (let x = xMin; x < xMax; x++) {\n for (let y = yMin; y < yMax; y++) {\n const pixelIndex = y * width + x;\n\n // If the pixel is the same segmentIndex and is inside the\n // Region defined by the array of points, set their value to segmentIndex.\n if (\n pointInShape({\n x,\n y,\n })\n ) {\n pixelData[pixelIndex] = segmentIndex;\n }\n }\n }\n}\n\n/**\n * Fill all pixels labeled with the activeSegmentIndex,\n * inside the region defined by the shape.\n * @param {Object} evt The Cornerstone event.\n * @param {Object} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @param {Object} pointInShape - A function that checks if a point, x,y is within a shape.\n * @param {number[]} topLeft The top left of the bounding box.\n * @param {number[]} bottomRight The bottom right of the bounding box.\n * @returns {null}\n */\nexport function fillInsideShape(\n evt,\n operationData,\n pointInShape,\n topLeft,\n bottomRight\n) {\n fillShape(evt, operationData, pointInShape, topLeft, bottomRight, 'inside');\n}\n\n/**\n * Fill all pixels labeled with the activeSegmentIndex,\n * outside the region defined by the shape.\n * @param {Object} evt The Cornerstone event.\n * @param {Object} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @param {Object} pointInShape - A function that checks if a point, x,y is within a shape.\n * @param {number[]} topLeft The top left of the bounding box.\n * @param {number[]} bottomRight The bottom right of the bounding box.\n * @returns {null}\n */\nexport function fillOutsideShape(\n evt,\n operationData,\n pointInShape,\n topLeft,\n bottomRight\n) {\n fillShape(\n evt,\n operationData,\n point => !pointInShape(point),\n topLeft,\n bottomRight,\n 'outside'\n );\n}\n","/**\n * floodFill.js - Taken from MIT OSS lib - https://github.com/tuzz/n-dimensional-flood-fill\n * Refactored to ES6.\n *\n * @param {function} getter The getter to the elements of your data structure,\n * e.g. getter(x,y) for a 2D interprettation of your structure.\n * @param {number[]} seed The seed for your fill. The dimensionality is infered\n * by the number of dimensions of the seed.\n * @param {function} [options.onFlood] An optional callback to execute when each pixel is flooded.\n * e.g. onFlood(x,y).\n * @param {function} [options.onBoundary] An optional callback to execute whenever a boundary is reached.\n * a boundary could be another segmentIndex, or the edge of your\n * data structure (i.e. when your getter returns undefined).\n * @param {function} [options.equals] An optional equality method for your datastructure.\n * Default is simply value1 = value2.\n * @param {boolean} [options.diagonals] Whether you allow flooding through diagonals. Defaults to false.\n *\n * @returns {Object}\n */\nexport default function(getter, seed, options = {}) {\n const onFlood = options.onFlood || function() {};\n const onBoundary = options.onBoundary || function() {};\n const equals = options.equals || defaultEquals;\n const diagonals = options.diagonals || false;\n const startNode = get(seed);\n const permutations = prunedPermutations();\n const stack = [];\n const flooded = [];\n const visits = {};\n const bounds = {};\n\n stack.push({ currentArgs: seed });\n\n while (stack.length > 0) {\n flood(stack.pop());\n }\n\n return {\n flooded,\n boundaries: boundaries(),\n };\n\n function flood(job) {\n const getArgs = job.currentArgs;\n const prevArgs = job.previousArgs;\n\n if (visited(getArgs)) {\n return;\n }\n markAsVisited(getArgs);\n\n if (member(getArgs)) {\n markAsFlooded(getArgs);\n pushAdjacent(getArgs);\n } else {\n markAsBoundary(prevArgs);\n }\n }\n\n function visited(key) {\n return visits[key] === true;\n }\n\n function markAsVisited(key) {\n visits[key] = true;\n }\n\n function member(getArgs) {\n const node = safely(get, [getArgs]);\n\n return safely(equals, [node, startNode]);\n }\n\n function markAsFlooded(getArgs) {\n flooded.push(getArgs);\n onFlood(...getArgs);\n }\n\n function markAsBoundary(prevArgs) {\n bounds[prevArgs] = prevArgs;\n onBoundary(...prevArgs);\n }\n\n function pushAdjacent(getArgs) {\n for (let i = 0; i < permutations.length; i += 1) {\n const perm = permutations[i];\n const nextArgs = getArgs.slice(0);\n\n for (let j = 0; j < getArgs.length; j += 1) {\n nextArgs[j] += perm[j];\n }\n\n stack.push({\n currentArgs: nextArgs,\n previousArgs: getArgs,\n });\n }\n }\n\n function get(getArgs) {\n return getter(...getArgs);\n }\n\n function safely(f, args) {\n try {\n return f(...args);\n } catch (error) {\n return;\n }\n }\n\n function prunedPermutations() {\n const permutations = permute(seed.length);\n\n return permutations.filter(function(perm) {\n const count = countNonZeroes(perm);\n\n return count !== 0 && (count === 1 || diagonals);\n });\n }\n\n function permute(length) {\n const perms = [];\n\n const permutation = function(string) {\n return string.split('').map(function(c) {\n return parseInt(c, 10) - 1;\n });\n };\n\n for (let i = 0; i < Math.pow(3, length); i += 1) {\n const string = lpad(i.toString(3), '0', length);\n\n perms.push(permutation(string));\n }\n\n return perms;\n }\n\n function boundaries() {\n const array = [];\n\n for (const key in bounds) {\n if (bounds.hasOwnProperty(key)) {\n array.unshift(bounds[key]);\n }\n }\n\n return array;\n }\n}\n\nfunction defaultEquals(a, b) {\n return a === b;\n}\n\nfunction countNonZeroes(array) {\n let count = 0;\n\n for (let i = 0; i < array.length; i += 1) {\n if (array[i] !== 0) {\n count += 1;\n }\n }\n\n return count;\n}\n\nfunction lpad(string, character, length) {\n const array = new Array(length + 1);\n const pad = array.join(character);\n\n return (pad + string).slice(-length);\n}\n","import external from '../externalModules';\n\n/**\n * Retrieve the bounds of the circle in image coordinates\n *\n * @param {*} startHandle\n * @param {*} endHandle\n * @returns {{ left: number, top: number, width: number, height: number }}\n */\nexport default function getCircleCoords(startHandle, endHandle) {\n const { distance } = external.cornerstoneMath.point;\n const radius = distance(startHandle, endHandle);\n\n return {\n left: Math.floor(Math.min(startHandle.x - radius, endHandle.x)),\n top: Math.floor(Math.min(startHandle.y - radius, endHandle.y)),\n width: radius * 2,\n height: radius * 2,\n };\n}\n","import getCircleCoords from '../getCircleCoords';\n\nexport default function getBoundingBoxAroundCircle(evt) {\n const { handles } = evt.detail;\n const { width: imageWidth, height: imageHeight } = evt.detail.image;\n const circleCoordinates = getCircleCoords(handles.start, handles.end);\n\n let xMax = circleCoordinates.width + circleCoordinates.left;\n let xMin = circleCoordinates.left;\n let yMax = circleCoordinates.top + circleCoordinates.height;\n let yMin = circleCoordinates.top;\n\n xMin = Math.floor(xMin);\n yMin = Math.floor(yMin);\n xMax = Math.floor(xMax);\n yMax = Math.floor(yMax);\n\n xMax = Math.min(imageWidth, xMax);\n xMin = Math.max(0, xMin);\n yMax = Math.min(imageHeight, yMax);\n yMin = Math.max(0, yMin);\n\n return [[xMin, yMin], [xMax, yMax]];\n}\n","export default function getBoundingBoxAroundPolygon(vertices, image) {\n let xMin = Infinity;\n let xMax = 0;\n let yMin = Infinity;\n let yMax = 0;\n const { width, height } = image;\n\n vertices.forEach(v => {\n xMin = Math.min(v[0], xMin);\n xMax = Math.max(v[0], xMax);\n yMin = Math.min(v[1], yMin);\n yMax = Math.max(v[1], yMax);\n });\n\n xMin = Math.floor(xMin);\n yMin = Math.floor(yMin);\n xMax = Math.floor(xMax);\n yMax = Math.floor(yMax);\n\n xMax = Math.min(width, xMax);\n xMin = Math.max(0, xMin);\n yMax = Math.min(height, yMax);\n yMin = Math.max(0, yMin);\n\n return [[xMin, yMin], [xMax, yMax]];\n}\n","/**\n * Gets the pixels within the circle.\n * @export @public @method\n * @name getCircle\n *\n * @param {number} radius The radius of the circle.\n * @param {number} rows The number of rows.\n * @param {number} columns The number of columns.\n * @param {number} [xCoord = 0] The x-location of the center of the circle.\n * @param {number} [yCoord = 0] The y-location of the center of the circle.\n * @returns {Array.number[]} Array of pixels contained within the circle.\n */\nexport default function getCircle(\n radius,\n rows,\n columns,\n xCoord = 0,\n yCoord = 0\n) {\n const x0 = Math.floor(xCoord);\n const y0 = Math.floor(yCoord);\n\n if (radius === 1) {\n return [[x0, y0]];\n }\n\n const circleArray = [];\n let index = 0;\n\n for (let y = -radius; y <= radius; y++) {\n const yCoord = y0 + y;\n\n if (yCoord > rows || yCoord < 0) {\n continue;\n }\n\n for (let x = -radius; x <= radius; x++) {\n const xCoord = x0 + x;\n\n if (xCoord >= columns || xCoord < 0) {\n continue;\n }\n\n if (x * x + y * y < radius * radius) {\n circleArray[index++] = [x0 + x, y0 + y];\n }\n }\n }\n\n return circleArray;\n}\n","import external from '../../externalModules.js';\n\nconst oneOverRoot2 = 1 / Math.sqrt(2); // Cache this to avoid repeated computation.\n\nconst DIRECTIONS = {\n up: {\n x: 0,\n y: 1,\n },\n upRight: {\n x: oneOverRoot2,\n y: oneOverRoot2,\n },\n right: {\n x: 1,\n y: 0,\n },\n downRight: {\n x: oneOverRoot2,\n y: -oneOverRoot2,\n },\n down: {\n x: 0,\n y: 1,\n },\n downLeft: {\n x: -oneOverRoot2,\n y: -oneOverRoot2,\n },\n left: {\n x: -1,\n y: 0,\n },\n upLeft: {\n x: -oneOverRoot2,\n y: oneOverRoot2,\n },\n};\n\n/**\n * GetPixelPathBetweenPixels - Generates a 1-pixel wide path of pixels between two pixels.\n * This is essentially simplified A* pathfinding, as we know there are no \"obstacles\".\n *\n * @param {Object} p1 The starting pixel\n * @param {Object} p2 The end pixel.\n *\n * @returns {Object[]} All of the pixels on the shortest path between p1 and p2.\n */\nexport default function(p1, p2) {\n const p = {\n x: p1.x,\n y: p1.y,\n };\n\n const path = [];\n\n while (p2.x !== p.x || p2.y !== p.y) {\n if (p2.x === p.x) {\n // Goal is above or bellow us.\n if (p2.y > p.y) {\n p.y++;\n } else {\n p.y--;\n }\n } else if (p2.y === p.y) {\n // Goal is to the left or right of us.\n if (p2.x > p.x) {\n p.x++;\n } else {\n p.x--;\n }\n } else if (p2.y > p.y) {\n if (p2.x > p.x) {\n // Can go up, right or diagonally up-right towards goal.\n moveUpRight(p, p2);\n } else {\n // Can go up, left, or diagonally up-left towards goal.\n moveUpLeft(p, p2);\n }\n } else if (p2.x > p.x) {\n // Can go down, right, or diagonally down-right towards goal.\n moveDownRight(p, p2);\n } else {\n // Can go down, left, or diagonally down-left towards goal.\n moveDownLeft(p, p2);\n }\n\n path.push({\n x: p.x,\n y: p.y,\n });\n }\n\n path.pop(); // Remove last node as is the same as the destination.\n\n return path;\n}\n\n/**\n * MoveUpRight - Moves p up, right or diagonally up right towards p2.\n * @param {Object} p\n * @param {Object} p2\n *\n * @returns {null}\n */\nfunction moveUpRight(p, p2) {\n const unitVector = unitVectorFromPtoP2(p, p2);\n\n // Largest dot product is fastest way to travel.\n const dotProducts = [\n dotProduct2D(unitVector, DIRECTIONS.up),\n dotProduct2D(unitVector, DIRECTIONS.right),\n dotProduct2D(unitVector, DIRECTIONS.upRight),\n ];\n\n const largestIndex = getIndexOfLargestInLengthThreeArray(dotProducts);\n\n switch (largestIndex) {\n case 0:\n p.y++;\n break;\n case 1:\n p.x++;\n break;\n case 2:\n p.y++;\n p.x++;\n }\n}\n\n/**\n * MoveUpLeft - Moves p up, left or diagonally up left towards p2.\n * @param {Object} p\n * @param {Object} p2\n *\n * @returns {null}\n */\nfunction moveUpLeft(p, p2) {\n const unitVector = unitVectorFromPtoP2(p, p2);\n\n // Largest dot product is fastest way to travel.\n const dotProducts = [\n dotProduct2D(unitVector, DIRECTIONS.up),\n dotProduct2D(unitVector, DIRECTIONS.left),\n dotProduct2D(unitVector, DIRECTIONS.upLeft),\n ];\n\n const largestIndex = getIndexOfLargestInLengthThreeArray(dotProducts);\n\n switch (largestIndex) {\n case 0:\n p.y++;\n break;\n case 1:\n p.x--;\n break;\n case 2:\n p.y++;\n p.x--;\n }\n}\n\n/**\n * MoveDownRight - Moves p down, right or diagonally down right towards p2.\n * @param {Object} p\n * @param {Object} p2\n *\n * @returns {null}\n */\nfunction moveDownRight(p, p2) {\n const unitVector = unitVectorFromPtoP2(p, p2);\n\n // Largest dot product is fastest way to travel.\n const dotProducts = [\n dotProduct2D(unitVector, DIRECTIONS.down),\n dotProduct2D(unitVector, DIRECTIONS.right),\n dotProduct2D(unitVector, DIRECTIONS.downRight),\n ];\n\n const largestIndex = getIndexOfLargestInLengthThreeArray(dotProducts);\n\n switch (largestIndex) {\n case 0:\n p.y--;\n break;\n case 1:\n p.x++;\n break;\n case 2:\n p.y--;\n p.x++;\n }\n}\n\n/**\n * MoveDownLeft - Moves p down, left or diagonally down left towards p2.\n * @param {Object} p\n * @param {Object} p2\n *\n * @returns {null}\n */\nfunction moveDownLeft(p, p2) {\n const unitVector = unitVectorFromPtoP2(p, p2);\n\n // Largest dot product is fastest way to travel.\n const dotProducts = [\n dotProduct2D(unitVector, DIRECTIONS.down),\n dotProduct2D(unitVector, DIRECTIONS.left),\n dotProduct2D(unitVector, DIRECTIONS.downLeft),\n ];\n\n const largestIndex = getIndexOfLargestInLengthThreeArray(dotProducts);\n\n switch (largestIndex) {\n case 0:\n p.y--;\n break;\n case 1:\n p.x--;\n break;\n case 2:\n p.y--;\n p.x--;\n }\n}\n\n/**\n * UnitVectorFromPtoP2 - Returns a unit vector pointing from p to p2.\n * @param {Object} p\n * @param {Object} p2\n *\n * @returns {Object} The unit vector.\n */\nfunction unitVectorFromPtoP2(p, p2) {\n const distance = external.cornerstoneMath.point.distance(p, p2);\n\n return {\n x: (p2.x - p.x) / distance,\n y: (p2.y - p.y) / distance,\n };\n}\n\nfunction dotProduct2D(p, p2) {\n return p.x * p2.x + p.y * p2.y;\n}\n\n/**\n * GetIndexOfLargestInLengthThreeArray - Returns the index of the largest value\n * in the 3 element array.\n * @param {number[]} array\n * @returns {number}\n */\nfunction getIndexOfLargestInLengthThreeArray(array) {\n let largestIndex = array[0] > array[1] ? 0 : 1;\n\n if (array[2] > array[largestIndex]) {\n largestIndex = 2;\n }\n\n return largestIndex;\n}\n","import external from '../../externalModules';\nimport EVENTS from '../../events.js';\nimport { getModule } from '../../store';\n\n/**\n * Triggers the LABELMAP_MODIFIED event for the active element, providing the labelmapIndex that was modified.\n *\n * @param {HTMLElement} element\n * @param {number} labelmapIndex The labelmapIndex. Defaults to the active for that element if not set.\n */\nexport default function triggerLabelmapModifiedEvent(element, labelmapIndex) {\n const { getters } = getModule('segmentation');\n\n labelmapIndex =\n labelmapIndex === undefined\n ? getters.activeLabelmapIndex(element)\n : labelmapIndex;\n\n external.cornerstone.triggerEvent(element, EVENTS.LABELMAP_MODIFIED, {\n labelmapIndex,\n });\n}\n","export default function getDiffBetweenPixelData(\n previousPixelData,\n newPixelData\n) {\n const diff = [];\n\n for (let i = 0; i < previousPixelData.length; i++) {\n if (previousPixelData[i] !== newPixelData[i]) {\n diff.push([i, previousPixelData[i], newPixelData[i]]);\n }\n }\n\n return diff;\n}\n","import getElement from './getElement';\nimport { getToolState } from '../../../stateManagement/toolState.js';\nimport state from './state';\nimport getSegmentsOnPixelData from './getSegmentsOnPixeldata';\nimport { triggerLabelmapModifiedEvent } from '../../../util/segmentation';\n\n/**\n * Takes a 16-bit encoded `ArrayBuffer` and stores it as a `Labelmap3D` for the\n * `BrushStackState` associated with the element.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone\n * enabled element or its UUID.\n * @param {ArrayBuffer} buffer\n * @param {number} labelmapIndex The index to store the labelmap under.\n * @param {Object[]} metadata = [] Any metadata about the segments.\n * @param {number[][]} [segmentsOnLabelmapArray] An array of array of segments on each imageIdIndex.\n * If not present, is calculated.\n * @param {colorLUTIndex} [colorLUTIndex = 0] The index of the colorLUT to use to render the segmentation.\n * @returns {null}\n */\nfunction setLabelmap3DForElement(\n elementOrEnabledElementUID,\n buffer,\n labelmapIndex,\n metadata = [],\n segmentsOnLabelmapArray,\n colorLUTIndex = 0\n) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n const numberOfFrames = stackState.data[0].imageIds.length;\n const firstImageId = stackState.data[0].imageIds[0];\n\n setLabelmap3DByFirstImageId(\n firstImageId,\n buffer,\n labelmapIndex,\n metadata,\n numberOfFrames,\n segmentsOnLabelmapArray,\n colorLUTIndex\n );\n\n triggerLabelmapModifiedEvent(element, labelmapIndex);\n}\n\n/**\n * Takes an 16-bit encoded `ArrayBuffer` and stores it as a `Labelmap3D` for\n * the `BrushStackState` associated with the firstImageId.\n *\n * @param {HTMLElement|string} firstImageId The firstImageId of the series to\n * store the segmentation on.\n * @param {ArrayBuffer} buffer\n * @param {number} labelmapIndex The index to store the labelmap under.\n * @param {Object[]} metadata = [] Any metadata about the segments.\n * @param {number} numberOfFrames The number of frames, required to set up the\n * relevant labelmap2D views.\n * @param {number[][]} [segmentsOnLabelmapArray] An array of array of segments on each imageIdIndex.\n * If not present, is calculated.\n * @param {colorLUTIndex} [colorLUTIndex = 0] The index of the colorLUT to use to render the segmentation.\n * @returns {null}\n */\nfunction setLabelmap3DByFirstImageId(\n firstImageId,\n buffer,\n labelmapIndex,\n metadata = [],\n numberOfFrames,\n segmentsOnLabelmapArray,\n colorLUTIndex = 0\n) {\n let brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n state.series[firstImageId] = {\n activeLabelmapIndex: labelmapIndex,\n labelmaps3D: [],\n };\n\n brushStackState = state.series[firstImageId];\n }\n\n brushStackState.labelmaps3D[labelmapIndex] = {\n buffer,\n labelmaps2D: [],\n metadata,\n activeSegmentIndex: 1,\n colorLUTIndex: 0,\n segmentsHidden: [],\n undo: [],\n redo: [],\n };\n\n const labelmaps2D = brushStackState.labelmaps3D[labelmapIndex].labelmaps2D;\n const slicelengthInBytes = buffer.byteLength / numberOfFrames;\n const sliceLengthInUint16 = slicelengthInBytes / 2; // SliceLength in Uint16.\n\n for (let i = 0; i < numberOfFrames; i++) {\n const pixelData = new Uint16Array(\n buffer,\n slicelengthInBytes * i,\n sliceLengthInUint16\n );\n\n const segmentsOnLabelmap = segmentsOnLabelmapArray\n ? segmentsOnLabelmapArray[i]\n : getSegmentsOnPixelData(pixelData);\n\n if (segmentsOnLabelmap && segmentsOnLabelmap.some(segment => segment)) {\n labelmaps2D[i] = {\n pixelData,\n segmentsOnLabelmap,\n };\n }\n }\n}\n\nexport { setLabelmap3DByFirstImageId, setLabelmap3DForElement };\n","import getElement from './getElement';\nimport { getToolState } from '../../../stateManagement/toolState.js';\nimport state from './state';\nimport external from '../../../externalModules';\n\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger('store:modules:segmentationModule:getLabelmapStats');\n\n/**\n * Returns the maximum pixel value, mean and standard deviation of the segment\n * given by the `segmentIndex` and `labelmapIndex`.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {number} segmentIndex The segment index to query.\n * @param {number} labelmapIndex The `labelmapIndex` of the `Labelmap3D` to query.\n * Defaults to the activeLabelmapIndex if not given.\n * @returns {Promise|null} A promise that resolves to an object containing\n * the maximum pixel value, the mean and the standard deviation.\n * Returns null if no cornerstone element is found.\n */\nexport default function getLabelmapStats(\n elementOrEnabledElementUID,\n segmentIndex,\n labelmapIndex\n) {\n const cornerstone = external.cornerstone;\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return null;\n }\n\n const stackState = getToolState(element, 'stack');\n const imageIds = stackState.data[0].imageIds;\n const firstImageId = imageIds[0];\n\n return new Promise(resolve => {\n const brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n resolve(null);\n }\n\n const { sufficientMetadata, imagePlanes } = _getImagePlanes(imageIds);\n\n if (!sufficientMetadata) {\n logger.warn(\n 'Insufficient imagePlaneModule information to calculate volume statistics.'\n );\n resolve(null);\n }\n\n labelmapIndex =\n labelmapIndex === undefined\n ? brushStackState.activeLabelmapIndex\n : labelmapIndex;\n\n const labelmap3D = brushStackState.labelmaps3D[labelmapIndex];\n\n const imagePromises = [];\n\n for (let i = 0; i < imageIds.length; i++) {\n imagePromises.push(cornerstone.loadAndCacheImage(imageIds[i]));\n }\n\n Promise.all(imagePromises).then(images => {\n const stats = _calculateLabelmapStats(\n labelmap3D,\n images,\n imagePlanes,\n segmentIndex\n );\n\n resolve(stats);\n });\n });\n}\n\n/**\n *\n * @param {string[]} imageIds An array of cornerstone imageIds.\n * @returns {Object} An object containing an array of per-frame imagePlane metadata,\n * and a flag indicating if the metadata was present.\n */\nfunction _getImagePlanes(imageIds) {\n const imagePlanes = [];\n const cornerstone = external.cornerstone;\n const metadataProvider = cornerstone.metaData;\n\n let sufficientMetadata = true;\n\n for (let i = 0; i < imageIds.length; i++) {\n const imagePlaneModule = metadataProvider.get(\n 'imagePlaneModule',\n imageIds[i]\n );\n\n if (!imagePlaneModule) {\n sufficientMetadata = false;\n break;\n }\n\n imagePlanes.push(imagePlaneModule);\n }\n\n return { sufficientMetadata, imagePlanes };\n}\n\n/**\n *\n * @param {Labelmap3D} labelmap3D The labelmap3D object.\n * @param {Object[]} images An array of cornerstone images.\n * @param {Object[]} imagePlanes An array of the per-frame imagePlane metadata.\n * @param {number} segmentIndex\n *\n * @returns {Object} Statistics object containing the volume in mm^3; and the\n * min, max, mean and stdev of the segmented voxels.\n */\nexport function _calculateLabelmapStats(\n labelmap3D,\n images,\n imagePlanes,\n segmentIndex\n) {\n const voxelsPerFrame = _getVoxelsPerFrameForSegment(\n labelmap3D,\n images,\n imagePlanes,\n segmentIndex\n );\n\n let volumeWeightedMean = 0;\n let max = voxelsPerFrame[0].values[0];\n let min = max;\n let volume = 0;\n\n // Calculate Min, Max, volume and mean.\n for (let i = 0; i < voxelsPerFrame.length; i++) {\n const { values, voxelInMM3 } = voxelsPerFrame[i];\n\n volume += voxelInMM3 * values.length;\n\n let sum = 0;\n\n values.forEach(value => {\n if (value > max) {\n max = value;\n } else if (value < min) {\n min = value;\n }\n\n sum += value;\n });\n\n volumeWeightedMean += sum * voxelInMM3;\n }\n\n volumeWeightedMean /= volume;\n\n let volumeWeightedStDev = 0;\n\n // Calculate the volume weigthed standard deviation.\n for (let i = 0; i < voxelsPerFrame.length; i++) {\n const { values, voxelInMM3 } = voxelsPerFrame[i];\n\n let stdDevSum = 0;\n\n values.forEach(value => {\n stdDevSum += Math.pow(value - volumeWeightedMean, 2);\n });\n\n volumeWeightedStDev += stdDevSum * voxelInMM3;\n }\n\n volumeWeightedStDev /= volume;\n volumeWeightedStDev = Math.sqrt(volumeWeightedStDev);\n\n return {\n volume,\n mean: volumeWeightedMean,\n stdDev: volumeWeightedStDev,\n max,\n min,\n };\n}\n\n/**\n * Returns an array of voxel values masked by the segment for each frame,\n * as well as the real world volume of a voxel on that frame.\n *\n * @param {Labelmap3D} labelmap3D The `Labelmap3D` object.\n * @param {Object[]} images An array of cornerstone images.\n * @param {Object[]} imagePlanes An array of the per-frame imagePlane metadata.\n * @param {number} segmentIndex The index of the segment to check.\n *\n * @returns {Object[]} An array of voxel values and voxel volumes per frame.\n */\nfunction _getVoxelsPerFrameForSegment(\n labelmap3D,\n images,\n imagePlanes,\n segmentIndex\n) {\n const { rowPixelSpacing, columnPixelSpacing } = images[0];\n const labelmaps2D = labelmap3D.labelmaps2D;\n const voxelsPerFrame = [];\n\n for (let i = 0; i < labelmaps2D.length; i++) {\n const labelmap2D = labelmaps2D[i];\n\n if (labelmap2D && labelmap2D.segmentsOnLabelmap.includes(segmentIndex)) {\n const sliceThickness = _getSliceThickness(images, imagePlanes, i);\n const voxelInMM3 = sliceThickness * rowPixelSpacing * columnPixelSpacing;\n const segmentationPixelData = labelmap2D.pixelData;\n const imagePixelData = images[i].getPixelData();\n const values = [];\n\n // Iterate over segmentationPixelData and count voxels.\n for (let p = 0; p < segmentationPixelData.length; p++) {\n if (segmentationPixelData[p] === segmentIndex) {\n values.push(imagePixelData[p]);\n }\n }\n\n voxelsPerFrame.push({\n voxelInMM3,\n values,\n });\n }\n }\n\n return voxelsPerFrame;\n}\n\n/**\n * Estimates the slice thickness given the image position patient of adjacent frames.\n * For the edges the slice thickness is assumed to be the perpendicular distance to the closest frame.\n * For all other frames the slice thickness is taken to be the sum of half of the distance to the frame above and below.\n *\n * Voxels on the first or last frame are assumed to be full occupied.\n *\n * @param {Object[]} images An array of cornerstone images.\n * @param {Object[]} imagePlanes An array of the per-frame imagePlane metadata.\n * @param {number} frameIndex The index of the frame to get the slice thickness for.\n *\n * @returns {number}\n */\nfunction _getSliceThickness(images, imagePlanes, frameIndex) {\n const numberOfSlices = images.length;\n const ipp = imagePlanes[frameIndex].imagePositionPatient;\n\n // Special cases: Edge of volume - Assume thickness is the distance\n // between the current slice and the closest slice as this is all the information we have.\n if (frameIndex === 0) {\n const ippAbove = imagePlanes[frameIndex + 1].imagePositionPatient;\n\n return distanceBetweenSlices(ipp, ippAbove);\n } else if (frameIndex === numberOfSlices - 1) {\n const ippBelow = imagePlanes[frameIndex - 1].imagePositionPatient;\n\n return distanceBetweenSlices(ipp, ippBelow);\n }\n\n // Estimate slice thickness from the two adjacent slices.\n const ippBelow = imagePlanes[frameIndex - 1].imagePositionPatient;\n const ippAbove = imagePlanes[frameIndex + 1].imagePositionPatient;\n\n return (\n (distanceBetweenSlices(ipp, ippBelow) +\n distanceBetweenSlices(ipp, ippAbove)) /\n 2\n );\n}\n\n/**\n * Returns the ditance between two imagePostionPatient coordinates.\n *\n * @param {number[]} ipp1 The first image position patient array.\n * @param {number[]} ipp2 The second image position patient array.\n */\nfunction distanceBetweenSlices(ipp1, ipp2) {\n return Math.sqrt(\n Math.pow(ipp1[0] - ipp2[0], 2) +\n Math.pow(ipp1[1] - ipp2[1], 2) +\n Math.pow(ipp1[2] - ipp2[2], 2)\n );\n}\n","/**\n * Adds a `Labelmap2D` view of one frame of a `Labelmap3D`.\n *\n * @param {BrushStackState} brushStackState The `BrushStackState` for a particular `Series`.\n * @param {number} labelmapIndex The labelmap index.\n * @param {number} imageIdIndex The stack position of the image.\n * @param {number} rows The number of rows in the image.\n * @param {number} columns The number of columns in the image.\n * @returns {null}\n */\nexport default function addLabelmap2D(\n brushStackState,\n labelmapIndex,\n imageIdIndex,\n rows,\n columns\n) {\n const sliceLength = rows * columns;\n const byteOffset = sliceLength * 2 * imageIdIndex; // 2 bytes/pixel\n\n const pixelData = new Uint16Array(\n brushStackState.labelmaps3D[labelmapIndex].buffer,\n byteOffset,\n sliceLength\n );\n\n brushStackState.labelmaps3D[labelmapIndex].labelmaps2D[imageIdIndex] = {\n pixelData,\n segmentsOnLabelmap: [],\n };\n}\n","import getElement from './getElement';\nimport { getToolState } from '../../../stateManagement/toolState.js';\nimport getSegmentsOnPixelData from './getSegmentsOnPixeldata';\nimport addLabelmap3D from './addLabelmap3D';\nimport addLabelmap2D from './addLabelmap2D';\nimport external from '../../../externalModules';\nimport state from './state';\n\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger('store:modules:segmentationModule:getLabelmap2D');\n\n/**\n * Returns the active `labelmap3D` and the `currentImageIdIndex`. If a labelmap does\n * not get exist, creates a new one. Generates a `labelmap2D` for the `currentImageIndex`\n * if it does not yet exist.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @returns {Object} The `Labelmap2D`, `Labelmap3D`, `activeLabelmapIndex` and `currentImageIdIndex`.\n */\nexport default function getLabelmap2D(elementOrEnabledElementUID) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n const stackState = getToolState(element, 'stack');\n\n if (!stackState) {\n logger.error(\n 'Consumers must define stacks in their application if using segmentations in cornerstoneTools.'\n );\n\n return;\n }\n\n const stackData = stackState.data[0];\n\n const enabledElement = cornerstone.getEnabledElement(element);\n\n const currentImageIdIndex = stackData.currentImageIdIndex;\n const { rows, columns } = enabledElement.image;\n\n const numberOfFrames = stackData.imageIds.length;\n const firstImageId = stackData.imageIds[0];\n\n let brushStackState = state.series[firstImageId];\n\n let activeLabelmapIndex;\n\n if (brushStackState) {\n activeLabelmapIndex = brushStackState.activeLabelmapIndex;\n\n if (!brushStackState.labelmaps3D[activeLabelmapIndex]) {\n const size = rows * columns * numberOfFrames;\n\n addLabelmap3D(brushStackState, activeLabelmapIndex, size);\n }\n\n if (\n !brushStackState.labelmaps3D[activeLabelmapIndex].labelmaps2D[\n currentImageIdIndex\n ]\n ) {\n addLabelmap2D(\n brushStackState,\n activeLabelmapIndex,\n currentImageIdIndex,\n rows,\n columns\n );\n }\n } else {\n activeLabelmapIndex = 0;\n\n state.series[firstImageId] = {\n activeLabelmapIndex,\n labelmaps3D: [],\n };\n\n brushStackState = state.series[firstImageId];\n\n const size = rows * columns * numberOfFrames;\n\n addLabelmap3D(brushStackState, activeLabelmapIndex, size);\n\n addLabelmap2D(\n brushStackState,\n activeLabelmapIndex,\n currentImageIdIndex,\n rows,\n columns\n );\n }\n\n const labelmap3D = brushStackState.labelmaps3D[activeLabelmapIndex];\n\n return {\n labelmap2D: labelmap3D.labelmaps2D[currentImageIdIndex],\n labelmap3D,\n currentImageIdIndex,\n activeLabelmapIndex,\n };\n}\n\n/**\n * Returns a `Labelmap2D` view of a `Labelmap3D` for the given `imageIdIndex`.\n * Creates and caches it if it doesn't yet exist.\n *\n * @param {Labelmap3D} labelmap3D The `Labelmap3D` object.\n * @param {number} imageIdIndex The imageId Index.\n * @param {number} rows The number of rows.\n * @param {number} columns The number of columns.\n * @returns {null}\n */\nexport function getLabelmap2DByImageIdIndex(\n labelmap3D,\n imageIdIndex,\n rows,\n columns\n) {\n if (!labelmap3D.labelmaps2D[imageIdIndex]) {\n const sliceLength = rows * columns;\n const byteOffset = sliceLength * 2 * imageIdIndex; // 2 bytes/pixel\n\n const pixelData = new Uint16Array(\n labelmap3D.buffer,\n byteOffset,\n sliceLength\n );\n\n labelmap3D.labelmaps2D[imageIdIndex] = {\n pixelData,\n segmentsOnLabelmap: getSegmentsOnPixelData(pixelData),\n };\n }\n\n return labelmap3D.labelmaps2D[imageIdIndex];\n}\n","/**\n * Checks if the point is within the image boundaries.\n * @param {Object} pixel The pixel.\n * @param {number} rows The number of rows.\n * @param {number} cols The number of columns.\n * @returns {boolean}\n */\nexport default function isPointInImage({ x, y }, rows, cols) {\n return x < cols && x >= 0 && y < rows && y >= 0;\n}\n","import { getToolState } from '../../../stateManagement/toolState.js';\nimport state from './state';\nimport isPointInImage from '../../../util/isPointInImage';\n\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger(\n 'store:modules:segmentationModule:getSegmentOfActiveLabelmapAtEvent'\n);\n\n/**\n * Returns the segmentIndex at the event position and its corresponding metadata.\n * @param {Object} evt A cornerstone event with a currentPoints property.\n *\n * @returns {Object} An `Object` with the `segmentIndex` and its `metadata`.\n */\nexport default function getSegmentOfActiveLabelmapAtEvent(evt) {\n const eventData = evt.detail;\n const { element, image, currentPoints } = eventData;\n\n if (!currentPoints) {\n logger.warn('Not a cornerstone input event.');\n\n return;\n }\n\n const cols = image.width;\n const rows = image.height;\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const currentImageIdIndex = stackData.currentImageIdIndex;\n const firstImageId = stackData.imageIds[0];\n const brushStackState = state.series[firstImageId];\n\n const activeLabelmapIndex = brushStackState.activeLabelmapIndex;\n\n const labelmap3D = brushStackState.labelmaps3D[activeLabelmapIndex];\n\n if (!labelmap3D) {\n // No labelmap3D === no segment here.\n return;\n }\n\n const labelmap2D = labelmap3D.labelmaps2D[currentImageIdIndex];\n\n if (!labelmap2D) {\n // No labelmap on this imageId === no segment here.\n return;\n }\n\n const pixelData = labelmap2D.pixelData;\n\n let { x, y } = currentPoints.image;\n\n x = Math.floor(x);\n y = Math.floor(y);\n\n if (isPointInImage({ x, y }, rows, cols)) {\n const segmentIndex = pixelData[y * cols + x];\n\n if (segmentIndex === 0) {\n return;\n }\n\n return {\n segmentIndex,\n metadata: labelmap3D.metadata[segmentIndex],\n };\n }\n\n // Outside image === no segment here.\n return;\n}\n","import external from '../../../externalModules';\nimport { getLogger } from '../../../util/logger';\nimport state from './state';\nimport { getModule } from '../../index.js';\n\nconst logger = getLogger('store:modules:segmentationModule:setColorLUT');\n\n/**\n * SetColorLUT - Sets the labelmap to a specfic LUT, or generates a new LUT.\n *\n * @param {number} labelmapIndex The labelmap index to apply the color LUT to.\n * @param {number[][]} [colorLUT] An array of The colorLUT to set.\n * @returns {null}\n */\nexport default function setColorLUT(colorLUTIndex, colorLUT = []) {\n const { configuration } = getModule('segmentation');\n const segmentsPerLabelmap = configuration.segmentsPerLabelmap;\n\n if (colorLUT) {\n _checkColorLUTLength(colorLUT, segmentsPerLabelmap);\n\n if (colorLUT.length < segmentsPerLabelmap) {\n colorLUT = [\n ...colorLUT,\n ..._generateNewColorLUT(segmentsPerLabelmap - colorLUT.length),\n ];\n }\n } else {\n // Autogenerate colorLUT.\n colorLUT = colorLUT || _generateNewColorLUT(segmentsPerLabelmap);\n }\n\n // Apppend the \"zero\" (no label) color to the front of the LUT.\n colorLUT.unshift([0, 0, 0, 0]);\n\n state.colorLutTables[colorLUTIndex] = colorLUT;\n}\n\nexport function setColorLUTIndexForLabelmap3D(labelmap3D, colorLUTIndex) {\n labelmap3D.colorLUTIndex = colorLUTIndex;\n}\n\nexport function getColorForSegmentIndexColorLUT(\n labelmap3DOrColorLUTIndex,\n segmentIndex\n) {\n const colorLUT = getColorLUT(labelmap3DOrColorLUTIndex);\n\n return colorLUT[segmentIndex];\n}\n\n/**\n * Sets a single color of a colorLUT.\n *\n * @param {Object|number} labelmap3DOrColorLUTIndex Either a `Labelmap3D` object (who's referenced colorLUT will be changed), or a colorLUTIndex.\n * @param {number} segmentIndex The segmentIndex color to change.\n * @param {[number,number,number,number]} colorArray The color values in RGBA array format.\n */\nexport function setColorForSegmentIndexOfColorLUT(\n labelmap3DOrColorLUTIndex,\n segmentIndex,\n colorArray\n) {\n const colorLUT = getColorLUT(labelmap3DOrColorLUTIndex);\n\n colorLUT[segmentIndex] = colorArray;\n}\n\nexport function getColorLUT(labelmap3DOrColorLUTIndex) {\n if (typeof labelmap3DOrColorLUTIndex === 'number') {\n return state.colorLutTables[labelmap3DOrColorLUTIndex];\n }\n\n return state.colorLutTables[labelmap3DOrColorLUTIndex.colorLUTIndex];\n}\n\n/**\n * Checks the length of `colorLUT` compared to `segmnetsPerLabelmap` and flags up any warnings.\n * @param {number[][]} colorLUT\n * @param {number} segmentsPerLabelmap\n * @returns {boolean} Whether the length is valid.\n */\nfunction _checkColorLUTLength(colorLUT, segmentsPerLabelmap) {\n if (colorLUT.length < segmentsPerLabelmap) {\n logger.warn(\n `The provided colorLUT only provides ${colorLUT.length} labels, whereas segmentsPerLabelmap is set to ${segmentsPerLabelmap}. Autogenerating the rest.`\n );\n } else if (colorLUT.length > segmentsPerLabelmap) {\n logger.warn(\n `segmentsPerLabelmap is set to ${segmentsPerLabelmap}, and the provided colorLUT provides ${colorLUT.length}. Using the first ${segmentsPerLabelmap} colors from the LUT.`\n );\n }\n}\n\n/**\n * Generates a new color LUT (Look Up Table) of length `numberOfColors`,\n * which returns an RGBA color for each segment index.\n *\n * @param {Number} numberOfColors = 255 The number of colors to generate\n * @returns {Number[][]} The array of RGB values.\n */\nfunction _generateNewColorLUT(numberOfColors = 255) {\n const rgbArr = [];\n\n for (let i = 0; i < numberOfColors; i++) {\n rgbArr.push(getRGBAfromHSLA(getNextHue(), getNextL()));\n }\n\n return rgbArr;\n}\n\nconst goldenAngle = 137.5;\nlet hueValue = 222.5;\n\nfunction getNextHue() {\n hueValue += goldenAngle;\n\n if (hueValue >= 360) {\n hueValue -= 360;\n }\n\n return hueValue;\n}\n\nlet l = 0.6;\nconst maxL = 0.82;\nconst minL = 0.3;\nconst incL = 0.07;\n\nfunction getNextL() {\n l += incL;\n\n if (l > maxL) {\n const diff = l - maxL;\n\n l = minL + diff;\n }\n\n return l;\n}\n\n/**\n * GetRGBAfromHSL - Returns an RGBA color given H, S, L and A.\n *\n * @param {Number} hue The hue.\n * @param {Number} s = 1 The saturation.\n * @param {Number} l = 0.6 The lightness.\n * @param {Number} alpha = 255 The alpha.\n * @returns {Number[]} The RGBA formatted color.\n */\nfunction getRGBAfromHSLA(hue, s = 1, l = 0.6, alpha = 255) {\n const c = (1 - Math.abs(2 * l - 1)) * s;\n const x = c * (1 - Math.abs(((hue / 60) % 2) - 1));\n const m = l - c / 2;\n\n let r, g, b;\n\n if (hue < 60) {\n [r, g, b] = [c, x, 0];\n } else if (hue < 120) {\n [r, g, b] = [x, c, 0];\n } else if (hue < 180) {\n [r, g, b] = [0, c, x];\n } else if (hue < 240) {\n [r, g, b] = [0, x, c];\n } else if (hue < 300) {\n [r, g, b] = [x, 0, c];\n } else if (hue < 360) {\n [r, g, b] = [c, 0, x];\n }\n\n return [(r + m) * 255, (g + m) * 255, (b + m) * 255, alpha];\n}\n","import { getToolState } from '../../../stateManagement/toolState.js';\nimport state from './state';\nimport getElement from './getElement';\n\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger('store:modules:segmentationModule:getBrushColor');\n\n/**\n * Returns the brush color as a rgba CSS color for the active segment of the active\n * `Labelmap3D` for the `BrushStackState` displayed on the element.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {boolean} drawing = false Whether the user is drawing or not.\n * @returns {string} An rgba value as a string.\n */\nexport default function getBrushColor(\n elementOrEnabledElementUID,\n drawing = false\n) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n\n if (!stackState) {\n logger.error(\n 'Consumers must define stacks in their application if using segmentations in cornerstoneTools.'\n );\n\n return;\n }\n\n const stackData = stackState.data[0];\n const firstImageId = stackData.imageIds[0];\n\n const brushStackState = state.series[firstImageId];\n\n let color;\n\n if (brushStackState) {\n const activeLabelmapIndex = brushStackState.activeLabelmapIndex;\n const labelmap3D = brushStackState.labelmaps3D[activeLabelmapIndex];\n\n const activeSegmentIndex = labelmap3D.activeSegmentIndex;\n\n color = state.colorLutTables[labelmap3D.colorLUTIndex][activeSegmentIndex];\n } else {\n // No data yet, make brush the default color of colormap 0.\n color = state.colorLutTables[0][1];\n }\n\n return drawing\n ? `rgba(${color[0]}, ${color[1]}, ${color[2]}, 1.0 )`\n : `rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.8 )`;\n}\n","// Segmentation module configuration.\nconst defaultConfiguration = {\n renderOutline: true,\n renderFill: true,\n shouldRenderInactiveLabelmaps: true,\n radius: 10,\n minRadius: 1,\n maxRadius: 50,\n segmentsPerLabelmap: 65535, // Max is 65535 due to using 16-bit Unsigned ints.\n fillAlpha: 0.2,\n fillAlphaInactive: 0.1,\n outlineAlpha: 0.7,\n outlineAlphaInactive: 0.35,\n outlineWidth: 3,\n storeHistory: true,\n};\n\nexport default defaultConfiguration;\n","import { getLabelmap3D } from './getLabelmaps3D';\nimport { getLogger } from '../../../util/logger';\nimport external from '../../../externalModules';\n\nconst logger = getLogger('util:segmentation:labelmap3DHistory');\n\nfunction pushState(element, operations, labelmapIndex) {\n const labelmap3D = getLabelmap3D(element, labelmapIndex);\n\n labelmap3D.undo.push(operations);\n labelmap3D.redo = [];\n}\n\nfunction undo(element, labelmapIndex) {\n const labelmap3D = getLabelmap3D(element, labelmapIndex);\n const { undo, redo } = labelmap3D;\n\n if (!undo.length) {\n logger.warn('No undos left.');\n\n return;\n }\n\n // Pop last set of operations from undo.\n const operations = undo.pop();\n\n // Undo operations.\n applyState(labelmap3D, operations, 1);\n\n // Push set of operations to redo.\n redo.push(operations);\n\n external.cornerstone.updateImage(element);\n}\n\nfunction redo(element, labelmapIndex) {\n const labelmap3D = getLabelmap3D(element, labelmapIndex);\n const { undo, redo } = labelmap3D;\n\n if (!redo.length) {\n logger.warn('No redos left.');\n\n return;\n }\n\n // Pop last set of operations from redo.\n const operations = redo.pop();\n\n // Redo operations.\n applyState(labelmap3D, operations, 2);\n\n // Push set of operations to undo.\n undo.push(operations);\n\n external.cornerstone.updateImage(element);\n}\n\nexport { pushState, undo, redo };\n\nfunction applyState(labelmap3D, operations, replaceIndex) {\n const { labelmaps2D } = labelmap3D;\n\n operations.forEach(operation => {\n const { imageIdIndex, diff } = operation;\n const labelmap2D = labelmaps2D[imageIdIndex];\n const pixelData = labelmap2D.pixelData;\n\n for (let i = 0; i < diff.length; i++) {\n const diffI = diff[i];\n\n pixelData[diffI[0]] = diffI[replaceIndex];\n }\n });\n}\n","import { getMetadata, setMetadata } from './metadata';\nimport {\n getActiveLabelmapIndex,\n setActiveLabelmapIndex,\n} from './activeLabelmapIndex';\nimport {\n getActiveSegmentIndex,\n setActiveSegmentIndex,\n incrementActiveSegmentIndex,\n decrementActiveSegmentIndex,\n} from './activeSegmentIndex';\nimport {\n isSegmentVisible,\n toggleSegmentVisibility,\n} from './segmentVisibility.js';\nimport {\n getLabelmapBuffers,\n getActiveLabelmapBuffer,\n} from './getLabelmapBuffers';\nimport {\n setLabelmap3DByFirstImageId,\n setLabelmap3DForElement,\n} from './setLabelmap3D.js';\nimport getLabelmapStats from './getLabelmapStats';\nimport getLabelmaps3D, { getLabelmap3D } from './getLabelmaps3D';\nimport getLabelmap2D, { getLabelmap2DByImageIdIndex } from './getLabelmap2D';\nimport getSegmentOfActiveLabelmapAtEvent from './getSegmentOfActiveLabelmapAtEvent';\nimport setColorLUT, {\n getColorLUT,\n getColorForSegmentIndexColorLUT,\n setColorLUTIndexForLabelmap3D,\n setColorForSegmentIndexOfColorLUT,\n} from './colorLUT';\nimport getBrushColor from './getBrushColor';\nimport getSegmentsOnPixelData from './getSegmentsOnPixeldata';\nimport deleteSegment from './deleteSegment';\n\nimport state from './state';\nimport configuration from './defaultConfiguration';\nimport { pushState, undo, redo } from './history';\nimport setRadius from './setRadius';\n\n/**\n * A map of `firstImageId` to associated `BrushStackState`, where\n * `firstImageId` is the `imageId` of the first image in a stack.\n *\n * @typedef {Object} Series\n */\n\n/**\n * @typedef {Object} BrushStackState An object defining a set of 3D labelmaps\n * associated with a specific cornerstone stack.\n * @property {number} activeLabelmapIndex The index of the active `Labelmap3D`.\n * @property {Labelmap3D[]} labelmaps3D An array of `Labelmap3D` objects.\n */\n\n/**\n * A 3D labelmap object which stores the labelmap data for an entire stack of cornerstone images.\n *\n * @typedef {Object} Labelmap3D An object defining a 3D labelmap.\n * @property {ArrayBuffer} buffer An array buffer to store the pixel data of the `Labelmap3D` (2 bytes/voxel).\n * @property {Labelmap2D[]} labelmaps2D array of `labelmap2D` views on the `buffer`, indexed by in-stack\n * image positions.\n * @property {Object[]} metadata An array of metadata per segment. Metadata is optional and its form is\n * application specific.\n * @property {number} activeSegmentIndex The index of the active segment for this `Labelmap3D`.\n * @property {number} colorLUTIndex The index of the color LUT to use when displaying this `Labelmap3D`.\n * @property {boolean[]} segmentsHidden The visibility of segments on this labelmap.\n * If an element is `true`, the element is hidden. If it `false|undefined`, the segment is visible.\n * @property {Object[]} undo A history of operations that can be reversed.\n * @property {Object[]} redo A history of reverted operations, so that an undo can be reversed.\n * Is cleared when changes are made to the labelmap.\n */\n\n/**\n * A 2D labelmap object which accesses only one frame's worth of data from its parent `Labelmap3D`.\n *\n * @typedef {Object} Labelmap2D An object defining a 2D view on a section of a `Labelmap3D`'s `buffer`.\n * @property {Uint16Array} pixelData A 2D view on a section of the parent `Labelmap3D`'s `buffer`.\n * @property {number[]} segmentsOnLabelmap An array of segments present in the `pixelData`.\n */\n\n/**\n * OnRegisterCallback - Initialise a single default colorLUT when cornerstoneTools is initialised.\n *\n * @returns {null}\n */\nfunction onRegisterCallback() {\n setColorLUT(0);\n}\n\nexport default {\n state,\n configuration,\n onRegisterCallback,\n getters: {\n metadata: getMetadata,\n labelmap3D: getLabelmap3D,\n labelmaps3D: getLabelmaps3D,\n activeLabelmapIndex: getActiveLabelmapIndex,\n activeSegmentIndex: getActiveSegmentIndex,\n isSegmentVisible,\n labelmap2D: getLabelmap2D,\n labelmap2DByImageIdIndex: getLabelmap2DByImageIdIndex,\n labelmapStats: getLabelmapStats,\n segmentOfActiveLabelmapAtEvent: getSegmentOfActiveLabelmapAtEvent,\n brushColor: getBrushColor,\n labelmapBuffers: getLabelmapBuffers,\n activeLabelmapBuffer: getActiveLabelmapBuffer,\n colorLUT: getColorLUT,\n colorForSegmentIndexColorLUT: getColorForSegmentIndexColorLUT,\n },\n setters: {\n metadata: setMetadata,\n labelmap3DForElement: setLabelmap3DForElement,\n labelmap3DByFirstImageId: setLabelmap3DByFirstImageId,\n incrementActiveSegmentIndex,\n decrementActiveSegmentIndex,\n activeSegmentIndex: setActiveSegmentIndex,\n toggleSegmentVisibility,\n updateSegmentsOnLabelmap2D: labelmap2D => {\n labelmap2D.segmentsOnLabelmap = getSegmentsOnPixelData(\n labelmap2D.pixelData\n );\n },\n deleteSegment,\n colorLUT: setColorLUT,\n colorLUTIndexForLabelmap3D: setColorLUTIndexForLabelmap3D,\n colorForSegmentIndexOfColorLUT: setColorForSegmentIndexOfColorLUT,\n activeLabelmapIndex: setActiveLabelmapIndex,\n radius: setRadius,\n pushState,\n undo,\n redo,\n },\n};\n","import getElement from './getElement';\nimport { getToolState } from '../../../stateManagement/toolState.js';\nimport addLabelmap3D from './addLabelmap3D';\nimport state from './state';\nimport external from '../../../externalModules';\n\n/**\n * Returns the index of the active `Labelmap3D`.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone\n * enabled element or its UUID.\n * @returns {number} The index of the active `Labelmap3D`.\n */\nfunction getActiveLabelmapIndex(elementOrEnabledElementUID) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const firstImageId = stackData.imageIds[0];\n\n const brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n return;\n }\n\n return brushStackState.activeLabelmapIndex;\n}\n\n/**\n * Sets the active `labelmapIndex` for the `BrushStackState` displayed on this\n * element. Creates the corresponding `Labelmap3D` if it doesn't exist.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled\n * element or its UUID.\n * @param {number} labelmapIndex = 0 The index of the labelmap.\n * @returns {null}\n */\nfunction setActiveLabelmapIndex(elementOrEnabledElementUID, labelmapIndex = 0) {\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const enabledElement = cornerstone.getEnabledElement(element);\n const { rows, columns } = enabledElement.image;\n const numberOfFrames = stackData.imageIds.length;\n const size = rows * columns * numberOfFrames;\n const firstImageId = stackData.imageIds[0];\n\n let brushStackState = state.series[firstImageId];\n\n if (brushStackState) {\n brushStackState.activeLabelmapIndex = labelmapIndex;\n\n if (!brushStackState.labelmaps3D[labelmapIndex]) {\n addLabelmap3D(brushStackState, labelmapIndex, size);\n }\n } else {\n state.series[firstImageId] = {\n activeLabelmapIndex: labelmapIndex,\n labelmaps3D: [],\n };\n\n brushStackState = state.series[firstImageId];\n\n addLabelmap3D(brushStackState, labelmapIndex, size);\n }\n\n cornerstone.updateImage(element);\n}\n\nexport { getActiveLabelmapIndex, setActiveLabelmapIndex };\n","import getElement from './getElement';\nimport { getToolState } from '../../../stateManagement/toolState.js';\nimport state from './state';\nimport external from '../../../externalModules';\n\n/**\n * Deletes the segment and any associated metadata from the `Labelmap3D`.\n *\n * @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone enabled element or its UUID.\n * @param {number} segmentIndex The segment Index\n * @param {number} [labelmapIndex] The labelmap index. Defaults to the active labelmap index.\n *\n * @returns {null}\n */\nexport default function deleteSegment(\n elementOrEnabledElementUID,\n segmentIndex,\n labelmapIndex\n) {\n if (!segmentIndex) {\n return;\n }\n\n const element = getElement(elementOrEnabledElementUID);\n\n if (!element) {\n return;\n }\n\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const firstImageId = stackData.imageIds[0];\n\n const brushStackState = state.series[firstImageId];\n\n if (!brushStackState) {\n return;\n }\n\n labelmapIndex =\n labelmapIndex === undefined\n ? brushStackState.activeLabelmapIndex\n : labelmapIndex;\n\n const labelmap3D = brushStackState.labelmaps3D[labelmapIndex];\n\n if (!labelmap3D) {\n return;\n }\n\n // Delete metadata if present.\n delete labelmap3D.metadata[segmentIndex];\n\n const labelmaps2D = labelmap3D.labelmaps2D;\n\n // Clear segment's voxels.\n for (let i = 0; i < labelmaps2D.length; i++) {\n const labelmap2D = labelmaps2D[i];\n\n // If the labelmap2D has data, and it contains the segment, delete it.\n if (labelmap2D && labelmap2D.segmentsOnLabelmap.includes(segmentIndex)) {\n const pixelData = labelmap2D.pixelData;\n\n // Remove this segment from the list.\n const indexOfSegment = labelmap2D.segmentsOnLabelmap.indexOf(\n segmentIndex\n );\n\n labelmap2D.segmentsOnLabelmap.splice(indexOfSegment, 1);\n\n // Delete the label for this segment.\n for (let p = 0; p < pixelData.length; p++) {\n if (pixelData[p] === segmentIndex) {\n pixelData[p] = 0;\n }\n }\n }\n }\n\n external.cornerstone.updateImage(element);\n}\n","import { getModule } from '../../index';\n\nexport default function setRadius(newRadius) {\n const { configuration } = getModule('segmentation');\n\n configuration.radius = Math.min(\n Math.max(newRadius, configuration.minRadius),\n configuration.maxRadius\n );\n}\n","import external from '../../externalModules';\n\nconst configuration = {\n iconSize: 16,\n viewBox: {\n x: 16,\n y: 16,\n },\n mousePoint: {\n x: 8,\n y: 8,\n },\n mousePointerGroupString: `\n <path stroke=\"ACTIVE_COLOR\" d=\"M8 16L8 0\"></path>\n <path stroke=\"ACTIVE_COLOR\" d=\"M16 8L0 8\"></path>\n `,\n};\n\nconst setters = {\n defaultOptions: newOptions => {\n Object.assign(configuration, newOptions);\n },\n};\n\nconst getters = {\n defaultOptions: () => configuration,\n};\n\nexport default {\n configuration,\n getters,\n setters,\n};\n","const configuration = {\n mouseEnabled: true,\n touchEnabled: true,\n globalToolSyncEnabled: false,\n showSVGCursors: false,\n autoResizeViewports: true,\n};\n\nexport default {\n configuration,\n};\n","// Modules\nimport segmentation from './modules/segmentationModule';\nimport cursor from './modules/cursorModule.js';\nimport globalConfiguration from './modules/globalConfigurationModule.js';\nimport external from '../externalModules.js';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('store:modules:storeLogger');\n\nexport const state = {\n // Global\n globalTools: {},\n globalToolChangeHistory: [],\n // Tracking\n enabledElements: [],\n tools: [],\n isToolLocked: false,\n activeMultiPartTool: null,\n mousePositionImage: {},\n // Settings\n clickProximity: 6,\n touchProximity: 10,\n handleRadius: 6,\n deleteIfHandleOutsideImage: true,\n preventHandleOutsideImage: false,\n // Cursor\n svgCursorUrl: null,\n};\n\nexport const getters = {\n mouseTools: () =>\n state.tools.filter(tool =>\n tool.supportedInteractionTypes.includes('Mouse')\n ),\n touchTools: () =>\n state.tools.filter(tool =>\n tool.supportedInteractionTypes.includes('Touch')\n ),\n enabledElementByUID: enabledElementUID =>\n state.enabledElements.find(\n element =>\n external.cornerstone.getEnabledElement(element).uuid ===\n enabledElementUID\n ),\n};\n\nexport const setters = {};\n\nexport const modules = {\n segmentation,\n cursor,\n globalConfiguration,\n};\n\nexport function getModule(moduleName) {\n return modules[moduleName];\n}\n\nexport default {\n modules,\n state,\n getters,\n};\n","import { state } from './index.js';\n\n/**\n * Returns the tool instance attached to the element.\n * @export\n * @public\n * @method\n * @name getToolForElement\n *\n * @param {HTMLElement} element The element.\n * @param {string} name The tool's name.\n * @returns {Object} The tool instance.\n */\nexport default function(element, name) {\n return state.tools.find(\n tool => tool.element === element && tool.name === name\n );\n}\n","import { state, modules } from './index.js';\n\nexport { setToolCursor, resetToolCursor, hideToolCursor };\n\nconst globalConfiguration = modules.globalConfiguration;\n\n/**\n * Creates an SVG Cursor for the target element\n *\n * @param {HTMLElement} element - The DOM Element to draw on\n * @param {MouseCursor} svgCursor - The cursor.\n * @returns {void}\n */\nfunction setToolCursor(element, svgCursor) {\n if (!globalConfiguration.configuration.showSVGCursors) {\n return;\n }\n // TODO: (state vs options) Exit if cursor wasn't updated\n // TODO: Exit if invalid options to create cursor\n\n // Note: Max size of an SVG cursor is 128x128, default is 32x32.\n const cursorBlob = svgCursor.getIconWithPointerSVG();\n const mousePoint = svgCursor.mousePoint;\n\n const svgCursorUrl = window.URL.createObjectURL(cursorBlob);\n\n element.style.cursor = `url('${svgCursorUrl}') ${mousePoint}, auto`;\n\n state.svgCursorUrl = svgCursorUrl;\n}\n\nfunction resetToolCursor(element) {\n _clearStateAndSetCursor(element, 'initial');\n}\n\nfunction hideToolCursor(element) {\n if (!globalConfiguration.configuration.showSVGCursors) {\n return;\n }\n\n _clearStateAndSetCursor(element, 'none');\n}\n\nfunction _clearStateAndSetCursor(element, cursorSeting) {\n if (state.svgCursorUrl) {\n window.URL.revokeObjectURL(state.svgCursorUrl);\n }\n\n state.svgCursorUrl = null;\n element.style.cursor = cursorSeting;\n}\n","import EVENTS from './../events.js';\nimport triggerEvent from './../util/triggerEvent.js';\nimport getToolForElement from './getToolForElement.js';\nimport {\n setToolCursor,\n resetToolCursor,\n hideToolCursor,\n} from './setToolCursor.js';\nimport { getLogger } from '../util/logger.js';\nimport store, { getModule } from './index.js';\n\nconst globalConfiguration = getModule('globalConfiguration');\nconst logger = getLogger('store:setToolMode');\n\n/**\n * Sets a tool's state, with the provided toolName and element, to 'active'. Active tools are rendered,\n * respond to user input, and can create new data.\n *\n * @public\n * @function setToolActiveForElement\n * @memberof CornerstoneTools\n *\n * @example <caption>Setting a tool 'active' for a specific interaction type.</caption>\n * // Sets length tool to Active\n * setToolActiveForElement(element, 'Length', {\n * mouseButtonMask: 1\n * }, ['Mouse'])\n * @example <caption>Setting a tool 'active' for all interaction types.</caption>\n * // Sets length tool to Active\n * setToolActiveForElement(element, 'Length', {\n * mouseButtonMask: 1\n * })\n * @param {HTMLElement} element\n * @param {string} toolName\n * @param {(Object|string[]|number)} options\n * @param {(string[])} interactionTypes\n * @returns {undefined}\n */\nconst setToolActiveForElement = function(\n element,\n toolName,\n options,\n interactionTypes\n) {\n // If interactionTypes was passed in via options\n if (interactionTypes === undefined && Array.isArray(options)) {\n interactionTypes = options;\n options = null;\n }\n\n const tool = getToolForElement(element, toolName);\n\n if (tool) {\n _resolveInputConflicts(element, tool, options, interactionTypes);\n\n // Iterate over specific interaction types and set active\n // This is used as a secondary check on active tools to find the active \"parts\" of the tool\n tool.supportedInteractionTypes.forEach(interactionType => {\n if (\n interactionTypes === undefined ||\n interactionTypes.includes(interactionType)\n ) {\n options[`is${interactionType}Active`] = true;\n } else {\n options[`is${interactionType}Active`] = false;\n }\n });\n\n if (\n globalConfiguration.configuration.showSVGCursors &&\n tool.supportedInteractionTypes.includes('Mouse')\n ) {\n _setToolCursorIfPrimary(element, options, tool);\n }\n }\n\n // Resume normal behavior\n setToolModeForElement('active', null, element, toolName, options);\n};\n\nfunction _setToolCursorIfPrimary(element, options, tool) {\n let mouseButtonMask;\n\n if (typeof options === 'number') {\n mouseButtonMask = [options];\n } else {\n mouseButtonMask = options.mouseButtonMask;\n }\n\n if (mouseButtonMask.includes(1)) {\n if (tool.svgCursor) {\n setToolCursor(tool.element, tool.svgCursor);\n } else if (tool.hideDefaultCursor) {\n hideToolCursor(element);\n } else {\n resetToolCursor(element);\n }\n }\n}\n\n/**\n * Sets all tool's state, with the provided toolName, to 'active'. Active tools are rendered,\n * respond to user input, and can create new data.\n * @public\n * @function setToolActive\n * @memberof CornerstoneTools\n *\n * @param {string} toolName\n * @param {(Object|string[]|number)} options\n * @param {(string[])} interactionTypes\n * @returns {undefined}\n */\nconst setToolActive = function(toolName, options, interactionTypes) {\n _trackGlobalToolModeChange('active', toolName, options, interactionTypes);\n store.state.enabledElements.forEach(element => {\n setToolActiveForElement(element, toolName, options, interactionTypes);\n });\n};\n\n/**\n * Sets a tool's state, with the provided toolName and element, to 'disabled'. Disabled tools are not rendered,\n * and do not respond to user input\n * @public\n * @function setToolDisabledForElement\n * @memberof CornerstoneTools\n *\n * @param {HTMLElement} element\n * @param {string} toolName\n * @param {(Object|number)} options\n * @returns {undefined}\n */\nconst setToolDisabledForElement = setToolModeForElement.bind(\n null,\n 'disabled',\n null\n);\n\n/**\n * Sets all tool's state, with the provided toolName, to 'disabled'. Disabled tools are not rendered,\n * and do not respond to user input\n * @public\n * @function setToolDisabled\n * @memberof CornerstoneTools\n *\n * @param {string} toolName\n * @param {(Object|number)} options\n * @returns {undefined}\n */\nconst setToolDisabled = setToolMode.bind(null, 'disabled', null);\n\n/**\n * Sets a tool's state, with the provided toolName and element, to 'enabled'. Enabled tools are rendered,\n * but do not respond to user input\n * @public\n * @function setToolEnabledForElement\n * @memberof CornerstoneTools\n *\n * @param {HTMLElement} element\n * @param {string} toolName\n * @param {(Object|number)} options\n * @returns {undefined}\n */\nconst setToolEnabledForElement = setToolModeForElement.bind(\n null,\n 'enabled',\n null\n);\n\n/**\n * Sets all tool's state, with the provided toolName, to 'enabled'. Enabled tools are rendered,\n * but do not respond to user input\n * @public\n * @function setToolEnabled\n * @memberof CornerstoneTools\n *\n * @param {string} toolName\n * @param {(Object|number)} options\n * @returns {undefined}\n */\nconst setToolEnabled = setToolMode.bind(null, 'enabled', null);\n\n/**\n * Sets a tool's state, with the provided toolName and element, to 'passive'. Passive tools are rendered and respond to user input,\n * but do not create new measurements or annotations.\n * @public\n * @function setToolPassiveForElement\n * @memberof CornerstoneTools\n *\n * @param {HTMLElement} element\n * @param {string} toolName\n * @param {(Object|number)} options\n * @returns {undefined}\n */\nconst setToolPassiveForElement = setToolModeForElement.bind(\n null,\n 'passive',\n EVENTS.TOOL_DEACTIVATED\n);\n\n/**\n * Sets all tool's state, with the provided toolName, to 'passive'. Passive tools are rendered and respond to user input,\n * but do not create new measurements or annotations.\n * @public\n * @function setToolPassive\n * @memberof CornerstoneTools\n *\n * @param {string} toolName\n * @param {(Object|number)} options\n * @returns {undefined}\n */\nconst setToolPassive = setToolMode.bind(\n null,\n 'passive',\n EVENTS.TOOL_DEACTIVATED\n);\n\n/**\n * An internal method that helps make sure we change tool mode in a consistent\n * way\n * @private\n * @function setToolModeForElement\n *\n * @param {string} mode\n * @param {string} changeEvent\n * @param {HTMLElement} element\n * @param {string} toolName\n * @param {(Object|number[]|number)} options\n * @returns {undefined}\n */\nfunction setToolModeForElement(mode, changeEvent, element, toolName, options) {\n const tool = getToolForElement(element, toolName);\n\n if (!tool) {\n logger.warn('Unable to find tool \"%s\" for enabledElement', toolName);\n\n return;\n }\n\n options = _getNormalizedOptions(options);\n\n // Keep the same if not an array (undefined)\n // Reset if empty array\n // Merge if array contains any bindings\n if (\n Array.isArray(options.mouseButtonMask) &&\n options.mouseButtonMask.length !== 0 &&\n Array.isArray(tool.options.mouseButtonMask)\n ) {\n options.mouseButtonMask = _mergeMouseButtonMask(\n options.mouseButtonMask,\n tool.options.mouseButtonMask\n );\n }\n\n // Set mode & options\n tool.mode = mode;\n tool.mergeOptions(options);\n\n // Call tool's hook for this event, if one exists\n if (tool[`${mode}Callback`]) {\n tool[`${mode}Callback`](element, options);\n }\n\n // Emit event indicating tool state change\n if (changeEvent) {\n const statusChangeEventData = {\n options,\n toolName,\n type: changeEvent,\n };\n\n triggerEvent(element, changeEvent, statusChangeEventData);\n }\n\n // Trigger Update\n // Todo: don't error out if image hasn't been loaded...\n // Cornerstone.updateImage(element);\n}\n\n/**\n * A helper/quick way to set a tool's mode for all canvases\n *\n * @private\n * @function setToolMode\n *\n * @param {string} mode\n * @param {string} changeEvent\n * @param {string} toolName\n * @param {(Object|number)} options\n * @returns {undefined}\n */\nfunction setToolMode(mode, changeEvent, toolName, options) {\n _trackGlobalToolModeChange(mode, toolName, options);\n store.state.enabledElements.forEach(element => {\n setToolModeForElement(mode, changeEvent, element, toolName, options);\n });\n}\n\n/**\n * Find tool's that conflict with the incoming tool's mouse/touch bindings and\n * resolve those conflicts.\n *\n * @private\n * @function _resolveInputConflicts\n *\n * @param {HTMLElement} element\n * @param {Object} tool\n * @param {(Object|number)} options\n * @param {(Array)} interactionTypes\n * @returns {undefined}\n */\nfunction _resolveInputConflicts(element, tool, options, interactionTypes) {\n // Iterate over the interaction types our tool supports.\n // For each one we intend to activate, check for potential conflicts\n // And resolve them\n tool.supportedInteractionTypes.forEach(interactionType => {\n if (\n interactionTypes === undefined ||\n interactionTypes.includes(interactionType)\n ) {\n const inputResolver = _inputResolvers[interactionType];\n\n if (inputResolver) {\n inputResolver(tool, element, options);\n } else {\n logger.warn(\n 'Unable to resolve input conflicts for type %s',\n interactionType\n );\n }\n }\n });\n\n const activeToolsForElement = store.state.tools.filter(\n t =>\n t.element === element &&\n t.mode === 'active' &&\n t.supportedInteractionTypes.length > 0\n );\n\n activeToolsForElement.forEach(t => {\n let toolHasAnyActiveInteractionType = false;\n\n t.supportedInteractionTypes.forEach(interactionType => {\n if (t.options[`is${interactionType}Active`]) {\n toolHasAnyActiveInteractionType = true;\n }\n });\n\n if (!toolHasAnyActiveInteractionType) {\n logger.log(\"Setting tool %s's to PASSIVE\", t.name);\n setToolPassiveForElement(element, t.name);\n }\n });\n}\n\n/**\n * Resolves conflicting active tools when activating a tool for mouse interaction\n * @private\n * @function _resolveMouseInputConflicts\n *\n * @param {Object} tool\n * @param {HTMLElement} element\n * @param {(Object|number)} options\n * @returns {undefined}\n */\nfunction _resolveMouseInputConflicts(tool, element, options) {\n const mouseButtonMask = _getNormalizedOptions(options).mouseButtonMask;\n const hasMouseButtonMask =\n Array.isArray(mouseButtonMask) && mouseButtonMask.length > 0;\n\n if (!hasMouseButtonMask) {\n return;\n }\n\n const activeToolWithMatchingMouseButtonMask = store.state.tools.find(\n t =>\n t.element === element &&\n t.mode === 'active' &&\n t.options.isMouseActive === true &&\n Array.isArray(t.options.mouseButtonMask) &&\n t.options.mouseButtonMask.some(v => mouseButtonMask.includes(v))\n );\n\n if (activeToolWithMatchingMouseButtonMask) {\n // Remove collissions\n activeToolWithMatchingMouseButtonMask.options.mouseButtonMask = activeToolWithMatchingMouseButtonMask.options.mouseButtonMask.filter(\n mask => !mouseButtonMask.includes(mask)\n );\n\n // If no remaining bindings, set inactive\n if (\n activeToolWithMatchingMouseButtonMask.options.mouseButtonMask.length === 0\n ) {\n activeToolWithMatchingMouseButtonMask.options.isMouseActive = false;\n }\n }\n}\n\n/**\n * Resolves conflicting active tools when activating a tool for touch interaction\n * @private\n * @function _resolveTouchInputConflicts\n *\n * @param {Object} tool\n * @param {HTMLElement} element\n * @returns {undefined}\n */\nfunction _resolveTouchInputConflicts(tool, element) {\n const activeTouchTool = store.state.tools.find(\n t =>\n t.element === element &&\n t.mode === 'active' &&\n t.options.isTouchActive === true\n );\n\n const activeMultiTouchToolWithOneTouchPointer = store.state.tools.find(\n t =>\n t.element === element &&\n t.mode === 'active' &&\n t.options.isMultiTouchActive === true &&\n t.configuration.touchPointers === 1\n );\n\n if (activeTouchTool) {\n logger.log(\n \"Setting tool %s's isTouchActive to false\",\n activeTouchTool.name\n );\n activeTouchTool.options.isTouchActive = false;\n }\n if (activeMultiTouchToolWithOneTouchPointer) {\n logger.log(\n \"Setting tool %s's isTouchActive to false\",\n activeMultiTouchToolWithOneTouchPointer.name\n );\n activeMultiTouchToolWithOneTouchPointer.options.isMultiTouchActive = false;\n }\n}\n\n/**\n * Resolves conflicting active tools when activating a tool for MultiTouch interaction\n * @private\n * @function _resolveMultiTouchInputConflicts\n *\n * @param {Object} tool\n * @param {HTMLElement} element\n * @returns {undefined}\n */\nfunction _resolveMultiTouchInputConflicts(tool, element) {\n const activeMultiTouchTool = store.state.tools.find(\n t =>\n t.element === element &&\n t.mode === 'active' &&\n t.options.isMultiTouchActive === true &&\n t.configuration.touchPointers === tool.configuration.touchPointers\n );\n\n let activeTouchTool;\n\n if (tool.configuration.touchPointers === 1) {\n activeTouchTool = store.state.tools.find(\n t =>\n t.element === element &&\n t.mode === 'active' &&\n t.options.isTouchActive === true\n );\n }\n\n if (activeMultiTouchTool) {\n logger.log(\n \"Setting tool %s's isMultiTouchActive to false\",\n activeMultiTouchTool.name\n );\n activeMultiTouchTool.options.isMultiTouchActive = false;\n }\n\n if (activeTouchTool) {\n logger.log(\n \"Setting tool %s's isTouchActive to false\",\n activeTouchTool.name\n );\n activeTouchTool.options.isTouchActive = false;\n }\n}\n\n/**\n * If the incoming tool isTouchActive, find any conflicting tools\n * and set their isTouchActive to false to avoid conflicts.\n *\n * @private\n * @function _resolveGenericInputConflicts\n *\n * @param {string} interactionType\n * @param {Object} tool\n * @param {HTMLElement} element\n * @param {(Object|number)} options\n * @returns {undefined}\n */\nfunction _resolveGenericInputConflicts(interactionType, tool, element) {\n const interactionTypeFlag = `is${interactionType}Active`;\n const activeToolWithActiveInteractionType = store.state.tools.find(\n t =>\n t.element === element &&\n t.mode === 'active' &&\n t.options[interactionTypeFlag] === true\n );\n\n if (activeToolWithActiveInteractionType) {\n logger.log(\n \"Setting tool %s's %s to false\",\n activeToolWithActiveInteractionType.name,\n interactionTypeFlag\n );\n activeToolWithActiveInteractionType.options[interactionTypeFlag] = false;\n }\n}\n\nfunction _trackGlobalToolModeChange(mode, toolName, options, interactionTypes) {\n if (!globalConfiguration.configuration.globalToolSyncEnabled) {\n return;\n }\n\n // Update Tool History\n const historyEvent = {\n mode,\n args: [toolName, options],\n };\n\n if (interactionTypes) {\n historyEvent.push(interactionTypes);\n }\n\n store.state.globalToolChangeHistory.push(historyEvent);\n\n const arbitraryChangeHistoryLimit = 50;\n\n if (\n store.state.globalToolChangeHistory.length > arbitraryChangeHistoryLimit\n ) {\n store.state.globalToolChangeHistory.shift();\n }\n\n // Update ActiveBindings Array\n const globalTool = store.state.globalTools[toolName];\n\n if (!globalTool) {\n logger.warn(\n `setToolMode call for tool not available globally: ${toolName}`\n );\n\n return;\n }\n\n if (mode === 'active') {\n let stringBindings = _determineStringBindings(\n toolName,\n options,\n interactionTypes\n );\n\n // Remove the incoming bindings from all global tools\n Object.keys(store.state.globalTools).forEach(key => {\n const tool = store.state.globalTools[key];\n\n tool.activeBindings = tool.activeBindings.filter(\n binding => !stringBindings.includes(binding)\n );\n });\n\n // @HACK: Clear mouse bindings\n if (stringBindings.some(binding => binding.includes('Mouse-DELETE'))) {\n globalTool.activeBindings = globalTool.activeBindings.filter(\n binding => !binding.includes('Mouse')\n );\n stringBindings = stringBindings.filter(\n binding => !binding.includes('Mouse')\n );\n }\n\n globalTool.activeBindings = globalTool.activeBindings.concat(\n stringBindings\n );\n } else {\n globalTool.activeBindings = [];\n }\n}\n\nfunction _determineStringBindings(toolName, options, interactionTypes) {\n if (interactionTypes === undefined && Array.isArray(options)) {\n interactionTypes = options;\n options = null;\n }\n\n const stringBindings = [];\n const globalTool = store.state.globalTools[toolName];\n\n if (globalTool) {\n // eslint-disable-next-line new-cap\n const tool = new globalTool.tool(globalTool.props);\n\n tool.supportedInteractionTypes.forEach(interactionType => {\n if (\n interactionTypes === undefined ||\n interactionTypes.includes(interactionType)\n ) {\n if (interactionType === 'Mouse') {\n const mouseButtonMasks = _getNormalizedOptions(options)\n .mouseButtonMask;\n\n // Add or delete\n if (Array.isArray(mouseButtonMasks) && mouseButtonMasks.length > 0) {\n mouseButtonMasks.forEach(mask =>\n stringBindings.push(`${interactionType}-${mask}`)\n );\n } else if (\n Array.isArray(mouseButtonMasks) &&\n mouseButtonMasks.length === 0\n ) {\n stringBindings.push(`${interactionType}-DELETE`);\n }\n } else if (interactionType === 'MultiTouch') {\n stringBindings.push(\n `${interactionType}-${tool.configuration.touchPointers}`\n );\n } else {\n stringBindings.push(interactionType);\n }\n }\n });\n }\n\n return stringBindings;\n}\n\nconst _inputResolvers = {\n Mouse: _resolveMouseInputConflicts,\n MouseWheel: _resolveGenericInputConflicts.bind(this, 'MouseWheel'),\n Touch: _resolveTouchInputConflicts,\n TouchPinch: _resolveGenericInputConflicts.bind(this, 'TouchPinch'),\n TouchRotate: _resolveGenericInputConflicts.bind(this, 'TouchRotate'),\n DoubleTap: _resolveGenericInputConflicts.bind(this, 'DoubleTap'),\n MultiTouch: _resolveMultiTouchInputConflicts,\n};\n\nfunction _getNormalizedOptions(options) {\n if (Array.isArray(options)) {\n // If options is an array assume the array is the mouseButtonMask array\n options = { mouseButtonMask: options };\n } else if (options !== Object(options)) {\n // And if it's something other than an object, assume options is\n // a single mouseButtonMask\n options = { mouseButtonMask: [options] };\n }\n\n // If there is still no 'mouseButtonMask' default it to an empty array\n if (!options.hasOwnProperty('mouseButtonMask')) {\n options.mouseButtonMask = [];\n }\n\n if (!Array.isArray(options.mouseButtonMask)) {\n options.mouseButtonMask = [options.mouseButtonMask];\n }\n\n // Now filter out anything that is not an number or is the number 0\n options.mouseButtonMask = options.mouseButtonMask.filter(\n o => typeof o === 'number' && o !== 0\n );\n\n return options;\n}\n\nfunction _mergeMouseButtonMask(newMask, oldMask) {\n // Merges and removes duplicates\n return newMask.concat(oldMask).reduce((acc, m) => {\n if (acc.indexOf(m) === -1) {\n acc.push(m);\n }\n\n return acc;\n }, []);\n}\n\nexport {\n setToolActive,\n setToolActiveForElement,\n setToolDisabled,\n setToolDisabledForElement,\n setToolEnabled,\n setToolEnabledForElement,\n setToolPassive,\n setToolPassiveForElement,\n // Exported for testing\n setToolMode,\n setToolModeForElement,\n _getNormalizedOptions,\n _mergeMouseButtonMask,\n};\n","import {\n setToolDisabledForElement,\n setToolActiveForElement,\n} from '../store/setToolMode.js';\n\n/**\n * If one attempts to change mode to 'passive', redirect the tool to 'disabled'.\n *\n * @param {HTMLElement} element The element on which the tool resides.\n * @returns {undefined}\n */\nfunction passiveCallback(element) {\n setToolDisabledForElement(element, this.name);\n}\n\n/**\n * If one attempts to turn the tool 'enabled', redirect the tool to 'active'.\n *\n * @param {HTMLElement} element The element on which the tool resides.\n * @returns {undefined}\n */\nfunction enabledCallback(element) {\n setToolActiveForElement(element, this.name);\n}\n\n/**\n * @mixin activeOrDisabledBinaryTool - Redirect enabled/passive mode changes to active/disabled.\n * @memberof Mixins\n */\nexport default {\n passiveCallback,\n enabledCallback,\n};\n","import {\n setToolDisabledForElement,\n setToolEnabledForElement,\n} from '../store/setToolMode.js';\n\n/**\n * If one attempts to change mode to 'passive', redirect the tool to 'disabled'.\n *\n * @param {HTMLElement} element The element on which the tool resides.\n * @returns {undefined}\n */\nfunction passiveCallback(element) {\n setToolDisabledForElement(element, this.name);\n}\n\n/**\n * If one attempts to change mode to 'active', redirect the tool to 'enabled'.\n *\n * @param {HTMLElement} element The element on which the tool resides.\n * @returns {undefined}\n */\nfunction activeCallback(element) {\n setToolEnabledForElement(element, this.name);\n}\n\n/**\n *\n * @mixin enabledOrDisabledBinaryTool - Redirect active/passive mode changes to enabled/disabled.\n * @memberof Mixins\n */\nexport default {\n passiveCallback,\n activeCallback,\n};\n","/**\n * This function manages the {@link https://www.w3.org/TR/2dcontext/#the-canvas-state|save/restore}\n * pattern for working in a new context state stack. The parameter `fn` is passed the `context` and can\n * execute any API calls in a clean stack.\n * @public\n * @method draw\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target Canvas\n * @param {ContextFn} fn - A function which performs drawing operations within the given context.\n * @returns {undefined}\n */\nexport default function(context, fn) {\n context.save();\n fn(context);\n context.restore();\n}\n","let defaultWidth = 1,\n activeWidth = 2;\n\nfunction setToolWidth(width) {\n defaultWidth = width;\n}\n\nfunction getToolWidth() {\n return defaultWidth;\n}\n\nfunction setActiveWidth(width) {\n activeWidth = width;\n}\n\nfunction getActiveWidth() {\n return activeWidth;\n}\n\nconst toolStyle = {\n setToolWidth,\n getToolWidth,\n setActiveWidth,\n getActiveWidth,\n};\n\nexport default toolStyle;\n","import toolStyle from './../stateManagement/toolStyle.js';\n\n/**\n * This function manages the beginPath/stroke pattern for working with\n * {@link https://www.w3.org/TR/2dcontext/#drawing-paths-to-the-canvas|path objects}.\n *\n * @public\n * @function path\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Context to add path to\n * @param {Object} [options={}] - Drawing Options\n * @param {StrokeStyle} [options.color] - The stroke style of the path.\n * @param {number} [options.lineWidth] - The width of lines in the path. If null, no line width is set.\n * If undefined then toolStyle.getToolWidth() is set.\n * @param {FillStyle} [options.fillStyle] - The style to fill the path with. If undefined then no filling is done.\n * @param {Number[]} [options.lineDash] - The {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash|dash pattern}\n * to use on the lines.\n * @param {boolean} [options.shouldDrawLines = true] Whether context.stroke should be evoked.\n * @param {ContextFn} fn - A drawing function to execute with the provided stroke pattern.\n * @returns {undefined}\n */\nexport default function(context, options = {}, fn) {\n const {\n color,\n lineWidth,\n fillStyle,\n lineDash,\n shouldDrawLines = true,\n } = options;\n\n context.beginPath();\n context.strokeStyle = color || context.strokeStyle;\n\n context.lineWidth =\n lineWidth ||\n (lineWidth === undefined && toolStyle.getToolWidth()) ||\n context.lineWidth;\n if (lineDash) {\n context.setLineDash(lineDash);\n }\n\n fn(context);\n\n if (fillStyle) {\n context.fillStyle = fillStyle;\n context.fill();\n }\n\n if (shouldDrawLines) {\n context.stroke();\n }\n\n if (lineDash) {\n context.setLineDash([]);\n }\n}\n","import external from './../externalModules.js';\nimport path from './path.js';\n\n/**\n * Draw a line between `start` and `end`.\n *\n * @public\n * @method drawLine\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context\n * @param {HTMLElement} element - The DOM Element to draw on\n * @param {Object} start - `{ x, y } in either pixel or canvas coordinates.\n * @param {Object} end - `{ x, y }` in either pixel or canvas coordinates.\n * @param {Object} options - See {@link path}\n * @param {String} [coordSystem='pixel'] - Can be \"pixel\" (default) or \"canvas\". The coordinate\n * system of the points passed in to the function. If \"pixel\" then cornerstone.pixelToCanvas\n * is used to transform the points from pixel to canvas coordinates.\n * @returns {undefined}\n */\nexport default function drawLine(\n context,\n element,\n start,\n end,\n options,\n coordSystem = 'pixel'\n) {\n path(context, options, context => {\n if (coordSystem === 'pixel') {\n start = external.cornerstone.pixelToCanvas(element, start);\n end = external.cornerstone.pixelToCanvas(element, end);\n }\n\n context.moveTo(start.x, start.y);\n context.lineTo(end.x, end.y);\n });\n}\n","import external from './../externalModules.js';\nimport path from './path.js';\n\n/**\n * Draw a series of joined lines, starting at `start` and then going to each point in `points`.\n * @public\n * @method drawJoinedLines\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target context\n * @param {HTMLElement} element - The DOM Element to draw on\n * @param {Object} start - `{ x, y }` in either pixel or canvas coordinates.\n * @param {Object[]} points - `[{ x, y }]` An array of points in either pixel or canvas coordinates.\n * @param {Object} options - See {@link path}\n * @param {String} [coordSystem='pixel'] - Can be \"pixel\" (default) or \"canvas\". The coordinate\n * system of the points passed in to the function. If \"pixel\" then cornerstone.pixelToCanvas\n * is used to transform the points from pixel to canvas coordinates.\n * @returns {undefined}\n */\nexport default function(\n context,\n element,\n start,\n points,\n options,\n coordSystem = 'pixel'\n) {\n path(context, options, context => {\n if (coordSystem === 'pixel') {\n start = external.cornerstone.pixelToCanvas(element, start);\n points = points.map(p => external.cornerstone.pixelToCanvas(element, p));\n }\n context.moveTo(start.x, start.y);\n points.forEach(({ x, y }) => {\n context.lineTo(x, y);\n });\n });\n}\n","import drawLine from './drawLine.js';\nimport drawJoinedLines from './drawJoinedLines.js';\n\n/**\n * Draw an arrow using the drawing API.\n * @public\n * @method drawArrow\n * @memberof Drawing\n *\n * @param {Object} context The canvas context.\n * @param {Object} start The start position.\n * @param {Object} end The end position.\n * @param {string} color The color of the arrow.\n * @param {number} lineWidth The width of the arrow line.\n * @returns {undefined}\n */\nexport default function(context, start, end, color, lineWidth) {\n // Variables to be used when creating the arrow\n const headLength = 10;\n\n const angle = Math.atan2(end.y - start.y, end.x - start.x);\n\n // Starting path of the arrow from the start square to the end square and drawing the stroke\n let options = {\n color,\n lineWidth,\n };\n\n drawLine(context, undefined, start, end, options, 'canvas');\n options = {\n color,\n lineWidth,\n fillStyle: color,\n };\n\n const points = [\n {\n x: end.x - headLength * Math.cos(angle - Math.PI / 7),\n y: end.y - headLength * Math.sin(angle - Math.PI / 7),\n },\n {\n x: end.x - headLength * Math.cos(angle + Math.PI / 7),\n y: end.y - headLength * Math.sin(angle + Math.PI / 7),\n },\n end,\n ];\n\n drawJoinedLines(context, undefined, end, points, options, 'canvas');\n}\n","import external from './../externalModules.js';\nimport path from './path.js';\n\n/**\n * Draw a circle with given `center` and `radius`.\n * @public\n * @method drawCircle\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target context\n * @param {HTMLElement} element - The DOM Element to draw on\n * @param {Object} center - `{ x, y }` in either pixel or canvas coordinates.\n * @param {number} radius - The circle's radius in canvas units.\n * @param {Object} options - See {@link path}\n * @param {String} [coordSystem='pixel'] - Can be \"pixel\" (default) or \"canvas\". The coordinate\n * system of the points passed in to the function. If \"pixel\" then cornerstone.pixelToCanvas\n * is used to transform the points from pixel to canvas coordinates.\n * @returns {undefined}\n */\nexport default function(\n context,\n element,\n center,\n radius,\n options,\n coordSystem = 'pixel'\n) {\n if (coordSystem === 'pixel') {\n center = external.cornerstone.pixelToCanvas(element, center);\n }\n\n path(context, options, context => {\n context.arc(center.x, center.y, radius, 0, 2 * Math.PI);\n });\n}\n","import external from '../externalModules.js';\n\n/**\n * Convert an Array to a cornerstoneMath.Vector3\n * @export @public @method\n * @name convertToVector3\n *\n * @param {Array|cornerstoneMath.Vector3} arrayOrVector3 Input array or Vector3\n * @returns {cornerstoneMath.Vector3}\n */\nexport default function convertToVector3(arrayOrVector3) {\n const cornerstoneMath = external.cornerstoneMath;\n\n if (arrayOrVector3 instanceof cornerstoneMath.Vector3) {\n return arrayOrVector3;\n }\n\n return new cornerstoneMath.Vector3(\n arrayOrVector3[0],\n arrayOrVector3[1],\n arrayOrVector3[2]\n );\n}\n","import external from '../externalModules.js';\nimport convertToVector3 from '../util/convertToVector3.js';\n\n/**\n * Projects a patient point to an image point\n * @export @public @method\n * @name projectPatientPointToImagePlane\n *\n * @param {Object} patientPoint The patient point.\n * @param {Object} imagePlane The image plane used for projection.\n * @returns {Object} The projected coordinates.\n */\nexport function projectPatientPointToImagePlane(patientPoint, imagePlane) {\n const rowCosines = convertToVector3(imagePlane.rowCosines);\n const columnCosines = convertToVector3(imagePlane.columnCosines);\n const imagePositionPatient = convertToVector3(\n imagePlane.imagePositionPatient\n );\n const point = patientPoint.clone().sub(imagePositionPatient);\n const x = rowCosines.dot(point) / imagePlane.columnPixelSpacing;\n const y = columnCosines.dot(point) / imagePlane.rowPixelSpacing;\n\n return {\n x,\n y,\n };\n}\n\n//\n/**\n * Projects an image point to a patient point\n * @export @public @method\n * @name imagePointToPatientPoint\n *\n * @param {Object} imagePoint The image point.\n * @param {Object} imagePlane The image plane used for projection.\n * @returns {Object} The projected coordinates.\n */\nexport function imagePointToPatientPoint(imagePoint, imagePlane) {\n const rowCosines = convertToVector3(imagePlane.rowCosines);\n const columnCosines = convertToVector3(imagePlane.columnCosines);\n const imagePositionPatient = convertToVector3(\n imagePlane.imagePositionPatient\n );\n\n const x = rowCosines.clone().multiplyScalar(imagePoint.x);\n\n x.multiplyScalar(imagePlane.columnPixelSpacing);\n const y = columnCosines.clone().multiplyScalar(imagePoint.y);\n\n y.multiplyScalar(imagePlane.rowPixelSpacing);\n const patientPoint = x.add(y);\n\n patientPoint.add(imagePositionPatient);\n\n return patientPoint;\n}\n\n/**\n * Returns a rectangle from the imagePlane.\n * @export @public @method\n * @name getRectangleFromImagePlane\n *\n * @param {Object} imagePlane The imagePlane.\n * @returns {Object} The rect.\n */\nfunction getRectangleFromImagePlane(imagePlane) {\n // Get the points\n const topLeft = imagePointToPatientPoint(\n {\n x: 0,\n y: 0,\n },\n imagePlane\n );\n const topRight = imagePointToPatientPoint(\n {\n x: imagePlane.columns,\n y: 0,\n },\n imagePlane\n );\n const bottomLeft = imagePointToPatientPoint(\n {\n x: 0,\n y: imagePlane.rows,\n },\n imagePlane\n );\n const bottomRight = imagePointToPatientPoint(\n {\n x: imagePlane.columns,\n y: imagePlane.rows,\n },\n imagePlane\n );\n\n // Get each side as a vector\n const rect = {\n top: new external.cornerstoneMath.Line3(topLeft, topRight),\n left: new external.cornerstoneMath.Line3(topLeft, bottomLeft),\n right: new external.cornerstoneMath.Line3(topRight, bottomRight),\n bottom: new external.cornerstoneMath.Line3(bottomLeft, bottomRight),\n };\n\n return rect;\n}\n\n/**\n * Gets all the intersections of a line with a rect.\n * @private\n * @method\n * @name lineRectangleIntersection\n *\n * @param {Object} line The line to check.\n * @param {Object} rect The rect being intersected.\n * @returns {Object[]} An array of the intersections.\n */\nfunction lineRectangleIntersection(line, rect) {\n const intersections = [];\n\n Object.keys(rect).forEach(function(side) {\n const segment = rect[side];\n const intersection = line.intersectLine(segment);\n\n if (intersection) {\n intersections.push(intersection);\n }\n });\n\n return intersections;\n}\n\n/**\n * Gets the line of intersection between two planes in patient space.\n * @export @public @method\n * @name planePlaneIntersection\n *\n * @param {Object} targetImagePlane The target plane.\n * @param {Object} referenceImagePlane The reference plane\n * @returns {Object} The intersections.\n */\nexport function planePlaneIntersection(targetImagePlane, referenceImagePlane) {\n const targetRowCosines = convertToVector3(targetImagePlane.rowCosines);\n const targetColumnCosines = convertToVector3(targetImagePlane.columnCosines);\n const targetImagePositionPatient = convertToVector3(\n targetImagePlane.imagePositionPatient\n );\n const referenceRowCosines = convertToVector3(referenceImagePlane.rowCosines);\n const referenceColumnCosines = convertToVector3(\n referenceImagePlane.columnCosines\n );\n const referenceImagePositionPatient = convertToVector3(\n referenceImagePlane.imagePositionPatient\n );\n\n // First, get the normals of each image plane\n const targetNormal = targetRowCosines.clone().cross(targetColumnCosines);\n const targetPlane = new external.cornerstoneMath.Plane();\n\n targetPlane.setFromNormalAndCoplanarPoint(\n targetNormal,\n targetImagePositionPatient\n );\n\n const referenceNormal = referenceRowCosines\n .clone()\n .cross(referenceColumnCosines);\n const referencePlane = new external.cornerstoneMath.Plane();\n\n referencePlane.setFromNormalAndCoplanarPoint(\n referenceNormal,\n referenceImagePositionPatient\n );\n\n const originDirection = referencePlane.clone().intersectPlane(targetPlane);\n const origin = originDirection.origin;\n const direction = originDirection.direction;\n\n // Calculate the longest possible length in the reference image plane (the length of the diagonal)\n const bottomRight = imagePointToPatientPoint(\n {\n x: referenceImagePlane.columns,\n y: referenceImagePlane.rows,\n },\n referenceImagePlane\n );\n const distance = referenceImagePositionPatient.distanceTo(bottomRight);\n\n // Use this distance to bound the ray intersecting the two planes\n const line = new external.cornerstoneMath.Line3();\n\n line.start = origin;\n line.end = origin.clone().add(direction.multiplyScalar(distance));\n\n // Find the intersections between this line and the reference image plane's four sides\n const rect = getRectangleFromImagePlane(referenceImagePlane);\n const intersections = lineRectangleIntersection(line, rect);\n\n // Return the intersections between this line and the reference image plane's sides\n // In order to draw the reference line from the target image.\n if (intersections.length !== 2) {\n return;\n }\n\n return {\n start: intersections[0],\n end: intersections[1],\n };\n}\n\n/**\n * Translate a point using a rotation angle.\n * @export @public @method\n * @name rotatePoint\n *\n * @param {Object} point - `{ x, y }` in either pixel or canvas coordinates.\n * @param {Object} center - `{ x, y }` in either pixel or canvas coordinates.\n * @param {Number} angle - angle in degrees\n * @returns {Object} - `{ x, y }` new point translated\n */\nexport function rotatePoint(point, center, angle) {\n const angleRadians = angle * (Math.PI / 180); // Convert to radians\n\n const rotatedX =\n Math.cos(angleRadians) * (point.x - center.x) -\n Math.sin(angleRadians) * (point.y - center.y) +\n center.x;\n\n const rotatedY =\n Math.sin(angleRadians) * (point.x - center.x) +\n Math.cos(angleRadians) * (point.y - center.y) +\n center.y;\n\n return {\n x: rotatedX,\n y: rotatedY,\n };\n}\n","import external from './../externalModules.js';\nimport path from './path.js';\nimport { rotatePoint } from '../util/pointProjector.js';\n\n/**\n * Draw an ellipse within the bounding box defined by `corner1` and `corner2`.\n * @public\n * @method drawEllipse\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target context\n * @param {HTMLElement} element - The DOM Element to draw on\n * @param {Object} corner1 - `{ x, y }` in either pixel or canvas coordinates.\n * @param {Object} corner2 - `{ x, y }` in either pixel or canvas coordinates.\n * @param {Object} options - See {@link path}\n * @param {String} [coordSystem='pixel'] - Can be \"pixel\" (default) or \"canvas\". The coordinate\n * system of the points passed in to the function. If \"pixel\" then cornerstone.pixelToCanvas\n * is used to transform the points from pixel to canvas coordinates.\n * @param {Number} initialRotation - Ellipse initial rotation\n * @returns {undefined}\n */\nexport default function(\n context,\n element,\n corner1,\n corner2,\n options,\n coordSystem = 'pixel',\n initialRotation = 0.0\n) {\n if (coordSystem === 'pixel') {\n corner1 = external.cornerstone.pixelToCanvas(element, corner1);\n corner2 = external.cornerstone.pixelToCanvas(element, corner2);\n }\n\n const viewport = external.cornerstone.getViewport(element);\n\n // Calculate the center of the image\n const { clientWidth: width, clientHeight: height } = element;\n const { scale, translation } = viewport;\n const rotation = viewport.rotation - initialRotation;\n\n const centerPoint = {\n x: width / 2 + translation.x * scale,\n y: height / 2 + translation.y * scale,\n };\n\n if (Math.abs(rotation) > 0.05) {\n corner1 = rotatePoint(corner1, centerPoint, -rotation);\n corner2 = rotatePoint(corner2, centerPoint, -rotation);\n }\n const w = Math.abs(corner1.x - corner2.x);\n const h = Math.abs(corner1.y - corner2.y);\n const xMin = Math.min(corner1.x, corner2.x);\n const yMin = Math.min(corner1.y, corner2.y);\n\n let center = {\n x: xMin + w / 2,\n y: yMin + h / 2,\n };\n\n if (Math.abs(rotation) > 0.05) {\n center = rotatePoint(center, centerPoint, rotation);\n }\n const angle = (rotation * Math.PI) / 180;\n\n path(context, options, context => {\n context.ellipse(center.x, center.y, w / 2, h / 2, angle, 0, 2 * Math.PI);\n context.closePath();\n });\n}\n","let defaultColor = 'white',\n activeColor = 'greenyellow',\n fillColor = 'transparent';\n\nfunction setFillColor(color) {\n fillColor = color;\n}\n\nfunction getFillColor() {\n return fillColor;\n}\n\nfunction setToolColor(color) {\n defaultColor = color;\n}\n\nfunction getToolColor() {\n return defaultColor;\n}\n\nfunction setActiveColor(color) {\n activeColor = color;\n}\n\nfunction getActiveColor() {\n return activeColor;\n}\n\nfunction getColorIfActive(data) {\n if (data.color) {\n return data.color;\n }\n\n return data.active ? activeColor : defaultColor;\n}\n\nconst toolColors = {\n setFillColor,\n getFillColor,\n setToolColor,\n getToolColor,\n setActiveColor,\n getActiveColor,\n getColorIfActive,\n};\n\nexport default toolColors;\n","import external from './../externalModules.js';\nimport toolStyle from './../stateManagement/toolStyle.js';\nimport toolColors from './../stateManagement/toolColors.js';\nimport path from './path.js';\nimport { state } from './../store/index.js';\n\n/**\n * Draws proivded handles to the provided context\n * @public\n * @method drawHandles\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target context\n * @param {*} evtDetail - Cornerstone's 'cornerstoneimagerendered' event's `detail`\n * @param {Object[]|Object} handles - An array of handle objects, or an object w/ named handle objects\n * @param {Object} [options={}] - Options object\n * @param {string} [options.color]\n * @param {Boolean} [options.drawHandlesIfActive=false] - Whether the handles should only be drawn if Active (hovered/selected)\n * @param {string} [options.fill]\n * @param {Number} [options.handleRadius=6]\n * @returns {undefined}\n */\nexport default function(context, evtDetail, handles, options = {}) {\n const element = evtDetail.element;\n const defaultColor = toolColors.getToolColor();\n\n context.strokeStyle = options.color || defaultColor;\n\n const handleKeys = Object.keys(handles);\n\n for (let i = 0; i < handleKeys.length; i++) {\n const handleKey = handleKeys[i];\n const handle = handles[handleKey];\n\n if (handle.drawnIndependently === true) {\n continue;\n }\n\n if (options.drawHandlesIfActive === true && !handle.active) {\n continue;\n }\n\n const lineWidth = handle.active\n ? toolStyle.getActiveWidth()\n : toolStyle.getToolWidth();\n const fillStyle = options.fill;\n\n path(\n context,\n {\n lineWidth,\n fillStyle,\n },\n context => {\n const handleCanvasCoords = external.cornerstone.pixelToCanvas(\n element,\n handle\n );\n\n // Handle's radisu, then tool's radius, then default radius\n const handleRadius =\n handle.radius || options.handleRadius || state.handleRadius;\n\n context.arc(\n handleCanvasCoords.x,\n handleCanvasCoords.y,\n handleRadius,\n 0,\n 2 * Math.PI\n );\n }\n );\n }\n}\n","import external from './../externalModules.js';\nimport path from './path.js';\n\n/**\n * Draw multiple lines.\n * @public\n * @method drawJoinedLines\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target context\n * @param {HTMLElement} element - The DOM Element to draw on\n * @param {Object[]} lines - `[{ start: {x, y}, end: { x, y }]` An array of `start`, `end` pairs.\n * Each point is `{ x, y }` in either pixel or canvas coordinates.\n * @param {Object} options - See {@link path}\n * @param {String} [coordSystem='pixel'] - Can be \"pixel\" (default) or \"canvas\". The coordinate\n * system of the points passed in to the function. If \"pixel\" then cornerstone.pixelToCanvas\n * is used to transform the points from pixel to canvas coordinates.\n * @returns {undefined}\n */\nexport default function(\n context,\n element,\n lines,\n options,\n coordSystem = 'pixel'\n) {\n path(context, options, context => {\n lines.forEach(line => {\n let start = line.start;\n let end = line.end;\n\n if (coordSystem === 'pixel') {\n const cornerstone = external.cornerstone;\n\n start = cornerstone.pixelToCanvas(element, start);\n end = cornerstone.pixelToCanvas(element, end);\n }\n\n context.moveTo(start.x, start.y);\n context.lineTo(end.x, end.y);\n });\n });\n}\n","import external from '../externalModules.js';\nimport drawLine from './drawLine.js';\n\n/**\n * Draw a link between an annotation to a box.\n * @public\n * @method drawLink\n * @memberof Drawing\n *\n * @param {Object[]} linkAnchorPoints An array of possible anchor points.\n * @param {Object} refPoint A reference point to select the anchor point.\n * @param {Object} boundingBox The bounding box to link.\n * @param {Object} context The canvas context.\n * @param {string} color The link color.\n * @param {number} lineWidth The line width of the link.\n * @returns {undefined}\n */\nexport default function(\n linkAnchorPoints,\n refPoint,\n boundingBox,\n context,\n color,\n lineWidth\n) {\n // Draw a link from \"the closest anchor point to refPoint\" to \"the nearest midpoint on the bounding box\".\n\n // Find the closest anchor point to RefPoint\n const start =\n linkAnchorPoints.length > 0\n ? external.cornerstoneMath.point.findClosestPoint(\n linkAnchorPoints,\n refPoint\n )\n : refPoint;\n\n // Calculate the midpoints of the bounding box\n const boundingBoxPoints = [\n {\n x: boundingBox.left + boundingBox.width / 2,\n y: boundingBox.top,\n },\n {\n x: boundingBox.left,\n y: boundingBox.top + boundingBox.height / 2,\n },\n {\n x: boundingBox.left + boundingBox.width / 2,\n y: boundingBox.top + boundingBox.height,\n },\n {\n x: boundingBox.left + boundingBox.width,\n y: boundingBox.top + boundingBox.height / 2,\n },\n ];\n\n // Calculate the link endpoint by identifying which midpoint of the bounding box\n // Is closest to the start point.\n const end = external.cornerstoneMath.point.findClosestPoint(\n boundingBoxPoints,\n start\n );\n\n // Finally we draw the dashed linking line\n const options = {\n color,\n lineWidth,\n lineDash: [2, 3],\n };\n\n drawLine(context, undefined, start, end, options, 'canvas');\n}\n","let defaultFontSize = 15,\n defaultFont = `${defaultFontSize}px Arial`,\n defaultBackgroundColor = 'transparent';\n\nfunction setFont(font) {\n defaultFont = font;\n}\n\nfunction getFont() {\n return defaultFont;\n}\n\nfunction setFontSize(fontSize) {\n defaultFontSize = fontSize;\n}\n\nfunction getFontSize() {\n return defaultFontSize;\n}\n\nfunction setBackgroundColor(backgroundColor) {\n defaultBackgroundColor = backgroundColor;\n}\n\nfunction getBackgroundColor() {\n return defaultBackgroundColor;\n}\n\nconst textStyle = {\n setFont,\n getFont,\n setFontSize,\n getFontSize,\n setBackgroundColor,\n getBackgroundColor,\n};\n\nexport default textStyle;\n","import textStyle from './../stateManagement/textStyle.js';\n\n/**\n * Draw multiple lines of text within a bounding box.\n * @public\n * @method fillTextLines\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target context\n * @param {Object} boundingBox - `{ left, top }` in canvas coordinates. Only the top-left corner is specified, as the text will take up as much space as it needs.\n * @param {String[]} textLines - The text to be displayed.\n * @param {FillStyle} fillStyle - The fillStyle to apply to the text.\n * @param {Number} padding - The amount of padding above/below each line in canvas units. Note this gives an inter-line spacing of `2*padding`.\n * @returns {undefined}\n */\nexport default function(context, boundingBox, textLines, fillStyle, padding) {\n const fontSize = textStyle.getFontSize();\n\n context.font = textStyle.getFont();\n context.textBaseline = 'top';\n context.fillStyle = fillStyle;\n textLines.forEach(function(text, index) {\n context.fillText(\n text,\n boundingBox.left + padding,\n boundingBox.top + padding + index * (fontSize + padding)\n );\n });\n}\n","/**\n * Draw a filled rectangle defined by `boundingBox` using the style defined by `fillStyle`.\n * @public\n * @method fillBox\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target context\n * @param {Object} boundingBox - `{ left, top, width, height }` in canvas coordinates.\n * @param {FillStyle} fillStyle - The fillStyle to apply to the region.\n * @returns {undefined}\n */\nexport default function(context, boundingBox, fillStyle) {\n context.fillStyle = fillStyle;\n context.fillRect(\n boundingBox.left,\n boundingBox.top,\n boundingBox.width,\n boundingBox.height\n );\n}\n","import textStyle from '../stateManagement/textStyle.js';\nimport draw from './draw.js';\nimport fillTextLines from './fillTextLines.js';\nimport fillBox from './fillBox.js';\n\n/**\n * Compute the width of the box required to display the given `text` with a given `padding`.\n * @public\n * @function textBoxWidth\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target context\n * @param {String} text - The text to find the width of.\n * @param {Number} padding - The padding to apply on either end of the text.\n * @returns {Number} computed text box width\n */\nexport function textBoxWidth(context, text, padding) {\n const font = textStyle.getFont();\n const origFont = context.font;\n\n if (font && font !== origFont) {\n context.font = font;\n }\n const width = context.measureText(text).width;\n\n if (font && font !== origFont) {\n context.font = origFont;\n }\n\n return width + 2 * padding;\n}\n\n/**\n * Draws a textBox.\n * @public\n * @function drawTextBox\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context The canvas context.\n * @param {string} textLines The text to display.\n * @param {number} x The x position of the textBox.\n * @param {number} y The y position of the textBox.\n * @param {string} color The color of the textBox.\n * @param {Object} options Options for the textBox.\n * @returns {Object} {top, left, width, height} - Bounding box; can be used for pointNearTool\n */\nexport default function(context, textLines, x, y, color, options) {\n if (Object.prototype.toString.call(textLines) !== '[object Array]') {\n textLines = [textLines];\n }\n\n const padding = 5;\n const fontSize = textStyle.getFontSize();\n const backgroundColor = textStyle.getBackgroundColor();\n\n // Find the longest text width in the array of text data\n let maxWidth = 0;\n\n textLines.forEach(function(text) {\n // Get the text width in the current font\n const width = textBoxWidth(context, text, padding);\n\n // Find the maximum with for all the text rows;\n maxWidth = Math.max(maxWidth, width);\n });\n\n // Calculate the bounding box for this text box\n const boundingBox = {\n width: maxWidth,\n height: padding + textLines.length * (fontSize + padding),\n };\n\n draw(context, context => {\n context.strokeStyle = color;\n\n // Draw the background box with padding\n if (options && options.centering && options.centering.x === true) {\n x -= boundingBox.width / 2;\n }\n\n if (options && options.centering && options.centering.y === true) {\n y -= boundingBox.height / 2;\n }\n\n boundingBox.left = x;\n boundingBox.top = y;\n\n const fillStyle =\n options && options.debug === true ? '#FF0000' : backgroundColor;\n\n fillBox(context, boundingBox, fillStyle);\n\n // Draw each of the text lines on top of the background box\n fillTextLines(context, boundingBox, textLines, color, padding);\n });\n\n // Return the bounding box so it can be used for pointNearHandle\n return boundingBox;\n}\n","import external from '../externalModules.js';\nimport drawTextBox from './drawTextBox.js';\nimport drawLink from './drawLink.js';\n\n/**\n * Draw a link between an annotation to a textBox.\n * @public\n * @method drawLinkedTextBox\n * @memberof Drawing\n *\n * @param {Object} context - The canvas context.\n * @param {HTMLElement} element - The element on which to draw the link.\n * @param {Object} textBox - The textBox to link.\n * @param {Object} text - The text to display in the textbox.\n * @param {Object[]} handles - The handles of the annotation.\n * @param {Object[]} textBoxAnchorPoints - An array of possible anchor points on the textBox.\n * @param {string} color - The link color.\n * @param {number} lineWidth - The line width of the link.\n * @param {number} xOffset - The x offset of the textbox.\n * @param {boolean} yCenter - Vertically centers the text if true.\n * @returns {undefined}\n */\nexport default function(\n context,\n element,\n textBox,\n text,\n handles,\n textBoxAnchorPoints,\n color,\n lineWidth,\n xOffset,\n yCenter\n) {\n const cornerstone = external.cornerstone;\n\n // Convert the textbox Image coordinates into Canvas coordinates\n const textCoords = cornerstone.pixelToCanvas(element, textBox);\n\n if (xOffset) {\n textCoords.x += xOffset;\n }\n\n const options = {\n centering: {\n x: false,\n y: yCenter,\n },\n };\n\n // Draw the text box\n textBox.boundingBox = drawTextBox(\n context,\n text,\n textCoords.x,\n textCoords.y,\n color,\n options\n );\n if (textBox.hasMoved) {\n // Identify the possible anchor points for the tool -> text line\n const linkAnchorPoints = textBoxAnchorPoints(handles).map(h =>\n cornerstone.pixelToCanvas(element, h)\n );\n\n // Draw dashed link line between tool and text\n drawLink(\n linkAnchorPoints,\n textCoords,\n textBox.boundingBox,\n context,\n color,\n lineWidth\n );\n }\n}\n","import external from './../externalModules.js';\nimport path from './path.js';\nimport { rotatePoint } from '../util/pointProjector.js';\n\n/**\n * Draw a rectangle defined by `corner1` and `corner2`.\n * @public\n * @method drawRect\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target context\n * @param {HTMLElement} element - The DOM Element to draw on\n * @param {Object} corner1 - `{ x, y }` in either pixel or canvas coordinates.\n * @param {Object} corner2 - `{ x, y }` in either pixel or canvas coordinates.\n * @param {Object} options - See {@link path}\n * @param {String} [coordSystem='pixel'] - Can be \"pixel\" (default) or \"canvas\". The coordinate\n * system of the points passed in to the function. If \"pixel\" then cornerstone.pixelToCanvas\n * is used to transform the points from pixel to canvas coordinates.\n * @param {Number} initialRotation - Rectangle initial rotation\n * @returns {undefined}\n */\nexport default function(\n context,\n element,\n corner1,\n corner2,\n options,\n coordSystem = 'pixel',\n initialRotation = 0.0\n) {\n if (coordSystem === 'pixel') {\n const cornerstone = external.cornerstone;\n\n corner1 = cornerstone.pixelToCanvas(element, corner1);\n corner2 = cornerstone.pixelToCanvas(element, corner2);\n }\n\n const viewport = external.cornerstone.getViewport(element);\n\n // Calculate the center of the image\n const { clientWidth: width, clientHeight: height } = element;\n const { scale, translation } = viewport;\n const rotation = viewport.rotation - initialRotation;\n\n const centerPoint = {\n x: width / 2 + translation.x * scale,\n y: height / 2 + translation.y * scale,\n };\n\n if (Math.abs(rotation) > 0.05) {\n corner1 = rotatePoint(corner1, centerPoint, -rotation);\n corner2 = rotatePoint(corner2, centerPoint, -rotation);\n }\n\n const w = Math.abs(corner1.x - corner2.x);\n const h = Math.abs(corner1.y - corner2.y);\n\n corner1 = {\n x: Math.min(corner1.x, corner2.x),\n y: Math.min(corner1.y, corner2.y),\n };\n\n corner2 = {\n x: corner1.x + w,\n y: corner1.y + h,\n };\n\n let corner3 = {\n x: corner1.x + w,\n y: corner1.y,\n };\n\n let corner4 = {\n x: corner1.x,\n y: corner1.y + h,\n };\n\n if (Math.abs(rotation) > 0.05) {\n corner1 = rotatePoint(corner1, centerPoint, rotation);\n corner2 = rotatePoint(corner2, centerPoint, rotation);\n corner3 = rotatePoint(corner3, centerPoint, rotation);\n corner4 = rotatePoint(corner4, centerPoint, rotation);\n }\n\n path(context, options, context => {\n context.moveTo(corner1.x, corner1.y);\n context.lineTo(corner3.x, corner3.y);\n context.moveTo(corner3.x, corner3.y);\n context.lineTo(corner2.x, corner2.y);\n context.moveTo(corner2.x, corner2.y);\n context.lineTo(corner4.x, corner4.y);\n context.moveTo(corner4.x, corner4.y);\n context.lineTo(corner1.x, corner1.y);\n });\n}\n","/**\n * Create a new {@link CanvasRenderingContext2D|context} object for the given {@link HTMLCanvasElement|canvas}\n * and set the transform to the {@link https://www.w3.org/TR/2dcontext/#transformations|identity transform}.\n *\n * @public\n * @function getNewContext\n * @memberof Drawing\n *\n * @param {HTMLCanvasElement} canvas - Canvas you would like the context for\n * @returns {CanvasRenderingContext2D} - The provided canvas's 2d context\n */\nexport default function(canvas) {\n const context = canvas.getContext('2d');\n\n context.setTransform(1, 0, 0, 1, 0, 0);\n\n return context;\n}\n","/**\n * Returns the first argument if defined, otherwise returns the second\n *\n * @param {*} value\n * @param {*} defaultValue\n * @returns {*}\n */\nexport default function(value, defaultValue) {\n return value === undefined ? defaultValue : value;\n}\n","import getDefault from './../util/getDefault.js';\n\n/**\n * Set the {@link https://www.w3.org/TR/2dcontext/#shadows|shadow} properties of the context.\n * Each property is set on the context object if defined, otherwise a default value is set.\n *\n * @public\n * @method setShadow\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Context to apply shadow options on\n * @param {Object} [options={}] - Options object\n * @param {Boolean} [options.shadow=undefined] - Whether to set any shadow options\n * @param {String} [options.shadowColor=#000000] - Default value: #000000\n * @param {Number} [options.shadowBlur=0] - Default Value: 0\n * @param {Number} [options.shadowOffsetX=1] - Default value: 1\n * @param {Number} [options.shadowOffsetY=1] - Default value: 1\n * @returns {undefined}\n */\nexport default function(context, options = {}) {\n if (options.shadow) {\n context.shadowColor = getDefault(options.shadowColor, '#000000');\n context.shadowBlur = getDefault(options.shadowBlur, 0);\n context.shadowOffsetX = getDefault(options.shadowOffsetX, 1);\n context.shadowOffsetY = getDefault(options.shadowOffsetY, 1);\n }\n}\n","/**\n * Transform the canvas {@link CanvasRenderingContext2D|context} such that it\n * coincides with the orientation of the viewport.\n *\n * @public\n * @function transformCanvasContext\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Context you wish to transform.\n * @param {HTMLCanvasElement} canvas - Canvas the context relates to.\n * @param {*} viewport - The viewport you wish to map on to.\n * @returns {void}\n */\nexport default function(context, canvas, viewport) {\n if (!(viewport.hflip || viewport.vflip || viewport.rotation)) {\n return;\n }\n\n const translation = {\n x: canvas.width / 2 + viewport.translation.x * viewport.scale,\n y: canvas.height / 2 + viewport.translation.y * viewport.scale,\n };\n\n context.translate(translation.x, translation.y);\n\n if (viewport.rotation) {\n context.rotate((viewport.rotation * Math.PI) / 180);\n }\n\n if (viewport.vflip) {\n context.scale(1, -1);\n }\n\n if (viewport.hflip) {\n context.scale(-1, 1);\n }\n\n context.translate(-translation.x, -translation.y);\n}\n","/**\n * Resets the canvas {@link CanvasRenderingContext2D|context} transform to the\n * {@link https://www.w3.org/TR/2dcontext/#transformations|identity transform}.\n *\n * @public\n * @function resetCanvasContextTransform\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - context you wish to transform\n * @returns {void}\n */\nexport default function(context) {\n context.setTransform(1, 0, 0, 1, 0, 0);\n}\n","/**\n * Helper to determine if an object has no keys and is the correct type (is empty)\n *\n * @private\n * @function isEmptyObject\n * @param {Object} obj The object to check\n * @returns {Boolean} true if the object is empty\n */\nconst isEmptyObject = obj =>\n Object.keys(obj).length === 0 && obj.constructor === Object;\n\nexport default isEmptyObject;\n","import { draw, drawCircle, getNewContext } from '../../drawing';\nimport external from '../../externalModules';\nimport _isEmptyObject from '../../util/isEmptyObject';\nimport { getModule } from '../../store';\nimport { getDiffBetweenPixelData } from '../../util/segmentation';\n\nconst { getters, setters } = getModule('segmentation');\n\n/**\n * Sets the start and end handle points to empty objects\n *\n * @private\n * @method _resetHandles\n * @returns {undefined}\n */\nfunction _resetHandles() {\n this.handles = {\n start: {},\n end: {},\n };\n}\n\n/**\n * Render hook: draws the Scissors's outline, box, or circle\n *\n * @param {Object} evt Cornerstone.event#cornerstoneimagerendered > cornerstoneimagerendered event\n * @memberof Tools.ScissorsTool\n * @returns {void}\n */\nfunction renderToolData(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n const color = getters.brushColor(element, true);\n const context = getNewContext(eventData.canvasContext.canvas);\n const { distance } = external.cornerstoneMath.point;\n\n draw(context, context => {\n if (!this.handles) {\n return null;\n }\n const startCanvas = external.cornerstone.pixelToCanvas(\n element,\n this.handles.start\n );\n\n const endCanvas = external.cornerstone.pixelToCanvas(\n element,\n this.handles.end\n );\n\n // Calculating the radius where startCanvas is the center of the circle to be drawn\n const radius = distance(startCanvas, endCanvas);\n\n // Draw Circle\n drawCircle(context, element, this.handles.start, radius, { color });\n });\n}\n\n/**\n * Sets the start handle point and claims the eventDispatcher event\n *\n * @private\n * @param {*} evt // mousedown, touchstart, click\n * @returns {Boolean} True\n */\nfunction _startOutliningRegion(evt) {\n const consumeEvent = true;\n const element = evt.detail.element;\n const image = evt.detail.currentPoints.image;\n\n if (_isEmptyObject(this.handles.start)) {\n this.handles.start = image;\n } else {\n this.handles.end = image;\n this._applyStrategy(evt);\n }\n\n external.cornerstone.updateImage(element);\n\n return consumeEvent;\n}\n\n/**\n * This function will update the handles and updateImage to force re-draw\n *\n * @private\n * @method _setHandlesAndUpdate\n * @param {(CornerstoneTools.event#TOUCH_DRAG|CornerstoneTools.event#MOUSE_DRAG|CornerstoneTools.event#MOUSE_MOVE)} evt Interaction event emitted by an enabledElement\n * @returns {void}\n */\nfunction _setHandlesAndUpdate(evt) {\n const { element, currentPoints } = evt.detail;\n const { image } = currentPoints;\n\n this.handles.end = image;\n external.cornerstone.updateImage(element);\n}\n\n/**\n * Event handler for MOUSE_UP/TOUCH_END during handle drag event loop.\n *\n * @private\n * @method _applyStrategy\n * @param {(CornerstoneTools.event#MOUSE_UP|CornerstoneTools.event#TOUCH_END)} evt Interaction event emitted by an enabledElement\n * @returns {void}\n */\nfunction _applyStrategy(evt) {\n evt.detail.handles = this.handles;\n const { element } = evt.detail;\n\n const { labelmap2D, labelmap3D, currentImageIdIndex } = getters.labelmap2D(\n element\n );\n\n const pixelData = labelmap2D.pixelData;\n const previousPixeldata = pixelData.slice();\n\n const points = {\n start: {\n x: this.handles.start.x,\n y: this.handles.start.y,\n },\n end: {\n x: this.handles.end.x,\n y: this.handles.end.y,\n },\n };\n\n const operationData = {\n points,\n pixelData,\n segmentIndex: labelmap3D.activeSegmentIndex,\n segmentationMixinType: `circleSegmentationMixin`,\n };\n\n this.applyActiveStrategy(evt, operationData);\n\n const operation = {\n imageIdIndex: currentImageIdIndex,\n diff: getDiffBetweenPixelData(previousPixeldata, pixelData),\n };\n\n setters.pushState(this.element, [operation]);\n\n // Invalidate the brush tool data so it is redrawn\n setters.updateSegmentsOnLabelmap2D(labelmap2D);\n external.cornerstone.updateImage(element);\n\n this._resetHandles();\n}\n\n/**\n * @mixin circleSegmentationMixin - Segmentation operations for circles.\n * @memberof Mixins\n */\nexport default {\n postTouchStartCallback: _startOutliningRegion,\n postMouseDownCallback: _startOutliningRegion,\n mouseClickCallback: _startOutliningRegion,\n touchDragCallback: _setHandlesAndUpdate,\n mouseDragCallback: _setHandlesAndUpdate,\n mouseMoveCallback: _setHandlesAndUpdate,\n touchEndCallback: _applyStrategy,\n mouseUpCallback: _applyStrategy,\n initializeMixin: _resetHandles,\n renderToolData,\n _resetHandles,\n _applyStrategy,\n};\n","import external from '../../externalModules.js';\nimport { getModule } from '../../store';\nimport { getLogger } from '../../util/logger.js';\nimport { draw, drawJoinedLines, getNewContext } from '../../drawing';\nimport { getDiffBetweenPixelData } from '../../util/segmentation';\n\nconst logger = getLogger('tools:ScissorsTool');\n\nconst { getters, setters } = getModule('segmentation');\n\n/**\n * Render hook: draws the FreehandScissors's outline\n *\n * @param {Object} evt Cornerstone.event#cornerstoneimagerendered > cornerstoneimagerendered event\n * @memberof Tools.ScissorsTool\n * @returns {void}\n */\nfunction renderToolData(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n const color = getters.brushColor(element, true);\n const context = getNewContext(eventData.canvasContext.canvas);\n const points = this.handles.points;\n\n if (points.length < 2) {\n return;\n }\n\n draw(context, context => {\n for (let j = 0; j < points.length; j++) {\n const lines = [...points[j].lines];\n\n if (j === points.length - 1) {\n // If it's still being actively drawn, keep the last line to\n // The mouse location\n lines.push(points[0]);\n }\n drawJoinedLines(context, element, points[j], lines, {\n color,\n });\n }\n });\n}\n\n/**\n * Sets the start handle point and claims the eventDispatcher event\n *\n * @private\n * @param {*} evt // mousedown, touchstart, click\n * @returns {void|null}\n */\nfunction _startOutliningRegion(evt) {\n const element = evt.detail.element;\n const image = evt.detail.currentPoints.image;\n const points = this.handles.points;\n\n if (!points.length) {\n logger.warn('Something went wrong, empty handles detected.');\n\n return null;\n }\n\n points.push({\n x: image.x,\n y: image.y,\n lines: [],\n });\n\n this.currentHandle += 1;\n\n external.cornerstone.updateImage(element);\n}\n\n/**\n * This function will update the handles and updateImage to force re-draw\n *\n * @private\n * @method _setHandlesAndUpdate\n * @param {(CornerstoneTools.event#TOUCH_DRAG|CornerstoneTools.event#MOUSE_DRAG|CornerstoneTools.event#MOUSE_MOVE)} evt Interaction event emitted by an enabledElement\n * @returns {void}\n */\nfunction _setHandlesAndUpdate(evt) {\n const eventData = evt.detail;\n const element = evt.detail.element;\n\n this._addPoint(eventData);\n external.cornerstone.updateImage(element);\n}\n\n/**\n * Event handler for MOUSE_UP/TOUCH_END during handle drag event loop.\n *\n * @private\n * @method _applyStrategy\n * @param {(CornerstoneTools.event#MOUSE_UP|CornerstoneTools.event#TOUCH_END)} evt Interaction event emitted by an enabledElement\n * @returns {void}\n */\nfunction _applyStrategy(evt) {\n const points = this.handles.points;\n const { element } = evt.detail;\n\n const { labelmap2D, labelmap3D, currentImageIdIndex } = getters.labelmap2D(\n element\n );\n\n const pixelData = labelmap2D.pixelData;\n const previousPixeldata = pixelData.slice();\n\n const operationData = {\n points,\n pixelData,\n segmentIndex: labelmap3D.activeSegmentIndex,\n segmentationMixinType: `freehandSegmentationMixin`,\n };\n\n this.applyActiveStrategy(evt, operationData);\n\n const operation = {\n imageIdIndex: currentImageIdIndex,\n diff: getDiffBetweenPixelData(previousPixeldata, pixelData),\n };\n\n setters.pushState(this.element, [operation]);\n\n // Invalidate the brush tool data so it is redrawn\n setters.updateSegmentsOnLabelmap2D(labelmap2D);\n external.cornerstone.updateImage(element);\n\n this._resetHandles();\n}\n\n/**\n * Sets the start and end handle points to empty objects\n *\n * @private\n * @method _resetHandles\n * @returns {undefined}\n */\nfunction _resetHandles() {\n this.handles = {\n points: [],\n };\n\n this.currentHandle = 0;\n}\n\n/**\n * Adds a point on mouse click in polygon mode.\n *\n * @private\n * @param {Object} evt - data object associated with an event.\n * @returns {void}\n */\nfunction _addPoint(evt) {\n const points = this.handles.points;\n\n if (points.length) {\n // Add the line from the current handle to the new handle\n points[this.currentHandle - 1].lines.push({\n x: evt.currentPoints.image.x,\n y: evt.currentPoints.image.y,\n lines: [],\n });\n }\n\n // Add the new handle\n points.push({\n x: evt.currentPoints.image.x,\n y: evt.currentPoints.image.y,\n lines: [],\n });\n\n // Increment the current handle value\n this.currentHandle += 1;\n\n // Force onImageRendered to fire\n external.cornerstone.updateImage(evt.element);\n}\n\n/**\n * @mixin freehandSegmentationMixin - segmentation operations for freehand\n * @memberof Mixins\n */\nexport default {\n postTouchStartCallback: _startOutliningRegion,\n postMouseDownCallback: _startOutliningRegion,\n mouseClickCallback: _startOutliningRegion,\n touchDragCallback: _setHandlesAndUpdate,\n mouseDragCallback: _setHandlesAndUpdate,\n mouseMoveCallback: _setHandlesAndUpdate,\n touchEndCallback: _applyStrategy,\n mouseUpCallback: _applyStrategy,\n initializeMixin: _resetHandles,\n renderToolData,\n _resetHandles,\n _addPoint,\n _applyStrategy,\n};\n","import { draw, drawJoinedLines, getNewContext } from '../../drawing';\nimport { getModule } from '../../store';\nimport freehandSegmentationMixin from './freehandSegmentationMixin';\n\nconst { getters } = getModule('segmentation');\n\n/**\n * Override for `freehandSegmentationMixin`'s `renderToolData` method to render a polyline instead\n * of a freehand region with the first and last point connected. Apply after the `freehandSegmentationMixin`.\n *\n * @override\n * @param {Object} evt The cornerstone render event.\n * @returns {null}\n */\nfunction renderToolData(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n const color = getters.brushColor(element, true);\n const context = getNewContext(eventData.canvasContext.canvas);\n const handles = this.handles;\n\n draw(context, context => {\n const isNotTheFirstHandle = handles.points.length > 1;\n\n if (isNotTheFirstHandle) {\n for (let j = 0; j < handles.points.length; j++) {\n const lines = [...handles.points[j].lines];\n\n drawJoinedLines(context, element, this.handles.points[j], lines, {\n color,\n });\n }\n }\n });\n}\n\nconst polylineSegmentationMixin = Object.assign({}, freehandSegmentationMixin, {\n renderToolData,\n});\n\n/**\n * @mixin freehandPolylineRenderOverride - segmentation operations for corrections Polyline\n * @memberof Mixins\n */\nexport default polylineSegmentationMixin;\n","import { draw, drawRect, getNewContext } from '../../drawing';\nimport external from '../../externalModules';\nimport _isEmptyObject from '../../util/isEmptyObject';\nimport { getModule } from '../../store';\nimport { getDiffBetweenPixelData } from '../../util/segmentation';\n\nconst { getters, setters } = getModule('segmentation');\n\n/**\n * Render hook: draws the Scissors's outline, box, or circle\n *\n * @param {Object} evt Cornerstone.event#cornerstoneimagerendered > cornerstoneimagerendered event\n * @memberof Tools.ScissorsTool\n * @returns {void}\n */\nfunction renderToolData(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n const color = getters.brushColor(element, true);\n const context = getNewContext(eventData.canvasContext.canvas);\n\n draw(context, context => {\n drawRect(context, element, this.handles.start, this.handles.end, {\n color,\n });\n });\n}\n\n/**\n * Sets the start handle point and claims the eventDispatcher event\n *\n * @private\n * @param {*} evt // mousedown, touchstart, click\n * @returns {Boolean} True\n */\nfunction _startOutliningRegion(evt) {\n const consumeEvent = true;\n const element = evt.detail.element;\n const image = evt.detail.currentPoints.image;\n\n if (_isEmptyObject(this.handles.start)) {\n this.handles.start = image;\n } else {\n this.handles.end = image;\n this._applyStrategy(evt);\n }\n\n external.cornerstone.updateImage(element);\n\n return consumeEvent;\n}\n\n/**\n * This function will update the handles and updateImage to force re-draw\n *\n * @private\n * @method _setHandlesAndUpdate\n * @param {(CornerstoneTools.event#TOUCH_DRAG|CornerstoneTools.event#MOUSE_DRAG|CornerstoneTools.event#MOUSE_MOVE)} evt Interaction event emitted by an enabledElement\n * @returns {void}\n */\nfunction _setHandlesAndUpdate(evt) {\n const {\n element,\n currentPoints: { image },\n } = evt.detail;\n\n this.handles.end = image;\n external.cornerstone.updateImage(element);\n}\n\n/**\n * Event handler for MOUSE_UP/TOUCH_END during handle drag event loop.\n *\n * @private\n * @method _applyStrategy\n * @param {(CornerstoneTools.event#MOUSE_UP|CornerstoneTools.event#TOUCH_END)} evt Interaction event emitted by an enabledElement\n * @returns {void}\n */\nfunction _applyStrategy(evt) {\n evt.detail.handles = this.handles;\n\n const { element } = evt.detail;\n\n const { labelmap2D, labelmap3D, currentImageIdIndex } = getters.labelmap2D(\n element\n );\n\n const pixelData = labelmap2D.pixelData;\n const previousPixeldata = pixelData.slice();\n\n const points = [\n {\n x: this.handles.start.x,\n y: this.handles.start.y,\n },\n {\n x: this.handles.end.x,\n y: this.handles.end.y,\n },\n ];\n\n const operationData = {\n points,\n pixelData,\n segmentIndex: labelmap3D.activeSegmentIndex,\n segmentationMixinType: `rectangleSegmentationMixin`,\n };\n\n this.applyActiveStrategy(evt, operationData);\n\n const operation = {\n imageIdIndex: currentImageIdIndex,\n diff: getDiffBetweenPixelData(previousPixeldata, pixelData),\n };\n\n setters.pushState(this.element, [operation]);\n\n // Invalidate the brush tool data so it is redrawn\n setters.updateSegmentsOnLabelmap2D(labelmap2D);\n external.cornerstone.updateImage(element);\n\n this._resetHandles();\n}\n\n/**\n * Sets the start and end handle points to empty objects\n *\n * @private\n * @method _resetHandles\n * @returns {void}\n */\nfunction _resetHandles() {\n this.handles = {\n start: {},\n end: {},\n };\n}\n\n/**\n * @mixin rectangleSegmentationMixin - segmentation operations for rectangles\n * @memberof Mixins\n */\nexport default {\n postTouchStartCallback: _startOutliningRegion,\n postMouseDownCallback: _startOutliningRegion,\n mouseClickCallback: _startOutliningRegion,\n touchDragCallback: _setHandlesAndUpdate,\n mouseDragCallback: _setHandlesAndUpdate,\n mouseMoveCallback: _setHandlesAndUpdate,\n touchEndCallback: _applyStrategy,\n mouseUpCallback: _applyStrategy,\n initializeMixin: _resetHandles,\n renderToolData,\n _resetHandles,\n _applyStrategy,\n};\n","import external from './../../externalModules.js';\nimport store, { getModule } from './../../store/index.js';\n\n/**\n * Called by the event dispatcher to render the image.\n *\n * @param {Object} evt - The event.\n * @returns {void}\n */\nfunction renderBrush(evt) {\n const { cornerstone } = external;\n const { getters, configuration } = getModule('segmentation');\n const eventData = evt.detail;\n const viewport = eventData.viewport;\n\n let mousePosition;\n\n if (this._drawing) {\n mousePosition = this._lastImageCoords;\n } else if (this._mouseUpRender) {\n mousePosition = this._lastImageCoords;\n this._mouseUpRender = false;\n } else {\n mousePosition = store.state.mousePositionImage;\n }\n\n if (!mousePosition) {\n return;\n }\n\n const { rows, columns } = eventData.image;\n const { x, y } = mousePosition;\n\n if (x < 0 || x > columns || y < 0 || y > rows) {\n return;\n }\n\n // Draw the hover overlay on top of the pixel data\n const radius = configuration.radius;\n const context = eventData.canvasContext;\n const element = eventData.element;\n const color = getters.brushColor(element, this._drawing);\n\n context.setTransform(1, 0, 0, 1, 0, 0);\n\n const circleRadius = radius * viewport.scale;\n const mouseCoordsCanvas = cornerstone.pixelToCanvas(element, mousePosition);\n\n context.beginPath();\n context.strokeStyle = color;\n context.ellipse(\n mouseCoordsCanvas.x,\n mouseCoordsCanvas.y,\n circleRadius,\n circleRadius,\n 0,\n 0,\n 2 * Math.PI\n );\n context.stroke();\n}\n\nexport default {\n renderBrush,\n};\n","import activeOrDisabledBinaryTool from './activeOrDisabledBinaryTool.js';\nimport enabledOrDisabledBinaryTool from './enabledOrDisabledBinaryTool.js';\nimport circleSegmentationMixin from './segmentation/circleSegmentationMixin.js';\nimport polylineSegmentationMixin from './segmentation/polylineSegmentationMixin.js';\nimport freehandSegmentationMixin from './segmentation/freehandSegmentationMixin.js';\nimport rectangleSegmentationMixin from './segmentation/rectangleSegmentationMixin.js';\nimport renderBrushMixin from './segmentation/renderBrushMixin.js';\n\nexport default {\n activeOrDisabledBinaryTool,\n enabledOrDisabledBinaryTool,\n circleSegmentationMixin,\n polylineSegmentationMixin,\n freehandSegmentationMixin,\n rectangleSegmentationMixin,\n renderBrushMixin,\n};\n","const isMergeableObject = val => {\n const nonNullObject = val && typeof val === 'object';\n\n return (\n nonNullObject &&\n Object.prototype.toString.call(val) !== '[object RegExp]' &&\n Object.prototype.toString.call(val) !== '[object Date]'\n );\n};\n\nconst emptyTarget = val => {\n const isEmpty = Array.isArray(val) ? [] : {};\n\n return isEmpty;\n};\n\nconst cloneIfNecessary = (value, optionsArgument) => {\n const clone = optionsArgument && optionsArgument.clone === true;\n\n return clone && isMergeableObject(value)\n ? deepmerge(emptyTarget(value), value, optionsArgument)\n : value;\n};\n\nconst defaultArrayMerge = (target, source, optionsArgument) => {\n const destination = target.slice();\n\n source.forEach(function(e, i) {\n if (typeof destination[i] === 'undefined') {\n destination[i] = cloneIfNecessary(e, optionsArgument);\n } else if (isMergeableObject(e)) {\n destination[i] = deepmerge(target[i], e, optionsArgument);\n } else if (target.indexOf(e) === -1) {\n destination.push(cloneIfNecessary(e, optionsArgument));\n }\n });\n\n return destination;\n};\n\nconst mergeObject = (target, source, optionsArgument) => {\n const destination = {};\n\n if (isMergeableObject(target)) {\n Object.keys(target).forEach(function(key) {\n destination[key] = cloneIfNecessary(target[key], optionsArgument);\n });\n }\n Object.keys(source).forEach(function(key) {\n if (!isMergeableObject(source[key]) || !target[key]) {\n destination[key] = cloneIfNecessary(source[key], optionsArgument);\n } else {\n destination[key] = deepmerge(target[key], source[key], optionsArgument);\n }\n });\n\n return destination;\n};\n\nconst deepmerge = (target = {}, source = {}, optionsArgument) => {\n const array = Array.isArray(source);\n const options = optionsArgument || { arrayMerge: defaultArrayMerge };\n const arrayMerge = options.arrayMerge || defaultArrayMerge;\n\n if (array) {\n return Array.isArray(target)\n ? arrayMerge(target, source, optionsArgument)\n : cloneIfNecessary(source, optionsArgument);\n }\n\n return mergeObject(target, source, optionsArgument);\n};\n\nexport default deepmerge;\n","import mixins from './../../mixins/index.js';\nimport { getLogger } from '../../util/logger.js';\nimport deepmerge from './../../util/deepmerge.js';\nimport { setToolCursor } from '../../store/setToolCursor.js';\nimport { getModule } from '../../store';\n\nconst logger = getLogger('tools:base:BaseTool');\n\nconst globalConfigurationModule = getModule('globalConfiguration');\n\n/**\n * @typedef ToolConfiguration\n * @param {String} name\n * @param {object} strategies - Named strategy functions\n * @param {String} defaultStrategy - The name of the strategy to use by default\n * @param {Object} configuration\n * @param {String[]} mixins - A list of mixin names to apply to the tool\n */\n\n/**\n * @memberof Tools.Base\n * @classdesc BaseTool Class description\n * @property {String[]} supportedInteractionTypes - A string list of ways the tool can interact with the user\n */\nclass BaseTool {\n /**\n * Constructor description\n * @param {props} [props={}] Tool properties set on instantiation of a tool\n * @param {defaultProps} [defaultProps={}] Tools Default properties\n */\n constructor(props, defaultProps) {\n /**\n * Merge default props with custom props\n */\n this.initialConfiguration = deepmerge(defaultProps, props);\n\n const {\n name,\n strategies,\n defaultStrategy,\n configuration,\n supportedInteractionTypes,\n mixins,\n svgCursor,\n } = this.initialConfiguration;\n\n /**\n * A unique, identifying tool name\n * @type {String}\n */\n this.name = name;\n\n /** @type {String} */\n this.mode = 'disabled';\n this.element = undefined;\n this.supportedInteractionTypes = supportedInteractionTypes || [];\n\n this.strategies = strategies || {};\n this.defaultStrategy =\n defaultStrategy || Object.keys(this.strategies)[0] || undefined;\n this.activeStrategy = this.defaultStrategy;\n\n if (svgCursor) {\n this.svgCursor = svgCursor;\n }\n\n // Options are set when a tool is added, during a \"mode\" change,\n // or via a tool's option's setter\n this._options = {};\n\n // Configuration is set at tool initalization\n this._configuration = Object.assign({}, configuration);\n\n // `updateOnMouseMove` causes the frame to render on every mouse move when\n // the tool is active. This is useful for tools that render large/dynamic\n // items to the canvas which can't easily be respresented with an SVG Cursor.\n this.updateOnMouseMove = false;\n this.hideDefaultCursor = false;\n\n // Apply mixins if mixinsArray is not empty.\n if (mixins && mixins.length) {\n this._applyMixins(mixins);\n }\n\n this._cursors = Object.assign({}, this.initialConfiguration.cursors);\n\n const defaultCursor =\n this.defaultStrategy && this._cursors[this.activeStrategy];\n\n if (defaultCursor) {\n this.svgCursor = defaultCursor;\n }\n }\n\n //\n // CONFIGURATION\n //\n\n /**\n * Config...\n * @public\n * @type {Object}\n * @instance\n */\n static get configuration() {}\n\n get configuration() {\n return this._configuration;\n }\n\n set configuration(configuration) {\n this._configuration = configuration;\n }\n\n //\n // OPTIONS\n //\n\n /**\n * Options...\n * @readonly\n * @instance\n */\n get options() {\n return this._options;\n }\n\n /**\n * Merges provided options with existing options.\n *\n * @public\n * @instance\n * @param {Object} options - options object to merge with existing options.\n * @returns {undefined}\n */\n mergeOptions(options) {\n this._options = Object.assign({}, this._options, options);\n }\n\n /**\n * Clears the tools options.\n *\n * @public\n * @instance\n * @memberof Tools.Base.BaseTool\n * @returns {undefined}\n */\n clearOptions() {\n this._options = {};\n }\n\n /**\n * Apply the currently set/active strategy.\n *\n * @public\n * @instance\n * @method applyActiveStrategy\n * @memberof Tools.Base.BaseTool\n *\n * @param {Object} evt The event that triggered the strategies application\n * @param {Object} operationData - An object containing extra data not present in the `evt`,\n * required to apply the strategy.\n * @returns {*} strategies vary widely; check each specific strategy to find expected return value\n */\n applyActiveStrategy(evt, operationData) {\n return this.strategies[this.activeStrategy].call(this, evt, operationData);\n }\n\n /**\n * Iterates over registered mixins; any matching names in the provided `mixinsArray` will\n * be merged with this instance.\n *\n * @private\n * @method _applyMixins\n * @param {string[]} mixinsArray An array of mixin identifiers (strings).\n * @returns {undefined}\n */\n _applyMixins(mixinsArray) {\n for (let i = 0; i < mixinsArray.length; i++) {\n const mixin = mixins[`${mixinsArray[i]}`];\n\n if (typeof mixin === 'object') {\n Object.assign(this, mixin);\n\n if (typeof this.initializeMixin === 'function') {\n // Run the mixin's initialisation process.\n this.initializeMixin();\n }\n } else {\n logger.warn(`${this.name}: mixin ${mixins[i]} does not exist.`);\n }\n }\n\n // Don't keep initialiseMixin from last mixin.\n if (this.initializeMixin === 'function') {\n delete this.initializeMixin;\n }\n }\n\n /**\n * Change the active strategy.\n *\n * @public\n * @method setActiveStrategy\n * @param {string} strategy\n * @returns {null}\n */\n setActiveStrategy(strategy) {\n this.activeStrategy = strategy;\n\n if (globalConfigurationModule.configuration.showSVGCursors) {\n this.changeCursor(this.element, strategy);\n }\n }\n\n /**\n * Function responsible for changing the Cursor, according to the strategy.\n * @param {HTMLElement} element\n * @param {string} strategy The strategy to be used on Tool\n * @public\n * @returns {void}\n */\n changeCursor(element, strategy) {\n // Necessary to avoid setToolCursor call without elements, which throws an error.\n if (!element) {\n return;\n }\n\n // If there are cursors set per strategy, change the cursor.\n const cursor = this._cursors[strategy];\n\n if (cursor) {\n this.svgCursor = cursor;\n\n if (this.mode === 'active') {\n setToolCursor(element, cursor);\n // External.cornerstone.updateImage(element);\n }\n }\n }\n\n // ===================================================================\n // Virtual Methods - Have default behavior but may be overridden.\n // ===================================================================\n\n //\n // MOUSE\n //\n\n /**\n * Callback that takes priority if the tool is active, before `MOUSE_DOWN`\n * events are processed. Does nothing by default.\n *\n * @callback BaseTool~preMouseDownCallback\n * @param {CornerstoneTools.event:cornerstonetoolsmousedown} evt\n * @returns {boolean} consumedEvent - True if function consumed the event.\n */\n /**\n * Callback that takes priority if the tool is active, after `MOUSE_DOWN`\n * events are processed. Does nothing by default.\n *\n * @callback BaseTool~postMouseDownCallback\n * @param {CornerstoneTools.event:cornerstonetoolsmousedown} evt\n * @returns {boolean} consumedEvent - True if function consumed the event.\n */\n\n /**\n * Callback that is called if the tool is active, after `MOUSE_DOWN`\n * events are processed. Does nothing by default.\n *\n * @virtual\n * @param {type} evt\n * @returns {boolean} consumedEvent - True if function consumed the event.\n */\n /**\n * Example implementation:\n *\n * postMouseDownCallback(evt) {\n * return false;\n * }\n */\n\n /**\n * Callback that takes priority if the tool is active, before `TOUCH_START`\n * events are processed. Does nothing by default.\n *\n * @virtual\n * @param {type} evt\n * @returns {boolean} consumedEvent - True if function consumed the event.\n */\n /**\n * Example implementation:\n *\n * preTouchStartCallback(evt) {\n * return false;\n * }\n */\n\n /**\n * Callback that is called if the tool is active, after `TOUCH_START`\n * events are processed. Does nothing by default.\n *\n * @virtual\n * @param {type} evt\n * @returns {boolean} consumedEvent - True if function consumed the event.\n */\n /**\n * Example implementation:\n *\n * postTouchStartCallback(evt) {\n * return false;\n * }\n */\n}\n\nexport default BaseTool;\n","import external from '../externalModules.js';\n\n/**\n * Returns true if a point is enclosed within a bounding box.\n * @export @public @method\n * @name pointInsideBoundingBox\n *\n * @param {Object} handle The handle containing the boundingBox.\n * @param {Object} coords The coordinate to check.\n * @returns {boolean} True if the point is enclosed within the bounding box.\n */\nexport default function(handle, coords) {\n if (!handle.boundingBox) {\n return;\n }\n\n return external.cornerstoneMath.point.insideRect(coords, handle.boundingBox);\n}\n","import external from '../externalModules.js';\nimport pointInsideBoundingBox from '../util/pointInsideBoundingBox.js';\n\n/**\n * Returns the first handle found to be near the provided point. Handles to search can be an array of handles, an\n * object of named handles, or an object of named handles AND named arrays of handles.\n *\n * @public\n * @function getHandleNearImagePoint\n * @memberof Manipulators\n *\n * @param {*} element - Target enabledElement\n * @param {(Array|Object)} handles - An arry of handles, object with named handles, or object with named handles AND named arrays of handles\n * @param {Object} coords - The coordinates to measure from when determining distance from handles\n * @param {number} distanceThreshold - minimum distance handle needs to be from provided coords\n * @returns {Object} Handle\n */\nconst getHandleNearImagePoint = function(\n element,\n handles,\n coords,\n distanceThreshold\n) {\n let nearbyHandle;\n\n if (!handles) {\n return;\n }\n\n if (Array.isArray(handles)) {\n const handleKeys = Object.keys(handles);\n\n for (let i = 0; i < handleKeys.length; i++) {\n const key = handleKeys[i];\n const handle = handles[key];\n\n if (\n // Not a true handle\n !handle.hasOwnProperty('x') ||\n !handle.hasOwnProperty('y')\n ) {\n continue;\n }\n\n if (_isHandleNearImagePoint(handle, element, coords, distanceThreshold)) {\n nearbyHandle = handle;\n break;\n }\n }\n } else if (typeof handles === 'object') {\n const handleKeys = Object.keys(handles);\n\n for (let i = 0; i < handleKeys.length; i++) {\n const handleName = handleKeys[i];\n\n if (Array.isArray(handles[handleName])) {\n nearbyHandle = getHandleNearImagePoint(\n element,\n handles[handleName],\n coords,\n distanceThreshold\n );\n if (nearbyHandle) {\n break;\n }\n } else {\n const handle = handles[handleName];\n\n if (\n _isHandleNearImagePoint(handle, element, coords, distanceThreshold)\n ) {\n nearbyHandle = handle;\n break;\n }\n }\n }\n }\n\n return nearbyHandle;\n};\n\n/**\n * Determines if the handle is less than the provided distance from the provided coordinates\n * @private\n * @function _isHandleNearImagePoint\n *\n * @param {*} handle\n * @param {*} element\n * @param {*} coords\n * @param {*} distanceThreshold\n * @returns {boolean} true if handles is near image point\n */\nconst _isHandleNearImagePoint = function(\n handle,\n element,\n coords,\n distanceThreshold\n) {\n if (handle.hasOwnProperty('pointNearHandle')) {\n if (handle.pointNearHandle(element, handle, coords)) {\n return true;\n }\n } else if (handle.hasBoundingBox === true) {\n if (pointInsideBoundingBox(handle, coords)) {\n return true;\n }\n } else {\n const handleCanvas = external.cornerstone.pixelToCanvas(element, handle);\n const distance = external.cornerstoneMath.point.distance(\n handleCanvas,\n coords\n );\n\n if (distance <= distanceThreshold) {\n return true;\n }\n }\n\n return false;\n};\n\nexport default getHandleNearImagePoint;\n","import getHandleNearImagePoint from './getHandleNearImagePoint.js';\n\n/**\n * Update the active handle\n * @public\n * @function handleActivator\n * @memberof Manipulators\n *\n * @param {*} element\n * @param {*} handles\n * @param {*} canvasPoint\n * @param {*} distanceThreshold\n * @returns {Boolean} - True if a handle was activated\n */\nexport default function(element, handles, canvasPoint, distanceThreshold) {\n if (!distanceThreshold) {\n distanceThreshold = 6;\n }\n\n const activeHandle = _getActiveHandle(handles);\n const nearbyHandle = getHandleNearImagePoint(\n element,\n handles,\n canvasPoint,\n distanceThreshold\n );\n\n if (activeHandle !== nearbyHandle) {\n if (nearbyHandle !== undefined) {\n nearbyHandle.active = true;\n }\n\n if (activeHandle !== undefined) {\n activeHandle.active = false;\n }\n\n return true;\n }\n\n return false;\n}\n\n/**\n *\n * @private\n *\n * @param {*} handles\n * @returns {Object} - Activated Handle\n */\nfunction _getActiveHandle(handles) {\n let activeHandle;\n\n Object.keys(handles).forEach(function(name) {\n const handle = handles[name];\n\n if (handle.active === true) {\n activeHandle = handle;\n\n return;\n }\n });\n\n return activeHandle;\n}\n","import external from '../externalModules.js';\n\n/**\n * Determine if a handle is outside the bounds of the rendered image.\n * @public\n * @function anyHandlesOutsideImage\n * @memberof Manipulators\n *\n * @param {*} renderData - Cornerstone Tool's event detail\n * @param {Object} handles - An object containing named handles\n * @returns {Boolean} - True if the handle was placed outside the image\n */\nexport default function(renderData, handles) {\n const image = renderData.image;\n const imageRect = {\n left: 0,\n top: 0,\n width: image.width,\n height: image.height,\n };\n\n let handleOutsideImage = false;\n\n Object.keys(handles).forEach(function(name) {\n const handle = handles[name];\n\n if (handle.allowedOutsideImage === true) {\n return;\n }\n\n if (\n external.cornerstoneMath.point.insideRect(handle, imageRect) === false\n ) {\n handleOutsideImage = true;\n }\n });\n\n return handleOutsideImage;\n}\n","/**\n * Clips a value to an upper and lower bound.\n * @export @public @method\n * @name clip\n *\n * @param {number} val The value to clip.\n * @param {number} low The lower bound.\n * @param {number} high The upper bound.\n * @returns {number} The clipped value.\n */\nexport function clip(val, low, high) {\n return Math.min(Math.max(low, val), high);\n}\n\n/**\n * Clips a value within a box.\n * @export @public @method\n * @name clipToBox\n *\n * @param {Object} point The point to clip\n * @param {Object} box The bounding box to clip to.\n * @returns {Object} The clipped point.\n */\nexport function clipToBox(point, box) {\n // Clip an {x, y} point to a box of size {width, height}\n point.x = clip(point.x, 0, box.width);\n point.y = clip(point.y, 0, box.height);\n}\n\nexport default clip;\n","/**\n * Filters an array of tools, returning only tools which are active.\n * @export\n * @public\n * @method\n * @name getActiveToolsForElement\n *\n * @param {HTMLElement} element The element.\n * @param {Object[]} tools The input tool array.\n * @param {string} handlerType The input type being queried.\n * @returns {Object[]} The filtered array.\n */\nexport default function(element, tools, handlerType) {\n return tools.filter(\n tool =>\n tool.element === element &&\n tool.mode === 'active' &&\n (handlerType === undefined || tool.options[`is${handlerType}Active`])\n );\n}\n","import getToolForElement from './getToolForElement.js';\n\n/**\n * Queries if a tool is active on the specified element.\n * @export\n * @public\n * @method\n * @name isToolActiveForElement\n *\n * @param {HTMLElement} element The element being queried.\n * @param {string} name The name of the tool.\n * @returns {boolean} True if the tool is active.\n */\nexport default function(element, name) {\n const tool = getToolForElement(element, name);\n\n return tool.mode === 'active';\n}\n","import BaseTool from './BaseTool.js';\nimport EVENTS from './../../events.js';\nimport external from './../../externalModules.js';\nimport isToolActiveForElement from './../../store/isToolActiveForElement.js';\nimport { getModule } from './../../store/index.js';\nimport {\n getDiffBetweenPixelData,\n triggerLabelmapModifiedEvent,\n} from '../../util/segmentation';\n\nconst segmentationModule = getModule('segmentation');\n\n/**\n * @abstract\n * @memberof Tools.Base\n * @classdesc Abstract class for tools which manipulate the mask data to be displayed on\n * the cornerstone canvas.\n * @extends Tools.Base.BaseTool\n */\nclass BaseBrushTool extends BaseTool {\n constructor(props, defaultProps = {}) {\n if (!defaultProps.configuration) {\n defaultProps.configuration = { alwaysEraseOnClick: false };\n }\n\n super(props, defaultProps);\n\n this.updateOnMouseMove = true;\n this.hideDefaultCursor = true;\n\n this._drawing = false;\n this._drawingMouseUpCallback = this._drawingMouseUpCallback.bind(this);\n }\n\n // ===================================================================\n // Abstract Methods - Must be implemented.\n // ===================================================================\n\n /**\n * Helper function for rendering the brush.\n *\n * @abstract\n * @param {Object} evt - The event.\n * @returns {void}\n */\n // eslint-disable-next-line no-unused-vars\n renderBrush(evt) {\n throw new Error(`Method renderBrush not implemented for ${this.name}.`);\n }\n\n /**\n * Paints the data to the labelmap.\n *\n * @protected\n * @abstract\n * @param {Object} evt The event.\n * @returns {void}\n */\n // eslint-disable-next-line no-unused-vars\n _paint(evt) {\n throw new Error(`Method _paint not implemented for ${this.name}.`);\n }\n\n // ===================================================================\n // Virtual Methods - Have default behavior but may be overriden.\n // ===================================================================\n\n /**\n * Event handler for MOUSE_DRAG event.\n *\n * @override\n * @abstract\n * @event\n * @param {Object} evt - The event.\n */\n mouseDragCallback(evt) {\n const { currentPoints } = evt.detail;\n\n this._lastImageCoords = currentPoints.image;\n\n // Safety measure incase _startPainting is overridden and doesn't always\n // start a paint.\n if (this._drawing) {\n this._paint(evt);\n }\n }\n\n /**\n * Event handler for MOUSE_DOWN event.\n *\n * @override\n * @abstract\n * @event\n * @param {Object} evt - The event.\n */\n preMouseDownCallback(evt) {\n const eventData = evt.detail;\n const { element, currentPoints } = eventData;\n\n this._startPainting(evt);\n\n this._lastImageCoords = currentPoints.image;\n this._drawing = true;\n this._startListeningForMouseUp(element);\n this._paint(evt);\n\n return true;\n }\n\n /**\n * Initialise painting with BaseBrushTool.\n *\n * @abstract\n * @event\n * @param {Object} evt - The event.\n * @returns {void}\n */\n _startPainting(evt) {\n const eventData = evt.detail;\n const element = eventData.element;\n const { configuration, getters } = segmentationModule;\n\n const {\n labelmap2D,\n labelmap3D,\n currentImageIdIndex,\n activeLabelmapIndex,\n } = getters.labelmap2D(element);\n\n const shouldErase =\n this._isCtrlDown(eventData) || this.configuration.alwaysEraseOnClick;\n\n this.paintEventData = {\n labelmap2D,\n labelmap3D,\n currentImageIdIndex,\n activeLabelmapIndex,\n shouldErase,\n };\n\n if (configuration.storeHistory) {\n const previousPixelData = labelmap2D.pixelData.slice();\n\n this.paintEventData.previousPixelData = previousPixelData;\n }\n }\n\n /**\n * End painting with BaseBrushTool.\n *\n * @abstract\n * @event\n * @param {Object} evt - The event.\n * @returns {void}\n */\n _endPainting(evt) {\n const { configuration, setters } = segmentationModule;\n const { labelmap2D, currentImageIdIndex } = this.paintEventData;\n\n // Grab the labels on the slice.\n const segmentSet = new Set(labelmap2D.pixelData);\n const iterator = segmentSet.values();\n\n const segmentsOnLabelmap = [];\n let done = false;\n\n while (!done) {\n const next = iterator.next();\n\n done = next.done;\n\n if (!done) {\n segmentsOnLabelmap.push(next.value);\n }\n }\n\n labelmap2D.segmentsOnLabelmap = segmentsOnLabelmap;\n\n if (configuration.storeHistory) {\n const { previousPixelData } = this.paintEventData;\n const newPixelData = labelmap2D.pixelData;\n const operation = {\n imageIdIndex: currentImageIdIndex,\n diff: getDiffBetweenPixelData(previousPixelData, newPixelData),\n };\n\n setters.pushState(this.element, [operation]);\n }\n\n triggerLabelmapModifiedEvent(this.element);\n }\n\n // ===================================================================\n // Implementation interface\n // ===================================================================\n\n /**\n * Event handler for MOUSE_MOVE event.\n *\n * @override\n * @abstract\n * @event\n * @param {Object} evt - The event.\n */\n mouseMoveCallback(evt) {\n const { currentPoints } = evt.detail;\n\n this._lastImageCoords = currentPoints.image;\n }\n\n /**\n * Used to redraw the tool's cursor per render.\n *\n * @override\n * @param {Object} evt - The event.\n */\n renderToolData(evt) {\n const eventData = evt.detail;\n const element = eventData.element;\n\n // Only brush needs to render.\n if (isToolActiveForElement(element, this.name)) {\n // Call the hover event for the brush\n this.renderBrush(evt);\n }\n }\n\n /**\n * Event handler for switching mode to passive.\n *\n * @override\n * @event\n * @param {Object} evt - The event.\n */\n // eslint-disable-next-line no-unused-vars\n passiveCallback(evt) {\n try {\n external.cornerstone.updateImage(this.element);\n } catch (error) {\n // It is possible that the image has not been loaded\n // when this is called.\n return;\n }\n }\n\n /**\n * Event handler for MOUSE_UP during the drawing event loop.\n *\n * @protected\n * @event\n * @param {Object} evt - The event.\n * @returns {void}\n */\n _drawingMouseUpCallback(evt) {\n const eventData = evt.detail;\n const element = eventData.element;\n\n this._endPainting(evt);\n\n this._drawing = false;\n this._mouseUpRender = true;\n this._stopListeningForMouseUp(element);\n }\n\n newImageCallback(evt) {\n if (this._drawing) {\n // End painting on one slice and start on another.\n this._endPainting(evt);\n this._startPainting(evt);\n }\n }\n\n /**\n * Adds modify loop event listeners.\n *\n * @protected\n * @param {Object} element - The viewport element to add event listeners to.\n * @modifies {element}\n * @returns {void}\n */\n _startListeningForMouseUp(element) {\n element.removeEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);\n element.removeEventListener(\n EVENTS.MOUSE_CLICK,\n this._drawingMouseUpCallback\n );\n\n element.addEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);\n element.addEventListener(EVENTS.MOUSE_CLICK, this._drawingMouseUpCallback);\n\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Adds modify loop event listeners.\n *\n * @protected\n * @param {Object} element - The viewport element to add event listeners to.\n * @modifies {element}\n * @returns {void}\n */\n _stopListeningForMouseUp(element) {\n element.removeEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);\n element.removeEventListener(\n EVENTS.MOUSE_CLICK,\n this._drawingMouseUpCallback\n );\n\n external.cornerstone.updateImage(element);\n }\n\n // ===================================================================\n // Brush API. This is effectively a wrapper around the store.\n // ===================================================================\n\n /**\n * Increases the brush size\n *\n * @public\n * @api\n * @returns {void}\n */\n increaseBrushSize() {\n const { configuration, setters } = segmentationModule;\n const oldRadius = configuration.radius;\n let newRadius = Math.floor(oldRadius * 1.2);\n\n // If e.g. only 2 pixels big. Math.floor(2*1.2) = 2.\n // Hence, have minimum increment of 1 pixel.\n if (newRadius === oldRadius) {\n newRadius += 1;\n }\n\n setters.radius(newRadius);\n }\n\n /**\n * Decreases the brush size\n *\n * @public\n * @api\n * @returns {void}\n */\n decreaseBrushSize() {\n const { configuration, setters } = segmentationModule;\n const oldRadius = configuration.radius;\n const newRadius = Math.floor(oldRadius * 0.8);\n\n setters.radius(newRadius);\n }\n\n _isCtrlDown(eventData) {\n return (eventData.event && eventData.event.ctrlKey) || eventData.ctrlKey;\n }\n}\n\nexport default BaseBrushTool;\n","import BaseAnnotationTool from '../tools/base/BaseAnnotationTool.js';\nimport BaseBrushTool from '../tools/base/BaseBrushTool.js';\n\n/**\n * Filters an array of tools, returning only tools which are active or passive.\n * @export\n * @public\n * @method\n * @name filterToolsUseableWithMultiPartTools\n *\n * @param {Object[]} tools The input tool array.\n * @returns {Object[]} The filtered array.\n */\nexport default function(tools) {\n return tools.filter(\n tool =>\n !tool.isMultiPartTool &&\n !(tool instanceof BaseAnnotationTool) &&\n !(tool instanceof BaseBrushTool)\n );\n}\n","import { getters, state } from '../store';\nimport getActiveToolsForElement from '../store/getActiveToolsForElement';\nimport filterToolsUseableWithMultiPartTools from '../store/filterToolsUsableWithMultiPartTools';\n\n// Todo: We could simplify this if we only allow one active\n// Tool per mouse button mask?\nexport default function getActiveTool(\n element,\n buttons,\n interactionType = 'mouse'\n) {\n let tools;\n\n if (interactionType === 'touch') {\n tools = getActiveToolsForElement(element, getters.touchTools());\n tools = tools.filter(tool => tool.options.isTouchActive);\n } else {\n // Filter out disabled, enabled, and passive\n tools = getActiveToolsForElement(element, getters.mouseTools());\n\n // Filter out tools that do not match mouseButtonMask\n tools = tools.filter(\n tool =>\n Array.isArray(tool.options.mouseButtonMask) &&\n buttons &&\n tool.options.mouseButtonMask.includes(buttons) &&\n tool.options.isMouseActive\n );\n\n if (state.isMultiPartToolActive) {\n tools = filterToolsUseableWithMultiPartTools(tools);\n }\n }\n\n if (tools.length === 0) {\n return;\n }\n\n return tools[0];\n}\n","import EVENTS from '../events.js';\nimport external from '../externalModules.js';\nimport anyHandlesOutsideImage from './anyHandlesOutsideImage.js';\nimport { removeToolState } from '../stateManagement/toolState.js';\nimport triggerEvent from '../util/triggerEvent.js';\nimport { clipToBox } from '../util/clip.js';\nimport { state } from './../store/index.js';\nimport getActiveTool from '../util/getActiveTool';\nimport BaseAnnotationTool from '../tools/base/BaseAnnotationTool';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('manipulators:moveAllHandles');\n\nconst _dragEvents = {\n mouse: [EVENTS.MOUSE_DRAG],\n touch: [EVENTS.TOUCH_DRAG],\n};\n\nconst _upOrEndEvents = {\n mouse: [EVENTS.MOUSE_UP, EVENTS.MOUSE_CLICK],\n touch: [\n EVENTS.TOUCH_END,\n EVENTS.TOUCH_DRAG_END,\n EVENTS.TOUCH_PINCH,\n EVENTS.TOUCH_PRESS,\n EVENTS.TAP,\n ],\n};\n\n/**\n * Manipulator to move all provided handles at the same time\n * @public\n * @function moveAllHandles\n * @memberof Manipulators\n *\n * @param {*} evtDetail\n * @param {*} evtDetail.element\n * @param {String} toolName\n * @param {*} annotation\n * @param {*} [handle=null] - not needed by moveAllHandles, but keeps call signature the same as `moveHandle`\n * @param {Object} [options={}]\n * @param {Boolean} [options.deleteIfHandleOutsideImage]\n * @param {Boolean} [options.preventHandleOutsideImage]\n * @param {string} [interactionType=mouse]\n * @param {function} [doneMovingCallback]\n * @returns {undefined}\n */\nexport default function(\n { element },\n toolName,\n annotation,\n handle,\n options = {},\n interactionType = 'mouse',\n doneMovingCallback\n) {\n // Use global defaults, unless overidden by provided options\n options = Object.assign(\n {\n deleteIfHandleOutsideImage: state.deleteIfHandleOutsideImage,\n preventHandleOutsideImage: state.preventHandleOutsideImage,\n },\n options\n );\n\n const dragHandler = _dragHandler.bind(\n this,\n toolName,\n annotation,\n options,\n interactionType\n );\n // So we don't need to inline the entire `upOrEndHandler` function\n const upOrEndHandler = evt => {\n _upOrEndHandler(\n toolName,\n annotation,\n options,\n interactionType,\n {\n dragHandler,\n upOrEndHandler,\n },\n evt,\n doneMovingCallback\n );\n };\n\n annotation.active = true;\n state.isToolLocked = true;\n\n // Add Event Listeners\n _dragEvents[interactionType].forEach(eventType => {\n element.addEventListener(eventType, dragHandler);\n });\n _upOrEndEvents[interactionType].forEach(eventType => {\n element.addEventListener(eventType, upOrEndHandler);\n });\n}\n\nfunction _dragHandler(\n toolName,\n annotation,\n options = {},\n interactionType,\n evt\n) {\n const { element, image, buttons } = evt.detail;\n const { x, y } = evt.detail.deltaPoints.image;\n\n annotation.active = true;\n annotation.invalidated = true;\n\n const handleKeys = Object.keys(annotation.handles);\n\n for (let i = 0; i < handleKeys.length; i++) {\n const key = handleKeys[i];\n const handle = annotation.handles[key];\n\n if (\n // Don't move this part of the annotation\n handle.movesIndependently === true ||\n // Not a true handle\n !handle.hasOwnProperty('x') ||\n !handle.hasOwnProperty('y')\n ) {\n continue;\n }\n\n handle.x += x;\n handle.y += y;\n\n if (options.preventHandleOutsideImage) {\n clipToBox(handle, image);\n }\n }\n\n external.cornerstone.updateImage(element);\n\n const activeTool = getActiveTool(element, buttons, interactionType);\n\n if (activeTool instanceof BaseAnnotationTool) {\n activeTool.updateCachedStats(image, element, annotation);\n }\n\n const eventType = EVENTS.MEASUREMENT_MODIFIED;\n const modifiedEventData = {\n toolName,\n element,\n measurementData: annotation,\n };\n\n triggerEvent(element, eventType, modifiedEventData);\n\n evt.preventDefault();\n evt.stopPropagation();\n}\n\nfunction _upOrEndHandler(\n toolName,\n annotation,\n options = {},\n interactionType,\n { dragHandler, upOrEndHandler },\n evt,\n doneMovingCallback\n) {\n const eventData = evt.detail;\n const element = evt.detail.element;\n\n annotation.active = false;\n annotation.invalidated = true;\n state.isToolLocked = false;\n\n // Remove Event Listeners\n _dragEvents[interactionType].forEach(eventType => {\n element.removeEventListener(eventType, dragHandler);\n });\n _upOrEndEvents[interactionType].forEach(eventType => {\n element.removeEventListener(eventType, upOrEndHandler);\n });\n\n // If any handle is outside the image, delete the tool data\n if (\n options.deleteIfHandleOutsideImage &&\n anyHandlesOutsideImage(eventData, annotation.handles)\n ) {\n removeToolState(element, toolName, annotation);\n }\n\n if (typeof options.doneMovingCallback === 'function') {\n logger.warn(\n '`options.doneMovingCallback` has been depricated. See https://github.com/cornerstonejs/cornerstoneTools/pull/915 for details.'\n );\n options.doneMovingCallback();\n }\n\n if (typeof doneMovingCallback === 'function') {\n doneMovingCallback();\n }\n\n external.cornerstone.updateImage(element);\n}\n","import EVENTS from '../events.js';\nimport external from '../externalModules.js';\nimport anyHandlesOutsideImage from './anyHandlesOutsideImage.js';\nimport { removeToolState } from '../stateManagement/toolState.js';\nimport triggerEvent from '../util/triggerEvent.js';\nimport { clipToBox } from '../util/clip.js';\nimport { state } from './../store/index.js';\nimport getActiveTool from '../util/getActiveTool';\nimport BaseAnnotationTool from '../tools/base/BaseAnnotationTool';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('manipulators:moveHandle');\n\nconst runAnimation = {\n value: false,\n};\n\nconst _dragEvents = {\n mouse: [EVENTS.MOUSE_DRAG],\n touch: [EVENTS.TOUCH_DRAG],\n};\n\nconst _upOrEndEvents = {\n mouse: [EVENTS.MOUSE_UP, EVENTS.MOUSE_CLICK],\n touch: [\n EVENTS.TOUCH_END,\n EVENTS.TOUCH_DRAG_END,\n EVENTS.TOUCH_PINCH,\n EVENTS.TOUCH_PRESS,\n EVENTS.TAP,\n ],\n};\n\n/**\n * Move the provided handle\n *\n * @public\n * @method moveHandle\n * @memberof Manipulators\n *\n * @param {*} evtDetail\n * @param {*} toolName\n * @param {*} annotation\n * @param {*} handle\n * @param {*} [options={}]\n * @param {Boolean} [options.deleteIfHandleOutsideImage]\n * @param {Boolean} [options.preventHandleOutsideImage]\n * @param {*} [interactionType=mouse]\n * @param {function} doneMovingCallback\n * @returns {undefined}\n */\nexport default function(\n evtDetail,\n toolName,\n annotation,\n handle,\n options = {},\n interactionType = 'mouse',\n doneMovingCallback\n) {\n // Use global defaults, unless overidden by provided options\n options = Object.assign(\n {\n deleteIfHandleOutsideImage: state.deleteIfHandleOutsideImage,\n preventHandleOutsideImage: state.preventHandleOutsideImage,\n },\n options\n );\n\n const element = evtDetail.element;\n const dragHandler = _dragHandler.bind(\n this,\n toolName,\n annotation,\n handle,\n options,\n interactionType\n );\n // So we don't need to inline the entire `upOrEndHandler` function\n const upOrEndHandler = evt => {\n _upOrEndHandler(\n toolName,\n evtDetail,\n annotation,\n handle,\n options,\n interactionType,\n {\n dragHandler,\n upOrEndHandler,\n },\n evt,\n doneMovingCallback\n );\n };\n\n handle.active = true;\n annotation.active = true;\n state.isToolLocked = true;\n\n // Add Event Listeners\n _dragEvents[interactionType].forEach(eventType => {\n element.addEventListener(eventType, dragHandler);\n });\n _upOrEndEvents[interactionType].forEach(eventType => {\n element.addEventListener(eventType, upOrEndHandler);\n });\n\n // ==========================\n // ======== TOUCH ==========\n // ==========================\n if (interactionType === 'touch') {\n runAnimation.value = true;\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n // Average pixel width of index finger is 45-57 pixels\n // https://www.smashingmagazine.com/2012/02/finger-friendly-design-ideal-mobile-touchscreen-target-sizes/\n const fingerDistance = -57;\n\n const aboveFinger = {\n x: evtDetail.currentPoints.page.x,\n y: evtDetail.currentPoints.page.y + fingerDistance,\n };\n\n const targetLocation = external.cornerstone.pageToPixel(\n element,\n aboveFinger.x,\n aboveFinger.y\n );\n\n _animate(handle, runAnimation, enabledElement, targetLocation);\n }\n}\n\nfunction _dragHandler(\n toolName,\n annotation,\n handle,\n options,\n interactionType,\n evt\n) {\n const { image, currentPoints, element, buttons } = evt.detail;\n const page = currentPoints.page;\n const fingerOffset = -57;\n const targetLocation = external.cornerstone.pageToPixel(\n element,\n page.x,\n interactionType === 'touch' ? page.y + fingerOffset : page.y\n );\n\n runAnimation.value = false;\n handle.active = true;\n handle.hasMoved = true;\n handle.x = targetLocation.x;\n handle.y = targetLocation.y;\n // TODO: A way to not flip this for textboxes on annotations\n annotation.invalidated = true;\n\n if (options.preventHandleOutsideImage) {\n clipToBox(handle, image);\n }\n\n external.cornerstone.updateImage(element);\n\n const activeTool = getActiveTool(element, buttons, interactionType);\n\n if (activeTool instanceof BaseAnnotationTool) {\n activeTool.updateCachedStats(image, element, annotation);\n }\n\n const eventType = EVENTS.MEASUREMENT_MODIFIED;\n const modifiedEventData = {\n toolName,\n element,\n measurementData: annotation,\n };\n\n triggerEvent(element, eventType, modifiedEventData);\n}\n\nfunction _upOrEndHandler(\n toolName,\n evtDetail,\n annotation,\n handle,\n options = {},\n interactionType,\n { dragHandler, upOrEndHandler },\n evt,\n doneMovingCallback\n) {\n const image = evtDetail.currentPoints.image;\n const element = evt.detail.element;\n\n handle.active = false;\n annotation.active = false;\n // TODO: A way to not flip this for textboxes on annotations\n annotation.invalidated = true;\n state.isToolLocked = false;\n runAnimation.value = false;\n\n // Remove Event Listeners\n _dragEvents[interactionType].forEach(eventType => {\n element.removeEventListener(eventType, dragHandler);\n });\n _upOrEndEvents[interactionType].forEach(eventType => {\n element.removeEventListener(eventType, upOrEndHandler);\n });\n\n // If any handle is outside the image, delete the tool data\n if (\n options.deleteIfHandleOutsideImage &&\n anyHandlesOutsideImage(evtDetail, annotation.handles)\n ) {\n removeToolState(element, toolName, annotation);\n }\n\n // TODO: What dark magic makes us want to handle TOUCH_PRESS differently?\n if (evt.type === EVENTS.TOUCH_PRESS) {\n evt.detail.handlePressed = annotation;\n handle.x = image.x; // Original Event\n handle.y = image.y;\n }\n\n if (typeof options.doneMovingCallback === 'function') {\n logger.warn(\n '`options.doneMovingCallback` has been depricated. See https://github.com/cornerstonejs/cornerstoneTools/pull/915 for details.'\n );\n\n options.doneMovingCallback();\n }\n\n if (typeof doneMovingCallback === 'function') {\n doneMovingCallback();\n }\n\n external.cornerstone.updateImage(element);\n}\n\n/**\n * Animates the provided handle using `requestAnimationFrame`\n * @private\n * @method _animate\n *\n * @param {*} handle\n * @param {*} runAnimation\n * @param {*} enabledElement\n * @param {*} targetLocation\n * @returns {undefined}\n */\nfunction _animate(handle, runAnimation, enabledElement, targetLocation) {\n if (!runAnimation.value) {\n return;\n }\n\n // Pixels / second\n const distanceRemaining = Math.abs(handle.y - targetLocation.y);\n const linearDistEachFrame = distanceRemaining / 10;\n\n if (distanceRemaining < 1) {\n handle.y = targetLocation.y;\n runAnimation.value = false;\n\n return;\n }\n\n if (handle.y > targetLocation.y) {\n handle.y -= linearDistEachFrame;\n } else if (handle.y < targetLocation.y) {\n handle.y += linearDistEachFrame;\n }\n\n // Update the image\n external.cornerstone.updateImage(enabledElement.element);\n\n // Request a new frame\n external.cornerstone.requestAnimationFrame(function() {\n _animate(handle, runAnimation, enabledElement, targetLocation);\n });\n}\n","import EVENTS from '../events.js';\nimport external from '../externalModules.js';\nimport anyHandlesOutsideImage from './anyHandlesOutsideImage.js';\nimport { removeToolState } from '../stateManagement/toolState.js';\nimport triggerEvent from '../util/triggerEvent.js';\nimport { clipToBox } from '../util/clip.js';\nimport { state } from './../store/index.js';\nimport getActiveTool from '../util/getActiveTool';\nimport BaseAnnotationTool from '../tools/base/BaseAnnotationTool';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('manipulators:moveNewHandle');\n\nconst _moveEvents = {\n mouse: [EVENTS.MOUSE_MOVE, EVENTS.MOUSE_DRAG],\n touch: [EVENTS.TOUCH_DRAG],\n};\n\nconst _moveEndEvents = {\n mouse: [EVENTS.MOUSE_UP, EVENTS.MOUSE_CLICK],\n touch: [EVENTS.TOUCH_END, EVENTS.TOUCH_PINCH, EVENTS.TAP],\n};\n\n/**\n * Move a new handle\n * @public\n * @method moveNewHandle\n * @memberof Manipulators\n *\n * @param {*} evtDetail\n * @param {*} toolName\n * @param {*} annotation\n * @param {*} handle\n * @param {*} [options={}]\n * @param {Boolean} [options.deleteIfHandleOutsideImage]\n * @param {Boolean} [options.preventHandleOutsideImage]\n * @param {string} [interactionType=mouse]\n * @param {function} [doneMovingCallback]\n * @returns {void}\n */\nexport default function(\n evtDetail,\n toolName,\n annotation,\n handle,\n options,\n interactionType = 'mouse',\n doneMovingCallback\n) {\n // Use global defaults, unless overidden by provided options\n options = Object.assign(\n {\n deleteIfHandleOutsideImage: state.deleteIfHandleOutsideImage,\n preventHandleOutsideImage: state.preventHandleOutsideImage,\n },\n options\n );\n\n const element = evtDetail.element;\n\n annotation.active = true;\n handle.active = true;\n state.isToolLocked = true;\n\n function moveHandler(evt) {\n _moveHandler(\n toolName,\n annotation,\n handle,\n options,\n interactionType,\n {\n moveHandler,\n moveEndHandler,\n },\n evt\n );\n }\n // So we don't need to inline the entire `moveEndEventHandler` function\n function moveEndHandler(evt) {\n _moveEndHandler(\n toolName,\n annotation,\n handle,\n options,\n interactionType,\n {\n moveHandler,\n moveEndHandler,\n },\n evt,\n doneMovingCallback\n );\n }\n\n // Add event listeners\n _moveEvents[interactionType].forEach(eventType => {\n element.addEventListener(eventType, moveHandler);\n });\n element.addEventListener(EVENTS.TOUCH_START, _stopImmediatePropagation);\n}\n\nfunction _moveHandler(\n toolName,\n annotation,\n handle,\n options,\n interactionType,\n { moveEndHandler },\n evt\n) {\n const { currentPoints, image, element, buttons } = evt.detail;\n // Add moveEndEvent Handler when move trigger\n\n _moveEndEvents[interactionType].forEach(eventType => {\n element.addEventListener(eventType, moveEndHandler);\n });\n const page = currentPoints.page;\n const fingerOffset = -57;\n const targetLocation = external.cornerstone.pageToPixel(\n element,\n interactionType === 'touch' ? page.x + fingerOffset : page.x,\n interactionType === 'touch' ? page.y + fingerOffset : page.y\n );\n\n annotation.invalidated = true;\n handle.active = true;\n handle.x = targetLocation.x;\n handle.y = targetLocation.y;\n\n if (options && options.preventHandleOutsideImage) {\n clipToBox(handle, image);\n }\n\n external.cornerstone.updateImage(element);\n\n const activeTool = getActiveTool(element, buttons, interactionType);\n\n if (activeTool instanceof BaseAnnotationTool) {\n activeTool.updateCachedStats(image, element, annotation);\n }\n\n const eventType = EVENTS.MEASUREMENT_MODIFIED;\n const modifiedEventData = {\n toolName,\n element,\n measurementData: annotation,\n };\n\n triggerEvent(element, eventType, modifiedEventData);\n}\n\nfunction _moveEndHandler(\n toolName,\n annotation,\n handle,\n options,\n interactionType,\n { moveHandler, moveEndHandler },\n evt,\n doneMovingCallback\n) {\n const { element, currentPoints } = evt.detail;\n const page = currentPoints.page;\n const fingerOffset = -57;\n const targetLocation = external.cornerstone.pageToPixel(\n element,\n interactionType === 'touch' ? page.x + fingerOffset : page.x,\n interactionType === 'touch' ? page.y + fingerOffset : page.y\n );\n\n // \"Release\" the handle\n annotation.active = false;\n annotation.invalidated = true;\n handle.active = false;\n handle.x = targetLocation.x;\n handle.y = targetLocation.y;\n state.isToolLocked = false;\n\n // Remove event listeners\n _moveEvents[interactionType].forEach(eventType => {\n element.removeEventListener(eventType, moveHandler);\n });\n _moveEndEvents[interactionType].forEach(eventType => {\n element.removeEventListener(eventType, moveEndHandler);\n });\n element.removeEventListener(EVENTS.TOUCH_START, _stopImmediatePropagation);\n\n // TODO: WHY?\n // Why would a Touch_Pinch or Touch_Press be associated with a new handle?\n if (evt.type === EVENTS.TOUCH_PINCH || evt.type === EVENTS.TOUCH_PRESS) {\n handle.active = false;\n external.cornerstone.updateImage(element);\n if (typeof options.doneMovingCallback === 'function') {\n logger.warn(\n '`options.doneMovingCallback` has been depricated. See https://github.com/cornerstonejs/cornerstoneTools/pull/915 for details.'\n );\n\n options.doneMovingCallback();\n }\n\n if (typeof doneMovingCallback === 'function') {\n doneMovingCallback();\n }\n\n return;\n }\n\n if (options.preventHandleOutsideImage) {\n clipToBox(handle, evt.detail.image);\n }\n\n // If any handle is outside the image, delete the tool data\n if (\n options.deleteIfHandleOutsideImage &&\n anyHandlesOutsideImage(evt.detail, annotation.handles)\n ) {\n removeToolState(element, toolName, annotation);\n }\n\n if (typeof options.doneMovingCallback === 'function') {\n logger.warn(\n '`options.doneMovingCallback` has been depricated. See https://github.com/cornerstonejs/cornerstoneTools/pull/915 for details.'\n );\n\n options.doneMovingCallback();\n }\n\n if (typeof doneMovingCallback === 'function') {\n doneMovingCallback();\n }\n\n // Update Image\n external.cornerstone.updateImage(element);\n}\n\n/**\n * Stop the CornerstoneToolsTouchStart event from\n * Becoming a CornerstoneToolsTouchStartActive event when\n * MoveNewHandle ends\n *\n * @private\n * @function _stopImmediatePropagation\n *\n * @param {*} evt\n * @returns {Boolean} false\n */\nfunction _stopImmediatePropagation(evt) {\n evt.stopImmediatePropagation();\n\n return false;\n}\n","import { state } from '../store/index.js';\nimport getHandleNearImagePoint from '../manipulators/getHandleNearImagePoint.js';\nimport { moveHandle, moveAllHandles } from './../manipulators/index.js';\n\n// TODO this should just be in manipulators? They are just manipulator wrappers anyway.\n\n/**\n * Moves a handle near the image point.\n * @public\n * @function moveHandleNearImagePoint\n * @memberof Util\n *\n * @param {Event} evt The event.\n * @param {*} tool The tool\n * @param {Object} toolData The toolData that corresponds to the handle.\n * @param {Object} handle The handle to be moved.\n * @param {string} interactionType\n * @returns {undefined}\n */\nconst moveHandleNearImagePoint = function(\n evt,\n tool,\n toolData,\n handle,\n interactionType\n) {\n toolData.active = true;\n state.isToolLocked = true;\n\n moveHandle(\n evt.detail,\n tool.name,\n toolData,\n handle,\n tool.options,\n interactionType\n );\n\n evt.stopImmediatePropagation();\n evt.stopPropagation();\n evt.preventDefault();\n\n return;\n};\n\n/**\n * Finds the handle near the image point and its corresponding data.\n *\n * @public\n * @function findHandleDataNearImagePoint\n * @memberof Util\n *\n * @param {HTMLElement} element The elment.\n * @param {Object} toolState The state of the tool.\n * @param {string} toolName The name of the tool the handle corrosponds to.\n * @param {Object} coords The coordinates that need to be checked.\n * @param {String} [interactionType=mouse]\n * @returns {*}\n */\nconst findHandleDataNearImagePoint = function(\n element,\n toolState,\n toolName,\n coords,\n interactionType = 'mouse'\n) {\n for (let i = 0; i < toolState.data.length; i++) {\n const data = toolState.data[i];\n const handle = getHandleNearImagePoint(\n element,\n data.handles,\n coords,\n interactionType === 'mouse' ? state.clickProximity : state.touchProximity\n );\n\n if (handle) {\n return {\n handle,\n data,\n };\n }\n }\n};\n\n/**\n * Moves an entire annotation near the click.\n *\n * @public\n * @function moveAnnotation\n * @memberof Util\n *\n * @param {Event} evt The event.\n * @param {Object} tool The tool that the annotation belongs to.\n * @param {string} tool.name\n * @param {Object} [tool.options={}]\n * @param {Boolean} [tool.options.preventHandleOutsideImage]\n * @param {Boolean} [tool.options.deleteIfHandleOutsideImage]\n * @param {Object} annotation The toolData that corresponds to the annotation.\n * @param {String} [interactionType=mouse]\n * @returns {undefined}\n */\nconst moveAnnotation = function(\n evt,\n tool,\n annotation,\n interactionType = 'mouse'\n) {\n annotation.active = true;\n state.isToolLocked = true;\n\n moveAllHandles(\n evt.detail,\n tool.name,\n annotation,\n null,\n tool.options,\n interactionType,\n () => {\n annotation.active = false;\n state.isToolLocked = false;\n }\n );\n\n evt.stopImmediatePropagation();\n evt.stopPropagation();\n evt.preventDefault();\n\n return;\n};\n\nexport {\n moveHandleNearImagePoint,\n findHandleDataNearImagePoint,\n moveAnnotation,\n};\n","import BaseTool from './BaseTool.js';\nimport { getToolState } from './../../stateManagement/toolState.js';\nimport handleActivator from './../../manipulators/handleActivator.js';\nimport {\n moveHandleNearImagePoint,\n moveAnnotation,\n} from './../../util/findAndMoveHelpers.js';\nimport { getLogger } from '../../util/logger';\n\nconst logger = getLogger('baseAnnotationTool');\n\n/**\n * @memberof Tools.Base\n * @classdesc Abstract class for tools which create and display annotations on the\n * cornerstone canvas.\n * @extends Tools.Base.BaseTool\n */\nclass BaseAnnotationTool extends BaseTool {\n // ===================================================================\n // Abstract Methods - Must be implemented.\n // ===================================================================\n\n /**\n * Creates a new annotation.\n *\n * @method createNewMeasurement\n * @memberof Tools.Base.BaseAnnotationTool\n *\n * @param {type} evt description\n * @returns {type} description\n */\n // eslint-disable-next-line no-unused-vars\n createNewMeasurement(evt) {\n throw new Error(\n `Method createNewMeasurement not implemented for ${this.name}.`\n );\n }\n\n /**\n *\n * Returns true if the given coords are need the tool.\n *\n * @method pointNearTool\n * @memberof Tools.Base.BaseAnnotationTool\n *\n * @param {*} element\n * @param {*} data\n * @param {*} coords\n * @param {string} [interactionType=mouse]\n * @returns {boolean} If the point is near the tool\n */\n // eslint-disable-next-line no-unused-vars\n pointNearTool(element, data, coords, interactionType = 'mouse') {\n throw new Error(`Method pointNearTool not implemented for ${this.name}.`);\n }\n\n /**\n * Returns the distance in px from the given coords to the closest handle of the annotation.\n *\n * @method distanceFromPoint\n * @memberof Tools.Base.BaseAnnotationTool\n *\n * @param {*} element\n * @param {*} data\n * @param {*} coords\n * @returns {number} - the distance in px from the provided coordinates to the\n * closest rendered portion of the annotation. -1 if the distance cannot be\n * calculated.\n */\n // eslint-disable-next-line no-unused-vars\n distanceFromPoint(element, data, coords) {\n throw new Error(\n `Method distanceFromPoint not implemented for ${this.name}.`\n );\n }\n\n /**\n * Used to redraw the tool's annotation data per render\n *\n * @abstract\n * @param {*} evt\n * @returns {void}\n */\n // eslint-disable-next-line no-unused-vars\n renderToolData(evt) {\n throw new Error(`renderToolData not implemented for ${this.name}.`);\n }\n\n // ===================================================================\n // Virtual Methods - Have default behavior but may be overriden.\n // ===================================================================\n\n /**\n * Event handler for MOUSE_MOVE event.\n *\n * @abstract\n * @event\n * @param {Object} evt - The event.\n * @returns {boolean} - True if the image needs to be updated\n */\n mouseMoveCallback(evt) {\n const { element, currentPoints } = evt.detail;\n const coords = currentPoints.canvas;\n const toolState = getToolState(element, this.name);\n\n let imageNeedsUpdate = false;\n\n for (let d = 0; d < toolState.data.length; d++) {\n const data = toolState.data[d];\n\n // Hovering a handle?\n if (handleActivator(element, data.handles, coords) === true) {\n imageNeedsUpdate = true;\n }\n\n // Tool data's 'active' does not match coordinates\n // TODO: can't we just do an if/else and save on a pointNearTool check?\n const nearToolAndNotMarkedActive =\n this.pointNearTool(element, data, coords, 'mouse') && !data.active;\n const notNearToolAndMarkedActive =\n !this.pointNearTool(element, data, coords, 'mouse') && data.active;\n\n if (nearToolAndNotMarkedActive || notNearToolAndMarkedActive) {\n data.active = !data.active;\n imageNeedsUpdate = true;\n }\n }\n\n return imageNeedsUpdate;\n }\n\n /**\n * Custom callback for when a handle is selected.\n * @method handleSelectedCallback\n * @memberof Tools.Base.BaseAnnotationTool\n *\n * @param {*} evt -\n * @param {*} toolData -\n * @param {*} handle - The selected handle.\n * @param {String} interactionType -\n * @returns {void}\n */\n handleSelectedCallback(evt, toolData, handle, interactionType = 'mouse') {\n moveHandleNearImagePoint(evt, this, toolData, handle, interactionType);\n }\n\n /**\n * Custom callback for when a tool is selected.\n *\n * @method toolSelectedCallback\n * @memberof Tools.Base.BaseAnnotationTool\n *\n * @param {*} evt\n * @param {*} annotation\n * @param {string} [interactionType=mouse]\n * @returns {void}\n */\n toolSelectedCallback(evt, annotation, interactionType = 'mouse') {\n moveAnnotation(evt, this, annotation, interactionType);\n }\n\n /**\n * Updates cached statistics for the tool's annotation data on the element\n *\n * @param {*} image\n * @param {*} element\n * @param {*} data\n * @returns {void}\n */\n updateCachedStats(image, element, data) {\n // eslint-disable-line\n logger.warn(`updateCachedStats not implemented for ${this.name}.`);\n }\n}\n\nexport default BaseAnnotationTool;\n","import external from '../externalModules.js';\n\n/**\n * Calculates the distance of a line segment from a point.\n * @export @public @method\n * @name lineSegDistance\n *\n * @param {HTMLElement} element The element.\n * @param {Object} start The starting position of the line.\n * @param {Object} end The end position of the line.\n * @param {Object} coords The coordinates of the point.\n * @returns {name} The distance between the line and the point.\n */\nexport default function(element, start, end, coords) {\n const cornerstone = external.cornerstone;\n\n const lineSegment = {\n start: cornerstone.pixelToCanvas(element, start),\n end: cornerstone.pixelToCanvas(element, end),\n };\n\n return external.cornerstoneMath.lineSegment.distanceToPoint(\n lineSegment,\n coords\n );\n}\n","/**\n * Rounds a number to the specified precision.\n * @export @public @method\n * @name roundToDecimal\n *\n * @param {number} value The value to round.\n * @param {number} precision The required precision.\n * @returns {number} The rounded number.\n */\nexport default function(value, precision) {\n const multiplier = Math.pow(10, precision);\n\n return Math.round(value * multiplier) / multiplier;\n}\n","import toolColors from '../../stateManagement/toolColors.js';\nimport { modules } from '../../store/index.js';\n\nconst cursorModule = modules.cursor;\n\n/* eslint-disable valid-jsdoc */\n\n/*\nMACROS - The following keys will have the appropriate value injected when\nan SVG is requested:\n\n- ACTIVE_COLOR => options.activeColor || toolColors.getActiveColor();\n- TOOL_COLOR => options.toolColor || toolColors.getToolColor();\n- FILL_COLOR => options.fillColor || toolColors.getFillColor();\n*/\n\nexport default class MouseCursor {\n constructor(iconGroupString, options) {\n this.iconGroupString = iconGroupString;\n this.options = Object.assign(\n {},\n cursorModule.getters.defaultOptions(),\n options\n );\n }\n\n /**\n * Returns an SVG of the icon only.\n *\n * @param {Object} options - An object which overrides default properties of the returned SVG.\n * @returns {Blob} The SVG of the icon.\n */\n getIconSVG(options = {}) {\n const svgString = this._generateIconSVGString(options);\n\n return new Blob([svgString], { type: 'image/svg+xml' });\n }\n\n /**\n * Returns a string representation of the SVG of the icon only.\n *\n * @param {Object} options - An object which overrides default properties of the returned SVG.\n * @returns {string} The stringified SVG of the icon.\n */\n getIconSVGString(options = {}) {\n return this._generateIconSVGString(options);\n }\n\n /**\n * Returns an SVG of the icon + pointer.\n *\n * @param {Object} options - An object which overrides default properties of the returned SVG.\n * @returns {Blob} The SVG of the icon + pointer..\n */\n getIconWithPointerSVG(options = {}) {\n const svgString = this._generateIconWithPointerSVGString(options);\n\n return new Blob([svgString], { type: 'image/svg+xml' });\n }\n\n /**\n * Returns a string representation of the SVG of the icon + pointer.\n *\n * @param {Object} options - An object which overrides default properties of the returned SVG.\n * @returns {string} The stringified SVG of the icon + pointer.\n */\n getIconWithPointerString(options = {}) {\n return this._generateIconWithPointerSVGString(options);\n }\n\n /**\n * Returns the mousePoint as a space seperated string.\n *\n * @returns {string} The mousePoint.\n */\n get mousePoint() {\n const mousePoint = this.options.mousePoint;\n\n return `${mousePoint.x} ${mousePoint.y}`;\n }\n\n /**\n * Generates a string representation of the icon + pointer.\n *\n * @param {Object} options - An object which overrides default properties of the returned string.\n * @returns {string} The SVG as a string.\n */\n _generateIconWithPointerSVGString(options = {}) {\n const svgOptions = Object.assign({}, this.options, options);\n const { mousePointerGroupString, iconSize, viewBox } = svgOptions;\n\n const scale = iconSize / Math.max(viewBox.x, viewBox.y);\n const svgSize = 16 + iconSize;\n\n const svgString = `\n <svg\n data-icon=\"cursor\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\"\n width=\"${svgSize}\" height=\"${svgSize}\" viewBox=\"0 0 ${svgSize} ${svgSize}\"\n >\n <g>\n ${mousePointerGroupString}\n </g>\n <g transform=\"translate(16, 16) scale(${scale})\">\n ${this.iconGroupString}\n </g>\n </svg>`;\n\n return this._injectColors(svgString, svgOptions);\n }\n\n /**\n * Generates a string representation of the icon.\n *\n * @param {Object} options - An object which overrides default properties of the returned string.\n * @returns {string} The SVG as a string.\n */\n _generateIconSVGString(options = {}) {\n const svgOptions = Object.assign({}, this.options, options);\n const { iconSize, viewBox } = svgOptions;\n\n const svgString = `\n <svg\n data-icon=\"cursor\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\"\n width=\"${iconSize}\" height=\"${iconSize}\" viewBox=\"0 0\n ${viewBox.x} ${viewBox.y}\"\n >\n ${this.iconGroupString}\n </svg>`;\n\n return this._injectColors(svgString, svgOptions);\n }\n\n /**\n * Replaces ACTIVE_COLOR, TOOL_COLOR and FILL_COLOR in svgString with their appropriate values.\n *\n * @param {string} svgString - The string to modify.\n * @param {Object} options - Optional overrides for the colors.\n * @returns {string} The string with color values injected.\n */\n _injectColors(svgString, options = {}) {\n const activeColor = options.activeColor || toolColors.getActiveColor();\n const toolColor = options.toolColor || toolColors.getToolColor();\n const fillColor = options.fillColor || toolColors.getFillColor();\n\n return svgString\n .replace(/ACTIVE_COLOR/g, `${activeColor}`)\n .replace(/TOOL_COLOR/g, `${toolColor}`)\n .replace(/FILL_COLOR/g, `${fillColor}`);\n }\n}\n","import MouseCursor from './MouseCursor.js';\n\n/*\nMACROS:\n\nThe following keys will have the appropriate value injected by the MouseCursor\nclass when an SVG is requested:\n\n- ACTIVE_COLOR => options.activeColor || toolColors.getActiveColor();\n- TOOL_COLOR => options.toolColor || toolColors.getToolColor();\n- FILL_COLOR => options.fillColor || toolColors.getFillColor();\n*/\n\nexport const angleCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M1203 544q0 13-10 23l-393 393 393 393q10 10 10 23t-10 23l-50\n 50q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l466-466q10-10 23-10t23\n 10l50 50q10 10 10 23z\"\n />`,\n {\n viewBox: {\n x: 1792,\n y: 1792,\n },\n }\n);\n\nexport const arrowAnnotateCursor = new MouseCursor(\n `<g id=\"arrowAnnotate-group\" fill=\"none\" stroke-width=\"1\" stroke=\"ACTIVE_COLOR\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path id=\"arrowAnnotate-arrow\" d=\"M23,7 l-15,15 M7,17 l0,6 6,0\" stroke-width=\"2\" />\n </g>`,\n {\n viewBox: {\n x: 24,\n y: 24,\n },\n }\n);\n\nexport const bidirectionalCursor = new MouseCursor(\n `<g fill=\"ACTIVE_COLOR\" stroke-width=\"3\" stroke=\"ACTIVE_COLOR\">\n <path d=\"M27.63 3.21L3.12 28.81\"></path>\n <path d=\"M27.63 15.75L15.27 4.43\"></path>\n <path d=\"M16.5 4.28C16.5 4.96 15.95 5.51 15.27 5.51C14.59 5.51 14.03 4.96 14.03 4.28C14.03 3.59 14.59 3.04 15.27 3.04C15.95 3.04 16.5 3.59 16.5 4.28Z\" ></path>\n <path d=\"M28.87 3.19C28.87 3.87 28.31 4.43 27.63 4.43C26.95 4.43 26.4 3.87 26.4 3.19C26.4 2.51 26.95 1.95 27.63 1.95C28.31 1.95 28.87 2.51 28.87 3.19Z\"></path>\n <path d=\"M28.87 15.75C28.87 16.43 28.31 16.99 27.63 16.99C26.95 16.99 26.4 16.43 26.4 15.75C26.4 15.07 26.95 14.51 27.63 14.51C28.31 14.51 28.87 15.07 28.87 15.75Z\"></path>\n <path d=\"M4.73 28.44C4.73 29.12 4.17 29.68 3.49 29.68C2.81 29.68 2.25 29.12 2.25 28.44C2.25 27.76 2.81 27.2 3.49 27.2C4.17 27.2 4.73 27.76 4.73 28.44Z\"></path>\n </g>`,\n {\n viewBox: {\n x: 48,\n y: 48,\n },\n }\n);\n\nexport const cobbAngleCursor = new MouseCursor(\n `<g stroke=\"ACTIVE_COLOR\" stroke-width=\"3\">\n <path d=\"M28.59 2.34L3.82 12.32\"></path>\n <path d=\"M28.59 29.66L3.82 19.68\"></path>\n <path stroke-dasharray=\"2\" fill-opacity=\"0\" d=\"M12.37\n 23.06C12.67 22.36 12.85 21.93 12.92 21.76C14.6 17.8 14.68 13.35 13.15\n 9.33C13.11 9.24 13.02 9 12.88 8.63\">\n </path>\n </g>`,\n {\n viewBox: {\n x: 32,\n y: 32,\n },\n }\n);\n\nexport const circleRoiCursor = new MouseCursor(\n `<circle stroke=\"ACTIVE_COLOR\" fill=\"none\" stroke-width=\"3\" cx=\"16\" cy=\"16\" r=\"14\" />`,\n {\n viewBox: {\n x: 32,\n y: 32,\n },\n }\n);\n\nexport const ellipticalRoiCursor = new MouseCursor(\n `<path stroke=\"ACTIVE_COLOR\" fill=\"none\" stroke-width=\"3\" d=\"M30.74 15.76C30.74 20.99 24.14 25.23 16\n 25.23C7.86 25.23 1.26 20.99 1.26 15.76C1.26 10.54 7.86 6.3 16 6.3C24.14\n 6.3 30.74 10.54 30.74 15.76Z\"\n />`,\n {\n viewBox: {\n x: 32,\n y: 32,\n },\n }\n);\n\nexport const freehandRoiCursor = new MouseCursor(\n `\n <g fill=\"ACTIVE_COLOR\" stroke=\"ACTIVE_COLOR\" stroke-width=\"2\">\n <ellipse ry=\"1\" rx=\"1\" id=\"svg_3\" cy=\"4.240343\" cx=\"14.306499\"/>\n <line id=\"svg_4\" y2=\"3.58462\" x2=\"12.242186\" y1=\"3.997482\" x1=\"13.432202\"/>\n <line id=\"svg_5\" y2=\"3.268901\" x2=\"10.857882\" y1=\"3.608906\" x1=\"12.387902\"/>\n <line id=\"svg_6\" y2=\"3.147471\" x2=\"9.740724\" y1=\"3.293187\" x1=\"10.955026\"/>\n <line id=\"svg_7\" y2=\"3.147471\" x2=\"8.089274\" y1=\"3.196043\" x1=\"9.983585\"/>\n <line id=\"svg_8\" y2=\"3.268901\" x2=\"6.874972\" y1=\"3.123185\" x1=\"8.307848\"/>\n <line id=\"svg_9\" y2=\"3.657478\" x2=\"5.587812\" y1=\"3.220329\" x1=\"7.020688\"/>\n <line id=\"svg_10\" y2=\"4.046054\" x2=\"4.737801\" y1=\"3.560334\" x1=\"5.854959\"/>\n <line id=\"svg_11\" y2=\"4.337487\" x2=\"4.300652\" y1=\"3.997482\" x1=\"4.834945\"/>\n <line id=\"svg_12\" y2=\"4.726063\" x2=\"3.88779\" y1=\"4.191771\" x1=\"4.470655\"/>\n <line id=\"svg_15\" y2=\"5.3575\" x2=\"3.377783\" y1=\"4.604633\" x1=\"3.960648\"/>\n <line id=\"svg_16\" y2=\"6.183226\" x2=\"2.916348\" y1=\"5.138926\" x1=\"3.547785\"/>\n <line id=\"svg_17\" y2=\"6.960379\" x2=\"2.770632\" y1=\"5.867507\" x1=\"3.037779\"/>\n <line id=\"svg_18\" y2=\"7.713246\" x2=\"2.673488\" y1=\"6.741804\" x1=\"2.819204\"/>\n <line id=\"svg_19\" y2=\"8.684687\" x2=\"2.697774\" y1=\"7.616102\" x1=\"2.673488\"/>\n <line id=\"svg_20\" y2=\"9.753273\" x2=\"2.892062\" y1=\"8.611829\" x1=\"2.697774\"/>\n <line id=\"svg_21\" y2=\"10.724714\" x2=\"3.134923\" y1=\"9.534698\" x1=\"2.84349\"/>\n <line id=\"svg_23\" y2=\"11.647583\" x2=\"3.596357\" y1=\"10.578998\" x1=\"3.086351\"/>\n <line id=\"svg_25\" y2=\"12.521881\" x2=\"4.276366\" y1=\"11.501867\" x1=\"3.499213\"/>\n <line id=\"svg_26\" y2=\"13.930471\" x2=\"5.830673\" y1=\"12.376165\" x1=\"4.13065\"/>\n <line id=\"svg_28\" y2=\"14.707624\" x2=\"7.263549\" y1=\"13.881899\" x1=\"5.733528\"/>\n <line id=\"svg_29\" y2=\"15.339061\" x2=\"8.963571\" y1=\"14.61048\" x1=\"7.06926\"/>\n <line id=\"svg_30\" y2=\"15.581921\" x2=\"10.882168\" y1=\"15.314775\" x1=\"8.817855\"/>\n <line id=\"svg_31\" y2=\"15.460491\" x2=\"12.023612\" y1=\"15.581921\" x1=\"10.785024\"/>\n <line id=\"svg_33\" y2=\"15.120487\" x2=\"13.092197\" y1=\"15.484777\" x1=\"11.877895\"/>\n <line id=\"svg_34\" y2=\"14.586194\" x2=\"13.86935\" y1=\"15.217631\" x1=\"12.897909\"/>\n <line id=\"svg_35\" y2=\"13.833327\" x2=\"14.597931\" y1=\"14.756196\" x1=\"13.699348\"/>\n <line id=\"svg_37\" y2=\"12.716169\" x2=\"15.180796\" y1=\"13.881899\" x1=\"14.549359\"/>\n <line id=\"svg_39\" y2=\"11.429009\" x2=\"15.520801\" y1=\"12.813313\" x1=\"15.15651\"/>\n <ellipse ry=\"1\" rx=\"1\" id=\"svg_40\" cy=\"10.967574\" cx=\"15.520801\"/>\n </g>`,\n {\n viewBox: {\n x: 18,\n y: 18,\n },\n }\n);\n\nexport const freehandRoiSculptorCursor = new MouseCursor(\n `<g id=\"icon-freehand-sculpt\" fill=\"none\" stroke-width=\"1.5\" stroke=\"ACTIVE_COLOR\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line id=\"svg_1\" y2=\"2.559367\" x2=\"10.184807\" y1=\"4.467781\" x1=\"8.81711\"/>\n <line id=\"svg_4\" y2=\"1.493836\" x2=\"11.727442\" y1=\"2.766112\" x1=\"10.089386\"/>\n <line id=\"svg_7\" y2=\"1.080346\" x2=\"13.047428\" y1=\"1.748291\" x1=\"11.345759\"/>\n <line id=\"svg_8\" y2=\"1.000829\" x2=\"14.351511\" y1=\"1.112153\" x1=\"12.77707\"/>\n <line id=\"svg_9\" y2=\"1.350705\" x2=\"15.242104\" y1=\"0.905408\" x1=\"13.969828\"/>\n <line id=\"svg_10\" y2=\"2.098167\" x2=\"15.862339\" y1=\"1.14396\" x1=\"14.955842\"/>\n <line id=\"svg_11\" y2=\"3.195505\" x2=\"16.41896\" y1=\"1.939133\" x1=\"15.766918\"/>\n <line id=\"svg_12\" y2=\"4.292843\" x2=\"16.530284\" y1=\"2.925147\" x1=\"16.387153\"/>\n <line id=\"svg_16\" y2=\"5.644637\" x2=\"16.196311\" y1=\"3.831643\" x1=\"16.593898\"/>\n <line id=\"svg_18\" y2=\"7.266789\" x2=\"15.623787\" y1=\"5.19934\" x1=\"16.275829\"/>\n <line id=\"svg_19\" y2=\"10.813258\" x2=\"14.526449\" y1=\"6.726071\" x1=\"15.766918\"/>\n <line id=\"svg_20\" y2=\"5.056209\" x2=\"8.085552\" y1=\"4.181519\" x1=\"8.976145\"/>\n <line id=\"svg_23\" y2=\"5.326568\" x2=\"7.481221\" y1=\"4.78585\" x1=\"8.403621\"/>\n <line id=\"svg_24\" y2=\"5.565119\" x2=\"6.749662\" y1=\"5.294761\" x1=\"7.624352\"/>\n <line id=\"svg_25\" y2=\"5.994512\" x2=\"5.429675\" y1=\"5.533312\" x1=\"6.956407\"/>\n <line id=\"svg_27\" y2=\"6.551133\" x2=\"4.284627\" y1=\"5.962706\" x1=\"5.572807\"/>\n <line id=\"svg_28\" y2=\"7.584858\" x2=\"3.044158\" y1=\"6.392099\" x1=\"4.427758\"/>\n <line id=\"svg_29\" y2=\"8.84123\" x2=\"2.185372\" y1=\"7.489437\" x1=\"3.219096\"/>\n <line id=\"svg_31\" y2=\"10.606513\" x2=\"1.644654\" y1=\"8.602678\" x1=\"2.280792\"/>\n <line id=\"svg_32\" y2=\"13.214679\" x2=\"1.48562\" y1=\"10.352058\" x1=\"1.724171\"/>\n <line id=\"svg_33\" y2=\"14.375631\" x2=\"1.676461\" y1=\"12.992031\" x1=\"1.453813\"/>\n <line id=\"svg_34\" y2=\"15.298031\" x2=\"2.264889\" y1=\"14.152983\" x1=\"1.517427\"/>\n <line id=\"svg_35\" y2=\"16.172721\" x2=\"3.521261\" y1=\"14.948155\" x1=\"1.915013\"/>\n <line id=\"svg_36\" y2=\"16.824762\" x2=\"5.207027\" y1=\"15.997783\" x1=\"3.28271\"/>\n <line id=\"svg_38\" y2=\"17.063314\" x2=\"7.035924\" y1=\"16.745245\" x1=\"4.968475\"/>\n <line id=\"svg_39\" y2=\"16.888376\" x2=\"9.278311\" y1=\"17.047411\" x1=\"6.733758\"/>\n <line id=\"svg_40\" y2=\"16.284045\" x2=\"10.661911\" y1=\"16.983797\" x1=\"8.992048\"/>\n <line id=\"svg_41\" y2=\"15.313934\" x2=\"11.647925\" y1=\"16.395369\" x1=\"10.455166\"/>\n <line id=\"svg_44\" y2=\"13.898527\" x2=\"12.82478\" y1=\"15.425259\" x1=\"11.504794\"/>\n <line id=\"svg_45\" y2=\"12.037824\" x2=\"14.144766\" y1=\"14.312017\" x1=\"12.522614\"/>\n <line id=\"svg_47\" y2=\"10.59061\" x2=\"14.605966\" y1=\"12.228665\" x1=\"13.953925\"/>\n <ellipse ry=\"1\" rx=\"1\" id=\"svg_48\" cy=\"3.982726\" cx=\"13.460918\"/>\n </g>`,\n {\n viewBox: {\n x: 18,\n y: 18,\n },\n }\n);\n\nexport const lengthCursor = new MouseCursor(\n `<g id=\"length-group\" fill=\"none\" stroke-width=\"1\" stroke=\"ACTIVE_COLOR\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path id=\"length-dashes\" d=\"m22.5,6 -16.5,16.5\" stroke-width=\"3\" stroke-dasharray=\"0.6666,5\" />\n </g>`,\n {\n viewBox: {\n x: 24,\n y: 24,\n },\n }\n);\n\nexport const probeCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M1152 896q0 106-75 181t-181 75-181-75-75-181 75-181 181-75 181 75\n 75 181zm-256-544q-148 0-273 73t-198 198-73 273 73 273 198 198 273 73 273-73\n 198-198 73-273-73-273-198-198-273-73zm768 544q0 209-103 385.5t-279.5\n 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5\n 385.5-103 385.5 103 279.5 279.5 103 385.5z\"\n />`,\n {\n viewBox: {\n x: 1792,\n y: 1792,\n },\n }\n);\n\nexport const rectangleRoiCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M1312 256h-832q-66 0-113 47t-47 113v832q0 66 47\n 113t113 47h832q66 0 113-47t47-113v-832q0-66-47-113t-113-47zm288 160v832q0\n 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119\n 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z\"\n />`,\n {\n viewBox: {\n x: 1792,\n y: 1792,\n },\n }\n);\n\nexport const textMarkerCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M789 559l-170 450q33 0 136.5 2t160.5 2q19 0\n 57-2-87-253-184-452zm-725 1105l2-79q23-7 56-12.5t57-10.5 49.5-14.5 44.5-29\n 31-50.5l237-616 280-724h128q8 14 11 21l205 480q33 78 106 257.5t114 274.5q15\n 34 58 144.5t72 168.5q20 45 35 57 19 15 88 29.5t84 20.5q6 38 6 57 0 5-.5\n 13.5t-.5 12.5q-63 0-190-8t-191-8q-76 0-215 7t-178 8q0-43 4-78l131-28q1 0\n 12.5-2.5t15.5-3.5 14.5-4.5 15-6.5 11-8 9-11\n 2.5-14q0-16-31-96.5t-72-177.5-42-100l-450-2q-26 58-76.5 195.5t-50.5 162.5q0\n 22 14 37.5t43.5 24.5 48.5 13.5 57 8.5 41 4q1 19 1 58 0 9-2 27-58\n 0-174.5-10t-174.5-10q-8 0-26.5 4t-21.5 4q-80 14-188 14z\"\n />`,\n {\n viewBox: {\n x: 1792,\n y: 1792,\n },\n }\n);\n\nexport const crosshairsCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M1325 1024h-109q-26 0-45-19t-19-45v-128q0-26\n 19-45t45-19h109q-32-108-112.5-188.5t-188.5-112.5v109q0 26-19 45t-45\n 19h-128q-26 0-45-19t-19-45v-109q-108 32-188.5 112.5t-112.5 188.5h109q26\n 0 45 19t19 45v128q0 26-19 45t-45 19h-109q32 108 112.5 188.5t188.5\n 112.5v-109q0-26 19-45t45-19h128q26 0 45 19t19 45v109q108-32\n 188.5-112.5t112.5-188.5zm339-192v128q0 26-19 45t-45 19h-143q-37 161-154.5\n 278.5t-278.5 154.5v143q0 26-19 45t-45 19h-128q-26\n 0-45-19t-19-45v-143q-161-37-278.5-154.5t-154.5-278.5h-143q-26\n 0-45-19t-19-45v-128q0-26 19-45t45-19h143q37-161\n 154.5-278.5t278.5-154.5v-143q0-26 19-45t45-19h128q26 0 45 19t19 45v143q161\n 37 278.5 154.5t154.5 278.5h143q26 0 45 19t19 45z\"\n />`,\n {\n viewBox: {\n x: 1792,\n y: 1792,\n },\n }\n);\n\nexport const eraserCursor = new MouseCursor(\n `<path transform=\"translate(0,1792) scale(1,-1)\" fill=\"ACTIVE_COLOR\" d=\"M960 1408l336-384h-768l-336 384h768zm1013-1077q15\n 34 9.5 71.5t-30.5 65.5l-896 1024q-38 44-96 44h-768q-38\n 0-69.5-20.5t-47.5-54.5q-15-34-9.5-71.5t30.5-65.5l896-1024q38-44 96-44h768q38\n 0 69.5 20.5t47.5 54.5z\"\n />`,\n {\n viewBox: {\n x: 2048,\n y: 1792,\n },\n }\n);\n\nexport const magnifyCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M508.5 481.6l-129-129c-2.3-2.3-5.3-3.5-8.5-3.5h-10.3C395\n 312 416 262.5 416 208 416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c54.5\n 0 104-21 141.1-55.2V371c0 3.2 1.3 6.2 3.5 8.5l129 129c4.7 4.7 12.3 4.7 17\n 0l9.9-9.9c4.7-4.7 4.7-12.3 0-17zM208 384c-97.3 0-176-78.7-176-176S110.7 32 208\n 32s176 78.7 176 176-78.7 176-176 176z\"\n />`,\n {\n viewBox: {\n x: 512,\n y: 512,\n },\n }\n);\n\nexport const panCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M1411 541l-355 355 355 355 144-144q29-31 70-14 39 17\n 39 59v448q0 26-19 45t-45 19h-448q-42 0-59-40-17-39 14-69l144-144-355-355-355\n 355 144 144q31 30 14 69-17 40-59 40h-448q-26 0-45-19t-19-45v-448q0-42 40-59\n 39-17 69 14l144 144 355-355-355-355-144 144q-19 19-45 19-12\n 0-24-5-40-17-40-59v-448q0-26 19-45t45-19h448q42 0 59 40 17 39-14 69l-144\n 144 355 355 355-355-144-144q-31-30-14-69 17-40 59-40h448q26 0 45 19t19\n 45v448q0 42-39 59-13 5-25 5-26 0-45-19z\"\n />`,\n {\n viewBox: {\n x: 1792,\n y: 1792,\n },\n }\n);\n\nexport const rotateCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M1664 256v448q0 26-19 45t-45 19h-448q-42 0-59-40-17-39\n 14-69l138-138q-148-137-349-137-104 0-198.5 40.5t-163.5 109.5-109.5\n 163.5-40.5 198.5 40.5 198.5 109.5 163.5 163.5 109.5 198.5 40.5q119 0\n 225-52t179-147q7-10 23-12 15 0 25 9l137 138q9 8 9.5 20.5t-7.5 22.5q-109\n 132-264 204.5t-327 72.5q-156 0-298-61t-245-164-164-245-61-298 61-298\n 164-245 245-164 298-61q147 0 284.5 55.5t244.5 156.5l130-129q29-31 70-14\n 39 17 39 59z\"\n />`,\n {\n viewBox: {\n x: 1792,\n y: 1792,\n },\n }\n);\n\nexport const stackScrollCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M24 21v2c0 0.547-0.453 1-1 1h-22c-0.547\n 0-1-0.453-1-1v-2c0-0.547 0.453-1 1-1h22c0.547 0 1 0.453 1 1zM24 13v2c0\n 0.547-0.453 1-1 1h-22c-0.547 0-1-0.453-1-1v-2c0-0.547 0.453-1 1-1h22c0.547\n 0 1 0.453 1 1zM24 5v2c0 0.547-0.453 1-1 1h-22c-0.547\n 0-1-0.453-1-1v-2c0-0.547 0.453-1 1-1h22c0.547 0 1 0.453 1 1z\"\n />`,\n {\n viewBox: {\n x: 24,\n y: 28,\n },\n }\n);\n\nexport const wwwcRegionCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M1664 416v960q0 119-84.5 203.5t-203.5 84.5h-960q-119\n 0-203.5-84.5t-84.5-203.5v-960q0-119 84.5-203.5t203.5-84.5h960q119 0 203.5\n 84.5t84.5 203.5z\"\n />`,\n {\n viewBox: {\n x: 1792,\n y: 1792,\n },\n }\n);\n\nexport const wwwcCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M14.5,3.5 a1 1 0 0 1 -11,11 Z\" stroke=\"none\" opacity=\"0.8\" />\n <circle cx=\"9\" cy=\"9\" r=\"8\" fill=\"none\" stroke-width=\"2\" stroke=\"ACTIVE_COLOR\" />`,\n {\n viewBox: {\n x: 18,\n y: 18,\n },\n }\n);\n\nexport const zoomCursor = new MouseCursor(\n `<path fill=\"ACTIVE_COLOR\" d=\"M508.5 481.6l-129-129c-2.3-2.3-5.3-3.5-8.5-3.5h-10.3C395\n 312 416 262.5 416 208 416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c54.5\n 0 104-21 141.1-55.2V371c0 3.2 1.3 6.2 3.5 8.5l129 129c4.7 4.7 12.3 4.7 17\n 0l9.9-9.9c4.7-4.7 4.7-12.3 0-17zM208 384c-97.3 0-176-78.7-176-176S110.7 32 208\n 32s176 78.7 176 176-78.7 176-176 176z\"\n />\n <path fill=\"ACTIVE_COLOR\" transform=\"scale(0.22,0.22) translate(1400,0)\" d=\"M1216\n 320q0 26-19 45t-45 19h-128v1024h128q26 0 45 19t19 45-19 45l-256 256q-19\n 19-45 19t-45-19l-256-256q-19-19-19-45t19-45 45-19h128v-1024h-128q-26\n 0-45-19t-19-45 19-45l256-256q19-19 45-19t45 19l256 256q19 19 19 45z\"\n />`,\n {\n viewBox: {\n x: 640,\n y: 512,\n },\n }\n);\n\nconst segToolCursorBoundaries = {\n x: 127,\n y: 60,\n};\n\nconst minusRect = (color = 'ACTIVE_COLOR') =>\n `<rect fill=\"${color}\" x=\"80.19\" y=\"25.03\" width=\"47.14\" height=\"15.85\"/>`;\n\nconst plusRect = (\n color = 'ACTIVE_COLOR'\n) => `<rect fill=\"${color}\" x=\"80.19\" y=\"25.03\" width=\"47.14\" height=\"15.85\"/>\n <rect fill=\"${color}\" x=\"95.84\" y=\"9.38\" width=\"15.85\" height=\"47.14\"/>`;\n\nconst scissorIcon = `<path fill=\"ACTIVE_COLOR\" d=\"M82.89,10a12.09,12.09,0,0,0-16.8-2.5l-27.5,20.4-8.5-6.3a2.93,2.93,0,0,1-1.1-3,14.66,14.66,0,0,0,.1-6.6,14.08,14.08,0,1,0-6.5,15.2,2.87,2.87,0,0,1,3.2.2l8.2,6.1-8.2,6.1a2.87,2.87,0,0,1-3.2.2,14.16,14.16,0,1,0,6.7,14.4,14,14,0,0,0-.3-5.8,2.93,2.93,0,0,1,1.1-3l8.5-6.3,27.5,20.4A11.91,11.91,0,0,0,82.89,57l-31.7-23.5ZM15.29,21a5.9,5.9,0,1,1,5.9-5.9A5.91,5.91,0,0,1,15.29,21Zm0,36.8a5.9,5.9,0,1,1,5.9-5.9A5.91,5.91,0,0,1,15.29,57.77Zm28.3-21.5a2.8,2.8,0,1,1,2.8-2.8A2.8,2.8,0,0,1,43.59,36.27Z\" transform=\"translate(-1.17 -0.96)\"/>`;\nconst rectangleIcon = `<path fill=\"ACTIVE_COLOR\" d=\"M8.86,2.25V66.08H72.69V2.25H8.86ZM65.28,58.67h-49v-49h49v49Z\" transform=\"translate(-8.86 -2.25)\"/>`;\nconst circleIcon = `<path fill=\"ACTIVE_COLOR\" d=\"M40.77,2.25A31.92,31.92,0,1,0,72.69,34.16,31.92,31.92,0,0,0,40.77,2.25Zm0,57.63A25.71,25.71,0,1,1,66.48,34.16,25.71,25.71,0,0,1,40.77,59.87Z\" transform=\"translate(-8.86 -2.25)\"/>`;\n\nexport const freehandEraseInsideCursor = new MouseCursor(\n `${scissorIcon} ${minusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const freehandFillInsideCursor = new MouseCursor(\n `${scissorIcon} ${plusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const freehandEraseOutsideCursor = new MouseCursor(\n `${scissorIcon} ${minusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const freehandFillOutsideCursor = new MouseCursor(\n `${scissorIcon} ${plusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const segRectangleEraseInsideCursor = new MouseCursor(\n `${rectangleIcon} ${minusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const segRectangleFillInsideCursor = new MouseCursor(\n `${rectangleIcon} ${plusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const segRectangleEraseOutsideCursor = new MouseCursor(\n `${rectangleIcon} ${minusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const segRectangleFillOutsideCursor = new MouseCursor(\n `${rectangleIcon} ${plusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const segCircleEraseInsideCursor = new MouseCursor(\n `${circleIcon} ${minusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const segCircleFillInsideCursor = new MouseCursor(\n `${circleIcon} ${plusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const segCircleEraseOutsideCursor = new MouseCursor(\n `${circleIcon} ${minusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n\nexport const segCircleFillOutsideCursor = new MouseCursor(\n `${circleIcon} ${plusRect()}`,\n {\n viewBox: segToolCursorBoundaries,\n }\n);\n","import external from '../externalModules';\n\nexport default function getPixelSpacing(image) {\n const imagePlane = external.cornerstone.metaData.get(\n 'imagePlaneModule',\n image.imageId\n );\n\n if (imagePlane) {\n return {\n rowPixelSpacing:\n imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing,\n colPixelSpacing:\n imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing,\n };\n }\n\n return {\n rowPixelSpacing: image.rowPixelSpacing,\n colPixelSpacing: image.columnPixelSpacing,\n };\n}\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * isObject({})\n * // => true\n *\n * isObject([1, 2, 3])\n * // => true\n *\n * isObject(Function)\n * // => true\n *\n * isObject(null)\n * // => false\n */\nfunction isObject(value) {\n const type = typeof value;\n\n return value !== null && (type === 'object' || type === 'function');\n}\n\nexport default isObject;\n","import isObject from './isObject.js';\n\n/**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked, or until the next browser frame is drawn. The debounced function\n * comes with a `cancel` method to cancel delayed `func` invocations and a\n * `flush` method to immediately invoke them. Provide `options` to indicate\n * whether `func` should be invoked on the leading and/or trailing edge of the\n * `wait` timeout. The `func` is invoked with the last arguments provided to the\n * debounced function. Subsequent calls to the debounced function return the\n * result of the last `func` invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * If `wait` is omitted in an environment with `requestAnimationFrame`, `func`\n * invocation will be deferred until the next frame is drawn (typically about\n * 16ms).\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `debounce` and `throttle`.\n *\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0]\n * The number of milliseconds to delay; if omitted, `requestAnimationFrame` is\n * used (if available).\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', debounce(calculateLayout, 150))\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }))\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * const debounced = debounce(batchLog, 250, { 'maxWait': 1000 })\n * const source = new EventSource('/stream')\n * jQuery(source).on('message', debounced)\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel)\n *\n * // Check for pending invocations.\n * const status = debounced.pending() ? \"Pending...\" : \"Ready\"\n */\nfunction debounce(func, wait, options) {\n let lastArgs, lastThis, maxWait, result, timerId, lastCallTime;\n\n let lastInvokeTime = 0;\n let leading = false;\n let maxing = false;\n let trailing = true;\n\n // Bypass `requestAnimationFrame` by explicitly setting `wait=0`.\n const useRAF =\n !wait && wait !== 0 && typeof window.requestAnimationFrame === 'function';\n\n if (typeof func !== 'function') {\n throw new TypeError('Expected a function');\n }\n wait = Number(wait) || 0;\n if (isObject(options)) {\n leading = Boolean(options.leading);\n maxing = 'maxWait' in options;\n maxWait = maxing ? Math.max(Number(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? Boolean(options.trailing) : trailing;\n }\n\n function invokeFunc(time) {\n const args = lastArgs;\n const thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n\n return result;\n }\n\n function startTimer(pendingFunc, wait) {\n if (useRAF) {\n return window.requestAnimationFrame(pendingFunc);\n }\n\n return setTimeout(pendingFunc, wait);\n }\n\n function cancelTimer(id) {\n if (useRAF) {\n return window.cancelAnimationFrame(id);\n }\n clearTimeout(id);\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = startTimer(timerExpired, wait);\n\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n const timeSinceLastCall = time - lastCallTime;\n const timeSinceLastInvoke = time - lastInvokeTime;\n const timeWaiting = wait - timeSinceLastCall;\n\n return maxing\n ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke)\n : timeWaiting;\n }\n\n function shouldInvoke(time) {\n const timeSinceLastCall = time - lastCallTime;\n const timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (\n lastCallTime === undefined ||\n timeSinceLastCall >= wait ||\n timeSinceLastCall < 0 ||\n (maxing && timeSinceLastInvoke >= maxWait)\n );\n }\n\n function timerExpired() {\n const time = Date.now();\n\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = startTimer(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n cancelTimer(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(Date.now());\n }\n\n function pending() {\n return timerId !== undefined;\n }\n\n function debounced(...args) {\n const time = Date.now();\n const isInvoking = shouldInvoke(time);\n\n lastArgs = args;\n lastThis = this; // eslint-disable-line consistent-this\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n timerId = startTimer(timerExpired, wait);\n\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = startTimer(timerExpired, wait);\n }\n\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n debounced.pending = pending;\n\n return debounced;\n}\n\nexport default debounce;\n","import debounce from './debounce.js';\nimport isObject from './isObject.js';\n\n/**\n * Creates a throttled function that only invokes `func` at most once per\n * every `wait` milliseconds (or once per browser frame). The throttled function\n * comes with a `cancel` method to cancel delayed `func` invocations and a\n * `flush` method to immediately invoke them. Provide `options` to indicate\n * whether `func` should be invoked on the leading and/or trailing edge of the\n * `wait` timeout. The `func` is invoked with the last arguments provided to the\n * throttled function. Subsequent calls to the throttled function return the\n * result of the last `func` invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the throttled function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * If `wait` is omitted in an environment with `requestAnimationFrame`, `func`\n * invocation will be deferred until the next frame is drawn (typically about\n * 16ms).\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `throttle` and `debounce`.\n *\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to throttle.\n * @param {number} [wait=0]\n * The number of milliseconds to throttle invocations to; if omitted,\n * `requestAnimationFrame` is used (if available).\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=true]\n * Specify invoking on the leading edge of the timeout.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new throttled function.\n * @example\n *\n * // Avoid excessively updating the position while scrolling.\n * jQuery(window).on('scroll', throttle(updatePosition, 100))\n *\n * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.\n * const throttled = throttle(renewToken, 300000, { 'trailing': false })\n * jQuery(element).on('click', throttled)\n *\n * // Cancel the trailing throttled invocation.\n * jQuery(window).on('popstate', throttled.cancel)\n */\nfunction throttle(func, wait, options) {\n let leading = true;\n let trailing = true;\n\n if (typeof func !== 'function') {\n throw new TypeError('Expected a function');\n }\n if (isObject(options)) {\n leading = 'leading' in options ? Boolean(options.leading) : leading;\n trailing = 'trailing' in options ? Boolean(options.trailing) : trailing;\n }\n\n return debounce(func, wait, {\n leading,\n trailing,\n maxWait: wait,\n });\n}\n\nexport default throttle;\n","import external from './../../externalModules.js';\nimport BaseAnnotationTool from '../base/BaseAnnotationTool.js';\n// State\nimport {\n addToolState,\n getToolState,\n} from './../../stateManagement/toolState.js';\nimport toolStyle from './../../stateManagement/toolStyle.js';\nimport toolColors from './../../stateManagement/toolColors.js';\n// Manipulators\nimport { moveNewHandle } from './../../manipulators/index.js';\n// Drawing\nimport {\n getNewContext,\n draw,\n setShadow,\n drawJoinedLines,\n} from './../../drawing/index.js';\nimport drawLinkedTextBox from './../../drawing/drawLinkedTextBox.js';\nimport { textBoxWidth } from './../../drawing/drawTextBox.js';\nimport drawHandles from './../../drawing/drawHandles.js';\nimport lineSegDistance from './../../util/lineSegDistance.js';\nimport roundToDecimal from './../../util/roundToDecimal.js';\nimport { angleCursor } from '../cursors/index.js';\nimport triggerEvent from '../../util/triggerEvent.js';\nimport EVENTS from '../../events.js';\nimport getPixelSpacing from '../../util/getPixelSpacing';\nimport throttle from '../../util/throttle';\n\n/**\n * @public\n * @class AngleTool\n * @memberof Tools.Annotation\n * @classdesc Create and position an angle by placing three consecutive points.\n * @extends Tools.Base.BaseAnnotationTool\n * @hideconstructor\n *\n * @param {ToolConfiguration} [props={}]\n */\nexport default class AngleTool extends BaseAnnotationTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Angle',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: angleCursor,\n };\n\n super(props, defaultProps);\n\n this.preventNewMeasurement = false;\n\n this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);\n }\n\n createNewMeasurement(eventData) {\n // Create the measurement data for this tool with the end handle activated\n return {\n visible: true,\n active: true,\n color: undefined,\n invalidated: true,\n handles: {\n start: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: false,\n },\n middle: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: true,\n },\n end: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: false,\n },\n textBox: {\n active: false,\n hasMoved: false,\n movesIndependently: false,\n drawnIndependently: true,\n allowedOutsideImage: true,\n hasBoundingBox: true,\n },\n },\n };\n }\n\n pointNearTool(element, data, coords) {\n if (data.visible === false) {\n return false;\n }\n\n return (\n lineSegDistance(\n element,\n data.handles.start,\n data.handles.middle,\n coords\n ) < 25 ||\n lineSegDistance(element, data.handles.middle, data.handles.end, coords) <\n 25\n );\n }\n\n updateCachedStats(image, element, data) {\n const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);\n\n const sideA = {\n x: (data.handles.middle.x - data.handles.start.x) * colPixelSpacing,\n y: (data.handles.middle.y - data.handles.start.y) * rowPixelSpacing,\n };\n\n const sideB = {\n x: (data.handles.end.x - data.handles.middle.x) * colPixelSpacing,\n y: (data.handles.end.y - data.handles.middle.y) * rowPixelSpacing,\n };\n\n const sideC = {\n x: (data.handles.end.x - data.handles.start.x) * colPixelSpacing,\n y: (data.handles.end.y - data.handles.start.y) * rowPixelSpacing,\n };\n\n const sideALength = length(sideA);\n const sideBLength = length(sideB);\n const sideCLength = length(sideC);\n\n // Cosine law\n let angle = Math.acos(\n (Math.pow(sideALength, 2) +\n Math.pow(sideBLength, 2) -\n Math.pow(sideCLength, 2)) /\n (2 * sideALength * sideBLength)\n );\n\n angle *= 180 / Math.PI;\n\n data.rAngle = roundToDecimal(angle, 2);\n data.invalidated = false;\n }\n\n renderToolData(evt) {\n const eventData = evt.detail;\n const enabledElement = eventData.enabledElement;\n const { handleRadius, drawHandlesOnHover } = this.configuration;\n // If we have no toolData for this element, return immediately as there is nothing to do\n const toolData = getToolState(evt.currentTarget, this.name);\n\n if (!toolData) {\n return;\n }\n\n // We have tool data for this element - iterate over each one and draw it\n const context = getNewContext(eventData.canvasContext.canvas);\n const { image, element } = eventData;\n const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);\n\n const lineWidth = toolStyle.getToolWidth();\n\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n draw(context, context => {\n setShadow(context, this.configuration);\n\n // Differentiate the color of activation tool\n const color = toolColors.getColorIfActive(data);\n\n const handleStartCanvas = external.cornerstone.pixelToCanvas(\n eventData.element,\n data.handles.start\n );\n const handleMiddleCanvas = external.cornerstone.pixelToCanvas(\n eventData.element,\n data.handles.middle\n );\n\n drawJoinedLines(\n context,\n eventData.element,\n data.handles.start,\n [data.handles.middle, data.handles.end],\n { color }\n );\n\n // Draw the handles\n const handleOptions = {\n color,\n handleRadius,\n drawHandlesIfActive: drawHandlesOnHover,\n };\n\n drawHandles(context, eventData, data.handles, handleOptions);\n\n // Update textbox stats\n if (data.invalidated === true) {\n if (data.rAngle) {\n this.throttledUpdateCachedStats(image, element, data);\n } else {\n this.updateCachedStats(image, element, data);\n }\n }\n\n if (data.rAngle) {\n const text = textBoxText(data, rowPixelSpacing, colPixelSpacing);\n\n const distance = 15;\n\n let textCoords;\n\n if (!data.handles.textBox.hasMoved) {\n textCoords = {\n x: handleMiddleCanvas.x,\n y: handleMiddleCanvas.y,\n };\n\n const padding = 5;\n const textWidth = textBoxWidth(context, text, padding);\n\n if (handleMiddleCanvas.x < handleStartCanvas.x) {\n textCoords.x -= distance + textWidth + 10;\n } else {\n textCoords.x += distance;\n }\n\n const transform = external.cornerstone.internal.getTransform(\n enabledElement\n );\n\n transform.invert();\n\n const coords = transform.transformPoint(textCoords.x, textCoords.y);\n\n data.handles.textBox.x = coords.x;\n data.handles.textBox.y = coords.y;\n }\n\n drawLinkedTextBox(\n context,\n eventData.element,\n data.handles.textBox,\n text,\n data.handles,\n textBoxAnchorPoints,\n color,\n lineWidth,\n 0,\n true\n );\n }\n });\n }\n\n function textBoxText(data, rowPixelSpacing, colPixelSpacing) {\n const suffix = !rowPixelSpacing || !colPixelSpacing ? ' (isotropic)' : '';\n const str = '00B0'; // Degrees symbol\n\n return (\n data.rAngle.toString() + String.fromCharCode(parseInt(str, 16)) + suffix\n );\n }\n\n function textBoxAnchorPoints(handles) {\n return [handles.start, handles.middle, handles.end];\n }\n }\n\n addNewMeasurement(evt, interactionType) {\n if (this.preventNewMeasurement) {\n return;\n }\n\n this.preventNewMeasurement = true;\n evt.preventDefault();\n evt.stopPropagation();\n\n const eventData = evt.detail;\n const measurementData = this.createNewMeasurement(eventData);\n const element = evt.detail.element;\n\n // Associate this data with this imageId so we can render it and manipulate it\n addToolState(element, this.name, measurementData);\n external.cornerstone.updateImage(element);\n\n // Step 1, create start and second middle.\n moveNewHandle(\n eventData,\n this.name,\n measurementData,\n measurementData.handles.middle,\n this.options,\n interactionType,\n () => {\n measurementData.active = false;\n measurementData.handles.end.active = true;\n\n external.cornerstone.updateImage(element);\n\n // Step 2, create end.\n moveNewHandle(\n eventData,\n this.name,\n measurementData,\n measurementData.handles.end,\n this.options,\n interactionType,\n () => {\n measurementData.active = false;\n this.preventNewMeasurement = false;\n external.cornerstone.updateImage(element);\n }\n );\n }\n );\n }\n}\n\nfunction length(vector) {\n return Math.sqrt(Math.pow(vector.x, 2) + Math.pow(vector.y, 2));\n}\n","/* eslint no-alert: 0 */\nimport external from './../../externalModules.js';\nimport BaseAnnotationTool from '../base/BaseAnnotationTool.js';\n\nimport EVENTS from './../../events.js';\nimport toolStyle from './../../stateManagement/toolStyle.js';\nimport textStyle from './../../stateManagement/textStyle.js';\nimport toolColors from './../../stateManagement/toolColors.js';\nimport { moveNewHandle } from './../../manipulators/index.js';\nimport pointInsideBoundingBox from './../../util/pointInsideBoundingBox.js';\nimport lineSegDistance from './../../util/lineSegDistance.js';\nimport triggerEvent from './../../util/triggerEvent.js';\n\nimport {\n addToolState,\n removeToolState,\n getToolState,\n} from './../../stateManagement/toolState.js';\nimport drawLinkedTextBox from './../../drawing/drawLinkedTextBox.js';\nimport { getNewContext, draw, setShadow } from './../../drawing/index.js';\nimport drawArrow from './../../drawing/drawArrow.js';\nimport drawHandles from './../../drawing/drawHandles.js';\nimport { textBoxWidth } from './../../drawing/drawTextBox.js';\nimport { arrowAnnotateCursor } from '../cursors/index.js';\n\n/**\n * @public\n * @class ArrowAnnotateTool\n * @memberof Tools.Annotation\n * @classdesc Create and position an arrow and label\n * @extends Tools.Base.BaseAnnotationTool\n */\nexport default class ArrowAnnotateTool extends BaseAnnotationTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'ArrowAnnotate',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {\n getTextCallback,\n changeTextCallback,\n drawHandles: false,\n drawHandlesOnHover: true,\n arrowFirst: true,\n },\n svgCursor: arrowAnnotateCursor,\n };\n\n super(props, defaultProps);\n this.preventNewMeasurement = false;\n }\n\n createNewMeasurement(evt) {\n // Create the measurement data for this tool with the end handle activated\n return {\n visible: true,\n active: true,\n color: undefined,\n handles: {\n start: {\n x: evt.detail.currentPoints.image.x,\n y: evt.detail.currentPoints.image.y,\n highlight: true,\n active: false,\n },\n end: {\n x: evt.detail.currentPoints.image.x,\n y: evt.detail.currentPoints.image.y,\n highlight: true,\n active: false,\n },\n textBox: {\n active: false,\n hasMoved: false,\n movesIndependently: false,\n drawnIndependently: true,\n allowedOutsideImage: true,\n hasBoundingBox: true,\n },\n },\n };\n }\n\n pointNearTool(element, data, coords) {\n if (data.visible === false) {\n return false;\n }\n\n return (\n lineSegDistance(element, data.handles.start, data.handles.end, coords) <\n 25\n );\n }\n\n updateCachedStats() {\n // Implementing to satisfy BaseAnnotationTool\n }\n\n renderToolData(evt) {\n const { element, enabledElement } = evt.detail;\n const { handleRadius, drawHandlesOnHover } = this.configuration;\n\n // If we have no toolData for this element, return immediately as there is nothing to do\n const toolData = getToolState(element, this.name);\n\n if (!toolData) {\n return;\n }\n\n // We have tool data for this element - iterate over each one and draw it\n const canvas = evt.detail.canvasContext.canvas;\n const context = getNewContext(canvas);\n\n const lineWidth = toolStyle.getToolWidth();\n\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n draw(context, context => {\n setShadow(context, this.configuration);\n\n const color = toolColors.getColorIfActive(data);\n\n // Draw the arrow\n const handleStartCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.start\n );\n const handleEndCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.end\n );\n\n // Config.arrowFirst = false;\n if (this.configuration.arrowFirst) {\n drawArrow(\n context,\n handleEndCanvas,\n handleStartCanvas,\n color,\n lineWidth\n );\n } else {\n drawArrow(\n context,\n handleStartCanvas,\n handleEndCanvas,\n color,\n lineWidth\n );\n }\n\n const handleOptions = {\n color,\n handleRadius,\n drawHandlesIfActive: drawHandlesOnHover,\n };\n\n if (this.configuration.drawHandles) {\n drawHandles(context, evt.detail, data.handles, handleOptions);\n }\n\n const text = textBoxText(data);\n\n // Draw the text\n if (text && text !== '') {\n // Calculate the text coordinates.\n const padding = 5;\n const textWidth = textBoxWidth(context, text, padding);\n const textHeight = textStyle.getFontSize() + 10;\n\n let distance = Math.max(textWidth, textHeight) / 2 + 5;\n\n if (handleEndCanvas.x < handleStartCanvas.x) {\n distance = -distance;\n }\n\n if (!data.handles.textBox.hasMoved) {\n let textCoords;\n\n if (this.configuration.arrowFirst) {\n textCoords = {\n x: handleEndCanvas.x - textWidth / 2 + distance,\n y: handleEndCanvas.y - textHeight / 2,\n };\n } else {\n // If the arrow is at the End position, the text should\n // Be placed near the Start position\n textCoords = {\n x: handleStartCanvas.x - textWidth / 2 - distance,\n y: handleStartCanvas.y - textHeight / 2,\n };\n }\n\n const transform = external.cornerstone.internal.getTransform(\n enabledElement\n );\n\n transform.invert();\n\n const coords = transform.transformPoint(textCoords.x, textCoords.y);\n\n data.handles.textBox.x = coords.x;\n data.handles.textBox.y = coords.y;\n }\n\n drawLinkedTextBox(\n context,\n element,\n data.handles.textBox,\n text,\n data.handles,\n textBoxAnchorPoints,\n color,\n lineWidth,\n 0,\n false\n );\n }\n });\n }\n\n function textBoxText(data) {\n return data.text;\n }\n\n function textBoxAnchorPoints(handles) {\n const midpoint = {\n x: (handles.start.x + handles.end.x) / 2,\n y: (handles.start.y + handles.end.y) / 2,\n };\n\n return [handles.start, midpoint, handles.end];\n }\n }\n\n addNewMeasurement(evt, interactionType) {\n const element = evt.detail.element;\n const measurementData = this.createNewMeasurement(evt);\n\n // Associate this data with this imageId so we can render it and manipulate it\n addToolState(element, this.name, measurementData);\n external.cornerstone.updateImage(element);\n\n moveNewHandle(\n evt.detail,\n this.name,\n measurementData,\n measurementData.handles.end,\n this.options,\n interactionType,\n () => {\n if (measurementData.text === undefined) {\n this.configuration.getTextCallback(text => {\n if (text) {\n measurementData.text = text;\n } else {\n removeToolState(element, this.name, measurementData);\n }\n\n measurementData.active = false;\n external.cornerstone.updateImage(element);\n });\n }\n external.cornerstone.updateImage(element);\n }\n );\n }\n\n doubleClickCallback(evt) {\n return this._updateTextForNearbyAnnotation(evt);\n }\n\n touchPressCallback(evt) {\n return this._updateTextForNearbyAnnotation(evt);\n }\n\n _updateTextForNearbyAnnotation(evt) {\n const element = evt.detail.element;\n const coords = evt.detail.currentPoints.canvas;\n const toolState = getToolState(element, this.name);\n\n if (!toolState) {\n return false;\n }\n\n for (let i = 0; i < toolState.data.length; i++) {\n const data = toolState.data[i];\n\n if (\n this.pointNearTool(element, data, coords) ||\n pointInsideBoundingBox(data.handles.textBox, coords)\n ) {\n data.active = true;\n external.cornerstone.updateImage(element);\n // Allow relabelling via a callback\n this.configuration.changeTextCallback(\n data,\n evt.detail,\n this._doneChangingTextCallback.bind(this, element, data)\n );\n\n evt.stopImmediatePropagation();\n evt.preventDefault();\n evt.stopPropagation();\n\n return true;\n }\n }\n }\n\n _doneChangingTextCallback(element, data, updatedText, deleteTool) {\n if (deleteTool === true) {\n removeToolState(element, this.name, data);\n } else {\n data.text = updatedText;\n }\n\n data.active = false;\n external.cornerstone.updateImage(element);\n }\n}\n\nfunction getTextCallback(doneChangingTextCallback) {\n doneChangingTextCallback(prompt('Enter your annotation:'));\n}\n\nfunction changeTextCallback(data, eventData, doneChangingTextCallback) {\n doneChangingTextCallback(prompt('Change your annotation:'));\n}\n","const getHandle = (x, y, index, extraAttributes = {}) =>\n Object.assign(\n {\n x,\n y,\n index,\n drawnIndependently: false,\n allowedOutsideImage: false,\n highlight: true,\n active: false,\n },\n extraAttributes\n );\n\nexport default function(mouseEventData) {\n const { x, y } = mouseEventData.currentPoints.image;\n // Create the measurement data for this tool with the end handle activated\n const measurementData = {\n toolType: this.name,\n isCreating: true,\n visible: true,\n active: true,\n invalidated: true,\n handles: {\n start: getHandle(x, y, 0),\n end: getHandle(x, y, 1, { active: true }),\n perpendicularStart: getHandle(x, y, 2, { locked: true }),\n perpendicularEnd: getHandle(x, y, 3),\n textBox: getHandle(x - 50, y - 70, null, {\n highlight: false,\n hasMoved: true,\n active: false,\n movesIndependently: false,\n drawnIndependently: true,\n allowedOutsideImage: true,\n hasBoundingBox: true,\n }),\n },\n longestDiameter: 0,\n shortestDiameter: 0,\n };\n\n return measurementData;\n}\n","import { state } from '../../../store/index.js';\nimport external from './../../../externalModules.js';\nimport pointInsideBoundingBox from './../../../util/pointInsideBoundingBox.js';\n\nconst pointNearPerpendicular = (\n element,\n handles,\n coords,\n distanceThreshold\n) => {\n const cornerstone = external.cornerstone;\n const cornerstoneMath = external.cornerstoneMath;\n const lineSegment = {\n start: cornerstone.pixelToCanvas(element, handles.perpendicularStart),\n end: cornerstone.pixelToCanvas(element, handles.perpendicularEnd),\n };\n\n const distanceToPoint = cornerstoneMath.lineSegment.distanceToPoint(\n lineSegment,\n coords\n );\n\n return distanceToPoint < distanceThreshold;\n};\n\nexport default function(element, data, coords, interactionType = 'mouse') {\n const cornerstone = external.cornerstone;\n const cornerstoneMath = external.cornerstoneMath;\n const { handles } = data;\n const lineSegment = {\n start: cornerstone.pixelToCanvas(element, handles.start),\n end: cornerstone.pixelToCanvas(element, handles.end),\n };\n\n const distanceToPoint = cornerstoneMath.lineSegment.distanceToPoint(\n lineSegment,\n coords\n );\n\n if (pointInsideBoundingBox(handles.textBox, coords)) {\n return true;\n }\n\n const distanceThreshold =\n interactionType === 'mouse' ? state.clickProximity : state.touchProximity;\n\n if (pointNearPerpendicular(element, handles, coords, distanceThreshold)) {\n return true;\n }\n\n return distanceToPoint < distanceThreshold;\n}\n","/**\n * Return the Vector of a line which determines its inclination and length\n *\n * @param {number} columnPixelSpacing Width that a pixel represents in mm\n * @param {number} rowPixelSpacing Height that a pixel represents in mm\n * @param {*} startPoint Start point of the line\n * @param {*} endPoint End point of the line\n *\n * @returns {*} Resulting line inclination vector\n */\nexport default function getLineVector(\n columnPixelSpacing,\n rowPixelSpacing,\n startPoint,\n endPoint\n) {\n const dx = (startPoint.x - endPoint.x) * columnPixelSpacing;\n const dy = (startPoint.y - endPoint.y) * rowPixelSpacing;\n const length = Math.sqrt(dx * dx + dy * dy);\n const vectorX = dx / length;\n const vectorY = dy / length;\n\n return {\n x: vectorX,\n y: vectorY,\n length,\n };\n}\n","/* eslint no-loop-func: 0 */ // --> OFF\nimport drawHandles from './../../../drawing/drawHandles.js';\nimport updatePerpendicularLineHandles from './utils/updatePerpendicularLineHandles.js';\n\nimport toolStyle from './../../../stateManagement/toolStyle.js';\nimport toolColors from './../../../stateManagement/toolColors.js';\nimport { getToolState } from './../../../stateManagement/toolState.js';\nimport {\n getNewContext,\n draw,\n setShadow,\n drawLine,\n} from './../../../drawing/index.js';\nimport drawLinkedTextBox from './../../../drawing/drawLinkedTextBox.js';\nimport getPixelSpacing from '../../../util/getPixelSpacing';\n\nexport default function(evt) {\n const eventData = evt.detail;\n const { element, canvasContext, image } = eventData;\n const { handleRadius, drawHandlesOnHover } = this.configuration;\n\n // If we have no toolData for this element, return immediately as there is nothing to do\n const toolData = getToolState(element, this.name);\n\n if (!toolData) {\n return;\n }\n\n const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);\n\n // LT-29 Disable Target Measurements when pixel spacing is not available\n if (!rowPixelSpacing || !colPixelSpacing) {\n return;\n }\n\n // We have tool data for this element - iterate over each one and draw it\n const context = getNewContext(canvasContext.canvas);\n\n let color;\n const activeColor = toolColors.getActiveColor();\n const lineWidth = toolStyle.getToolWidth();\n\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n color = data.active ? activeColor : toolColors.getToolColor();\n\n // Calculate the data measurements\n if (data.invalidated === true) {\n if (data.longestDiameter && data.shortestDiameter) {\n this.throttledUpdateCachedStats(image, element, data);\n } else {\n this.updateCachedStats(image, element, data);\n }\n }\n\n draw(context, context => {\n // Configurable shadow\n setShadow(context, this.configuration);\n\n const {\n start,\n end,\n perpendicularStart,\n perpendicularEnd,\n textBox,\n } = data.handles;\n\n // Draw the measurement line\n drawLine(context, element, start, end, { color });\n\n // Draw perpendicular line\n const strokeWidth = lineWidth;\n\n updatePerpendicularLineHandles(eventData, data);\n drawLine(context, element, perpendicularStart, perpendicularEnd, {\n color,\n strokeWidth,\n });\n\n // Draw the handles\n const handleOptions = {\n color,\n handleRadius,\n drawHandlesIfActive: drawHandlesOnHover,\n };\n\n // Draw the handles\n drawHandles(context, eventData, data.handles, handleOptions);\n\n // Draw the textbox\n // Move the textbox slightly to the right and upwards\n // So that it sits beside the length tool handle\n const xOffset = 10;\n const textBoxAnchorPoints = handles => [\n handles.start,\n handles.end,\n handles.perpendicularStart,\n handles.perpendicularEnd,\n ];\n const textLines = getTextBoxText(data, rowPixelSpacing, colPixelSpacing);\n\n drawLinkedTextBox(\n context,\n element,\n textBox,\n textLines,\n data.handles,\n textBoxAnchorPoints,\n color,\n lineWidth,\n xOffset,\n true\n );\n });\n }\n}\n\nconst getTextBoxText = (data, rowPixelSpacing, colPixelSpacing) => {\n let suffix = ' mm';\n\n if (!rowPixelSpacing || !colPixelSpacing) {\n suffix = ' pixels';\n }\n\n const lengthText = ` L ${data.longestDiameter}${suffix}`;\n const widthText = ` W ${data.shortestDiameter}${suffix}`;\n\n const { labels } = data;\n\n if (labels && Array.isArray(labels)) {\n return [...labels, lengthText, widthText];\n }\n\n return [lengthText, widthText];\n};\n","let coordsData;\n\nfunction setCoords(eventData) {\n coordsData = eventData.currentPoints.canvas;\n}\n\nfunction getCoords() {\n return coordsData;\n}\n\nconst toolCoordinates = {\n setCoords,\n getCoords,\n};\n\nexport default toolCoordinates;\n","import getLineVector from './getLineVector';\n\n/**\n * Update the perpendicular line handles when the measurement is being created.\n * This method will make the perpendicular line intersect in the middle of the\n * long line and assume half the size of the long line.\n *\n * @param {*} eventData Data object associated with the event\n * @param {*} measurementData Data from current bidirectional tool measurement\n *\n * @returns {boolean} False in case the handle is not locked or true when moved\n */\nexport default function updatePerpendicularLineHandles(\n eventData,\n measurementData\n) {\n if (!measurementData.handles.perpendicularStart.locked) {\n return false;\n }\n\n let startX, startY, endX, endY;\n\n const { start, end } = measurementData.handles;\n const { columnPixelSpacing = 1, rowPixelSpacing = 1 } = eventData.image;\n\n if (start.x === end.x && start.y === end.y) {\n startX = start.x;\n startY = start.y;\n endX = end.x;\n endY = end.y;\n } else {\n // Mid point of long-axis line\n const mid = {\n x: (start.x + end.x) / 2,\n y: (start.y + end.y) / 2,\n };\n\n // Inclination of the perpendicular line\n const vector = getLineVector(\n columnPixelSpacing,\n rowPixelSpacing,\n start,\n end\n );\n\n const perpendicularLineLength = vector.length / 2;\n const rowMultiplier = perpendicularLineLength / (2 * rowPixelSpacing);\n const columnMultiplier = perpendicularLineLength / (2 * columnPixelSpacing);\n\n startX = mid.x + columnMultiplier * vector.y;\n startY = mid.y - rowMultiplier * vector.x;\n endX = mid.x - columnMultiplier * vector.y;\n endY = mid.y + rowMultiplier * vector.x;\n }\n\n measurementData.handles.perpendicularStart.x = startX;\n measurementData.handles.perpendicularStart.y = startY;\n measurementData.handles.perpendicularEnd.x = endX;\n measurementData.handles.perpendicularEnd.y = endY;\n\n return true;\n}\n","import external from './../../../externalModules.js';\nimport EVENTS from './../../../events.js';\nimport { moveNewHandle } from './../../../manipulators/index.js';\nimport anyHandlesOutsideImage from './../../../manipulators/anyHandlesOutsideImage.js';\nimport {\n addToolState,\n removeToolState,\n} from './../../../stateManagement/toolState.js';\nimport triggerEvent from '../../../util/triggerEvent.js';\nimport getActiveTool from '../../../util/getActiveTool';\nimport BaseAnnotationTool from '../../base/BaseAnnotationTool';\n\nexport default function(evt, interactionType) {\n const eventData = evt.detail;\n const { element, image, buttons } = eventData;\n const config = this.configuration;\n\n if (checkPixelSpacing(image)) {\n return;\n }\n\n const measurementData = this.createNewMeasurement(eventData);\n\n const doneCallback = () => {\n measurementData.active = false;\n external.cornerstone.updateImage(element);\n };\n\n // Associate this data with this imageId so we can render it and manipulate it\n addToolState(element, this.name, measurementData);\n external.cornerstone.updateImage(element);\n\n const timestamp = new Date().getTime();\n const { end, perpendicularStart } = measurementData.handles;\n\n moveNewHandle(\n eventData,\n this.name,\n measurementData,\n end,\n {},\n interactionType,\n () => {\n const { handles, longestDiameter, shortestDiameter } = measurementData;\n const hasHandlesOutside = anyHandlesOutsideImage(eventData, handles);\n const longestDiameterSize = parseFloat(longestDiameter) || 0;\n const shortestDiameterSize = parseFloat(shortestDiameter) || 0;\n const isTooSmal = longestDiameterSize < 1 || shortestDiameterSize < 1;\n const isTooFast = new Date().getTime() - timestamp < 150;\n\n if (hasHandlesOutside || isTooSmal || isTooFast) {\n // Delete the measurement\n measurementData.cancelled = true;\n removeToolState(element, this.name, measurementData);\n } else {\n // Set lesionMeasurementData Session\n config.getMeasurementLocationCallback(\n measurementData,\n eventData,\n doneCallback\n );\n }\n\n // Perpendicular line is not connected to long-line\n perpendicularStart.locked = false;\n\n measurementData.invalidated = true;\n\n external.cornerstone.updateImage(element);\n\n const activeTool = getActiveTool(element, buttons, interactionType);\n\n if (activeTool instanceof BaseAnnotationTool) {\n activeTool.updateCachedStats(image, element, measurementData);\n }\n\n const modifiedEventData = {\n toolType: this.name,\n element,\n measurementData,\n };\n\n triggerEvent(element, EVENTS.MEASUREMENT_MODIFIED, modifiedEventData);\n triggerEvent(element, EVENTS.MEASUREMENT_COMPLETED, modifiedEventData);\n }\n );\n}\n\nconst checkPixelSpacing = image => {\n const imagePlane = external.cornerstone.metaData.get(\n 'imagePlaneModule',\n image.imageId\n );\n let rowPixelSpacing = image.rowPixelSpacing;\n let colPixelSpacing = image.columnPixelSpacing;\n\n if (imagePlane) {\n rowPixelSpacing =\n imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing;\n colPixelSpacing =\n imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing;\n }\n\n // LT-29 Disable Target Measurements when pixel spacing is not available\n return !rowPixelSpacing || !colPixelSpacing;\n};\n","import external from './../../../externalModules.js';\nimport toolCoordinates from './../../../stateManagement/toolCoordinates.js';\nimport getHandleNearImagePoint from './../../../manipulators/getHandleNearImagePoint.js';\nimport { getToolState } from './../../../stateManagement/toolState.js';\n\n// Replaces the cornerstoneTools.handleActivator function by skiping the active handle comparison\nconst handleActivator = (\n element,\n handles,\n canvasPoint,\n distanceThreshold = 6\n) => {\n const nearbyHandle = getHandleNearImagePoint(\n element,\n handles,\n canvasPoint,\n distanceThreshold\n );\n\n let handleActivatorChanged = false;\n\n Object.keys(handles).forEach(handleKey => {\n if (handleKey === 'textBox') {\n return;\n }\n const handle = handles[handleKey];\n const newActiveState = handle === nearbyHandle;\n\n if (handle.active !== newActiveState) {\n handleActivatorChanged = true;\n }\n\n handle.active = newActiveState;\n });\n\n return handleActivatorChanged;\n};\n\n// MouseMoveCallback is used to hide handles when mouse is away\nexport default function(event) {\n const eventData = event.detail;\n const { element } = eventData;\n\n toolCoordinates.setCoords(eventData);\n\n // If we have no tool data for this element, do nothing\n const toolData = getToolState(element, this.name);\n\n if (!toolData) {\n return;\n }\n\n // We have tool data, search through all data and see if we can activate a handle\n let imageNeedsUpdate = false;\n\n for (let i = 0; i < toolData.data.length; i++) {\n // Get the cursor position in canvas coordinates\n const coords = eventData.currentPoints.canvas;\n\n const data = toolData.data[i];\n const handleActivatorChanged = handleActivator(\n element,\n data.handles,\n coords\n );\n\n Object.keys(data.handles).forEach(handleKey => {\n if (handleKey === 'textBox') {\n return;\n }\n const handle = data.handles[handleKey];\n\n handle.hover = handle.active;\n });\n\n if (handleActivatorChanged) {\n imageNeedsUpdate = true;\n }\n\n const nearTool = this.pointNearTool(element, data, coords, 'mouse');\n const nearToolAndInactive = nearTool && !data.active;\n const notNearToolAndActive = !nearTool && data.active;\n\n if (nearToolAndInactive || notNearToolAndActive) {\n data.active = !data.active;\n imageNeedsUpdate = true;\n }\n }\n\n // Handle activation status changed, redraw the image\n if (imageNeedsUpdate === true) {\n external.cornerstone.updateImage(element);\n }\n}\n","export default function(evt, toolData, handle, interactionType = 'mouse') {\n if (interactionType === 'touch') {\n this.handleSelectedTouchCallback(evt);\n } else {\n this.handleSelectedMouseCallback(evt);\n }\n}\n","/**\n * Return the distance between 2 points considering the pixel spacing\n *\n * @param {number} columnPixelSpacing Width that a pixel represents in mm\n * @param {number} rowPixelSpacing Height that a pixel represents in mm\n * @param {*} startPoint Start point of the line\n * @param {*} endPoint End point of the line\n *\n * @returns {number} Distance between the 2 given points considering the pixel spacing\n */\nexport default function getDistanceWithPixelSpacing(\n columnPixelSpacing,\n rowPixelSpacing,\n startPoint,\n endPoint\n) {\n const calcX = (startPoint.x - endPoint.x) / rowPixelSpacing;\n const calcY = (startPoint.y - endPoint.y) / columnPixelSpacing;\n\n return Math.sqrt(calcX * calcX + calcY * calcY);\n}\n","import external from '../../../../externalModules.js';\nimport getDistanceWithPixelSpacing from '../utils/getDistanceWithPixelSpacing.js';\n\nfunction createLine(startPoint, endPoint) {\n return {\n start: startPoint,\n end: endPoint,\n };\n}\n\n/**\n * Extract and group the base data to be used on bidirectional tool lines\n * moving.\n *\n * @param {*} measurementData Data from current bidirectional tool measurement\n * @param {*} eventData Data object associated with the event\n * @param {*} fixedPoint Point that is not being moved in line\n *\n * @returns {*} Grouped that needed for lines moving\n */\nexport default function getBaseData(measurementData, eventData, fixedPoint) {\n const { lineSegment } = external.cornerstoneMath;\n const {\n start,\n end,\n perpendicularStart,\n perpendicularEnd,\n } = measurementData.handles;\n const { columnPixelSpacing = 1, rowPixelSpacing = 1 } = eventData.image;\n\n const longLine = createLine(start, end);\n const perpendicularLine = createLine(perpendicularStart, perpendicularEnd);\n const intersection = lineSegment.intersectLine(longLine, perpendicularLine);\n\n const distanceToFixed = getDistanceWithPixelSpacing(\n columnPixelSpacing,\n rowPixelSpacing,\n fixedPoint,\n intersection\n );\n\n return {\n columnPixelSpacing, // Width that a pixel represents in mm\n rowPixelSpacing, // Height that a pixel represents in mm\n start, // Start point of the long line\n end, // End point of the long line\n perpendicularStart, // Start point of the perpendicular line\n perpendicularEnd, // End point of the perpendicular line\n longLine, // Long line object containing the start and end points\n intersection, // Intersection point between long and perpendicular lines\n distanceToFixed, // Distance from intersection to the fixed point\n fixedPoint, // Opposite point from the handle that is being moved\n };\n}\n","import getDistanceWithPixelSpacing from '../../utils/getDistanceWithPixelSpacing.js';\nimport getBaseData from '../getBaseData.js';\nimport updatePerpendicularLine from './updatePerpendicularLine.js';\n\n/**\n * Move the long line updating the perpendicular line handles position.\n *\n * @param {*} proposedPoint Point that was moved in bidirectional tool\n * @param {*} measurementData Data from current bidirectional tool measurement\n * @param {*} eventData Data object associated with the event\n * @param {*} fixedPoint Point that is not being moved in long line\n *\n * @returns {boolean} True if perpendicular handles were updated, false if not\n */\nexport default function moveLongLine(\n proposedPoint,\n measurementData,\n eventData,\n fixedPoint\n) {\n const baseData = getBaseData(measurementData, eventData, fixedPoint);\n const { columnPixelSpacing, rowPixelSpacing, distanceToFixed } = baseData;\n\n // Calculate the length of the new line, considering the proposed point\n const newLineLength = getDistanceWithPixelSpacing(\n columnPixelSpacing,\n rowPixelSpacing,\n fixedPoint,\n proposedPoint\n );\n\n // Stop here if the handle tries to move before the intersection point\n if (newLineLength <= distanceToFixed) {\n return false;\n }\n\n // Calculate the new intersection point\n const distanceRatio = distanceToFixed / newLineLength;\n const newIntersection = {\n x: fixedPoint.x + (proposedPoint.x - fixedPoint.x) * distanceRatio,\n y: fixedPoint.y + (proposedPoint.y - fixedPoint.y) * distanceRatio,\n };\n\n // Calculate and the new position of the perpendicular handles\n const newLine = updatePerpendicularLine(baseData, newIntersection);\n\n // Update the perpendicular line handles\n measurementData.handles.perpendicularStart.x = newLine.start.x;\n measurementData.handles.perpendicularStart.y = newLine.start.y;\n measurementData.handles.perpendicularEnd.x = newLine.end.x;\n measurementData.handles.perpendicularEnd.y = newLine.end.y;\n\n return true;\n}\n","import getLineVector from '../../utils/getLineVector';\nimport getDistanceWithPixelSpacing from '../../utils/getDistanceWithPixelSpacing';\n\n/**\n * Returns the updated line object that will be used to change the position of\n * the perpendicular line handles.\n *\n * @param {*} baseData Base data for bidirectional line moving\n * @param {*} mid Middle point considering the proposed point\n *\n * @returns {*} Returns a line object with the updated handles position\n */\nexport default function updatePerpendicularLine(baseData, mid) {\n const {\n columnPixelSpacing,\n rowPixelSpacing,\n start,\n perpendicularStart,\n perpendicularEnd,\n intersection,\n fixedPoint,\n } = baseData;\n\n // Get the original distance from perpendicular start handle to intersection\n const distancePS = getDistanceWithPixelSpacing(\n columnPixelSpacing,\n rowPixelSpacing,\n perpendicularStart,\n intersection\n );\n\n // Get the original distance from perpendicular end handle to intersection\n const distancePE = getDistanceWithPixelSpacing(\n columnPixelSpacing,\n rowPixelSpacing,\n perpendicularEnd,\n intersection\n );\n\n // Inclination of the perpendicular line\n const vector = getLineVector(\n columnPixelSpacing,\n rowPixelSpacing,\n fixedPoint,\n mid\n );\n\n // Define the multiplier\n const multiplier = fixedPoint === start ? 1 : -1;\n const rowMultiplier = multiplier * rowPixelSpacing;\n const columnMultiplier = multiplier * columnPixelSpacing;\n\n // Calculate and return the new position of the perpendicular handles\n return {\n start: {\n x: mid.x + vector.y * distancePS * rowMultiplier,\n y: mid.y + vector.x * distancePS * columnMultiplier * -1,\n },\n end: {\n x: mid.x + vector.y * distancePE * rowMultiplier * -1,\n y: mid.y + vector.x * distancePE * columnMultiplier,\n },\n };\n}\n","/**\n * Returns true if the end point is the point that is not being moved in the\n * perpendicular line.\n *\n * @param {*} fixedPoint Point that is not being moved in perpendicular line\n * @param {*} perpendicularEnd The end point of the perpencular line\n *\n * @returns {boolean} Returns true if the fixed point is the end point\n */\nexport default function isPerpendicularEndFixed(fixedPoint, perpendicularEnd) {\n return fixedPoint === perpendicularEnd;\n}\n","import isPerpendicularEndFixed from './isPerpendicularEndFixed.js';\n\n/**\n * Return the direction multiplier based on the perpendicular fixed point and\n * the end point.\n *\n * @param {*} fixedPoint Point that is not being moved in perpendicular line\n * @param {*} perpendicularEnd The end point of the perpencular line\n *\n * @returns {number} Returns -1 if end point is not being moved or 1 if it is\n */\nexport default function getDirectionMultiplier(fixedPoint, perpendicularEnd) {\n return isPerpendicularEndFixed(fixedPoint, perpendicularEnd) ? -1 : 1;\n}\n","import getDirectionMultiplier from './getDirectionMultiplier';\nimport getMovingPoint from './getMovingPoint';\n\n/**\n * Returns the updated line object that will be used to change the position of\n * the perpendicular line handles.\n *\n * @param {*} baseData Base data for bidirectional line moving\n * @param {*} mid Middle point considering the proposed point\n * @param {*} helperLine Line based on proposed point that crosses long line\n * @param {*} vector Vector with the perpendicular line inclination\n *\n * @returns {*} Returns a line object with the updated handles position\n */\nexport default function updatePerpendicularLine(\n baseData,\n mid,\n helperLine,\n vector\n) {\n const {\n columnPixelSpacing,\n rowPixelSpacing,\n fixedPoint,\n perpendicularStart,\n perpendicularEnd,\n distanceToFixed,\n } = baseData;\n\n // Get the multiplier\n const multiplier =\n getDirectionMultiplier(fixedPoint, perpendicularEnd) * distanceToFixed;\n\n // Define the moving point\n const movingPoint = getMovingPoint(\n fixedPoint,\n perpendicularStart,\n perpendicularEnd\n );\n\n // Get the object keys for moving and fixed points\n const isMovingStart = movingPoint === perpendicularStart;\n const movingKey = isMovingStart ? 'start' : 'end';\n const fixedKey = isMovingStart ? 'end' : 'start';\n\n // Calculate and return the new position of the perpendicular handles\n return {\n [movingKey]: {\n x: helperLine.start.x,\n y: helperLine.start.y,\n },\n [fixedKey]: {\n x: mid.x + vector.y * rowPixelSpacing * multiplier,\n y: mid.y + vector.x * columnPixelSpacing * multiplier * -1,\n },\n };\n}\n","import isPerpendicularEndFixed from './isPerpendicularEndFixed.js';\n\n/**\n * Utility function to return the point that is the opposite of the fixed\n * point (the point not being moved in the bidirectional tool's perpendicular\n * line).\n *\n * @param {*} fixedPoint Point that is not being moved in perpendicular line\n * @param {*} perpendicularStart The start point of the perpencular line\n * @param {*} perpendicularEnd The end point of the perpencular line\n *\n * @returns {*} Point that is being moved in perpendicular line\n */\nexport default function getMovingPoint(\n fixedPoint,\n perpendicularStart,\n perpendicularEnd\n) {\n if (isPerpendicularEndFixed(fixedPoint, perpendicularEnd)) {\n return perpendicularStart;\n }\n\n return perpendicularEnd;\n}\n","import external from './../../../../../externalModules.js';\nimport getLineVector from '../../utils/getLineVector.js';\nimport getBaseData from '../getBaseData.js';\nimport lineHasLength from './lineHasLength.js';\nimport getHelperLine from './getHelperLine.js';\nimport updatePerpendicularLine from './updatePerpendicularLine.js';\n\n/**\n * Move the perpendicular line updating the opposite handle position.\n *\n * @param {*} proposedPoint Point that was moved in bidirectional tool\n * @param {*} measurementData Data from current bidirectional tool measurement\n * @param {*} eventData Data object associated with the event\n * @param {*} fixedPoint Point that is not being moved in long line\n *\n * @returns {boolean} True if perpendicular handles were updated, false if not\n */\nexport default function movePerpendicularLine(\n proposedPoint,\n measurementData,\n eventData,\n fixedPoint\n) {\n const { lineSegment } = external.cornerstoneMath;\n const baseData = getBaseData(measurementData, eventData, fixedPoint);\n const {\n columnPixelSpacing,\n rowPixelSpacing,\n start,\n longLine,\n intersection,\n } = baseData;\n\n // Stop here if the long line has no length\n if (!lineHasLength(columnPixelSpacing, rowPixelSpacing, longLine)) {\n return false;\n }\n\n // Inclination of the perpendicular line\n const vector = getLineVector(\n columnPixelSpacing,\n rowPixelSpacing,\n start,\n intersection\n );\n\n // Get a helper line to calculate the intersection\n const helperLine = getHelperLine(baseData, proposedPoint, vector);\n\n // Find the new intersection in the long line\n const newIntersection = lineSegment.intersectLine(longLine, helperLine);\n\n // Stop the flow here if there's no intersection point between lines\n if (!newIntersection) {\n return false;\n }\n\n // Calculate and the new position of the perpendicular handles\n const newLine = updatePerpendicularLine(\n baseData,\n newIntersection,\n helperLine,\n vector\n );\n\n // Change the position of the perpendicular line handles\n measurementData.handles.perpendicularStart.x = newLine.start.x;\n measurementData.handles.perpendicularStart.y = newLine.start.y;\n measurementData.handles.perpendicularEnd.x = newLine.end.x;\n measurementData.handles.perpendicularEnd.y = newLine.end.y;\n\n return true;\n}\n","import getDistanceWithPixelSpacing from '../../utils/getDistanceWithPixelSpacing';\n\n/**\n * Returns true if the given line object has its length different from zero,\n * considering the column and row pixel spacings.\n *\n * @param {number} columnPixelSpacing Width that a pixel represents in mm\n * @param {number} rowPixelSpacing Height that a pixel represents in mm\n * @param {*} line Line object that will have its length calculated\n *\n * @returns {boolean} Returns true if line has any length\n */\nexport default function lineHasLength(\n columnPixelSpacing,\n rowPixelSpacing,\n line\n) {\n const lineLength = getDistanceWithPixelSpacing(\n columnPixelSpacing,\n rowPixelSpacing,\n line.start,\n line.end\n );\n\n return lineLength !== 0;\n}\n","import getDirectionMultiplier from './getDirectionMultiplier';\n\n/**\n * Creates a helper line with the same inclination as the perpendicular line\n * but having the start point as the proposed point.\n * This line will start in the proposed point and will grow in the long line\n * direction trying to cross it to enable finding the intersection point\n * between the long line and this new perpendicular line.\n *\n * @param {*} baseData Base data for bidirectional line moving\n * @param {*} proposedPoint Point that was moved in bidirectional tool\n * @param {*} vector Vector with the perpendicular line inclination\n *\n * @returns {*} Returns the helper line containing the start and end points\n */\nexport default function getHelperLine(baseData, proposedPoint, vector) {\n const {\n columnPixelSpacing,\n rowPixelSpacing,\n perpendicularEnd,\n fixedPoint,\n } = baseData;\n\n // Create a helper line to find the intesection point in the long line\n const highNumber = Number.MAX_SAFE_INTEGER;\n\n // Get the multiplier\n const multiplier =\n getDirectionMultiplier(fixedPoint, perpendicularEnd) * highNumber;\n\n return {\n start: proposedPoint,\n end: {\n x: proposedPoint.x + vector.y * rowPixelSpacing * multiplier,\n y: proposedPoint.y + vector.x * columnPixelSpacing * multiplier * -1,\n },\n };\n}\n","import external from './../../../../externalModules.js';\nimport moveLongLine from './moveLongLine/moveLongLine.js';\nimport movePerpendicularLine from './movePerpendicularLine/movePerpendicularLine.js';\n\n// Sets position of handles(start, end, perpendicularStart, perpendicularEnd)\nexport default function(handle, eventData, data, distanceFromTool) {\n let movedPoint;\n let outOfBounds;\n let result;\n let intersection;\n let d1;\n let d2;\n\n const longLine = {};\n const perpendicularLine = {};\n const proposedPoint = {\n x: eventData.currentPoints.image.x + distanceFromTool.x,\n y: eventData.currentPoints.image.y + distanceFromTool.y,\n };\n\n if (handle.index === 0) {\n // If long-axis start point is moved\n result = moveLongLine(proposedPoint, data, eventData, data.handles.end);\n if (result) {\n handle.x = proposedPoint.x;\n handle.y = proposedPoint.y;\n } else {\n eventData.currentPoints.image.x = handle.x;\n eventData.currentPoints.image.y = handle.y;\n }\n } else if (handle.index === 1) {\n // If long-axis end point is moved\n result = moveLongLine(proposedPoint, data, eventData, data.handles.start);\n if (result) {\n handle.x = proposedPoint.x;\n handle.y = proposedPoint.y;\n } else {\n eventData.currentPoints.image.x = handle.x;\n eventData.currentPoints.image.y = handle.y;\n }\n } else if (handle.index === 2) {\n outOfBounds = false;\n // If perpendicular start point is moved\n longLine.start = {\n x: data.handles.start.x,\n y: data.handles.start.y,\n };\n longLine.end = {\n x: data.handles.end.x,\n y: data.handles.end.y,\n };\n\n perpendicularLine.start = {\n x: data.handles.perpendicularEnd.x,\n y: data.handles.perpendicularEnd.y,\n };\n perpendicularLine.end = {\n x: proposedPoint.x,\n y: proposedPoint.y,\n };\n\n intersection = external.cornerstoneMath.lineSegment.intersectLine(\n longLine,\n perpendicularLine\n );\n if (!intersection) {\n perpendicularLine.end = {\n x: data.handles.perpendicularStart.x,\n y: data.handles.perpendicularStart.y,\n };\n\n intersection = external.cornerstoneMath.lineSegment.intersectLine(\n longLine,\n perpendicularLine\n );\n\n d1 = external.cornerstoneMath.point.distance(\n intersection,\n data.handles.start\n );\n d2 = external.cornerstoneMath.point.distance(\n intersection,\n data.handles.end\n );\n\n if (!intersection || d1 < 3 || d2 < 3) {\n outOfBounds = true;\n }\n }\n\n movedPoint = false;\n\n if (!outOfBounds) {\n movedPoint = movePerpendicularLine(\n proposedPoint,\n data,\n eventData,\n data.handles.perpendicularEnd\n );\n\n if (!movedPoint) {\n eventData.currentPoints.image.x = data.handles.perpendicularStart.x;\n eventData.currentPoints.image.y = data.handles.perpendicularStart.y;\n }\n }\n } else if (handle.index === 3) {\n outOfBounds = false;\n\n // If perpendicular end point is moved\n longLine.start = {\n x: data.handles.start.x,\n y: data.handles.start.y,\n };\n longLine.end = {\n x: data.handles.end.x,\n y: data.handles.end.y,\n };\n\n perpendicularLine.start = {\n x: data.handles.perpendicularStart.x,\n y: data.handles.perpendicularStart.y,\n };\n perpendicularLine.end = {\n x: proposedPoint.x,\n y: proposedPoint.y,\n };\n\n intersection = external.cornerstoneMath.lineSegment.intersectLine(\n longLine,\n perpendicularLine\n );\n if (!intersection) {\n perpendicularLine.end = {\n x: data.handles.perpendicularEnd.x,\n y: data.handles.perpendicularEnd.y,\n };\n\n intersection = external.cornerstoneMath.lineSegment.intersectLine(\n longLine,\n perpendicularLine\n );\n\n d1 = external.cornerstoneMath.point.distance(\n intersection,\n data.handles.start\n );\n d2 = external.cornerstoneMath.point.distance(\n intersection,\n data.handles.end\n );\n\n if (!intersection || d1 < 3 || d2 < 3) {\n outOfBounds = true;\n }\n }\n\n movedPoint = false;\n\n if (!outOfBounds) {\n movedPoint = movePerpendicularLine(\n proposedPoint,\n data,\n eventData,\n data.handles.perpendicularStart\n );\n\n if (!movedPoint) {\n eventData.currentPoints.image.x = data.handles.perpendicularEnd.x;\n eventData.currentPoints.image.y = data.handles.perpendicularEnd.y;\n }\n }\n }\n}\n","const swapAttribute = (a, b, attribute) => {\n const originalA = a[attribute];\n const originalB = b[attribute];\n\n a[attribute] = originalB;\n b[attribute] = originalA;\n};\n\nconst swapHandles = (a, b) => {\n swapAttribute(a, b, 'x');\n swapAttribute(a, b, 'y');\n swapAttribute(a, b, 'moving');\n swapAttribute(a, b, 'hover');\n swapAttribute(a, b, 'active');\n swapAttribute(a, b, 'selected');\n};\n\nexport default function invertHandles(eventData, measurementData, handle) {\n const { rowPixelSpacing, columnPixelSpacing } = eventData.image;\n const { handles } = measurementData;\n const { start, end, perpendicularStart, perpendicularEnd } = handles;\n\n // Calculate the long axis length\n const dx = (start.x - end.x) * (columnPixelSpacing || 1);\n const dy = (start.y - end.y) * (rowPixelSpacing || 1);\n const length = Math.sqrt(dx * dx + dy * dy);\n\n // Calculate the short axis length\n const wx =\n (perpendicularStart.x - perpendicularEnd.x) * (columnPixelSpacing || 1);\n const wy =\n (perpendicularStart.y - perpendicularEnd.y) * (rowPixelSpacing || 1);\n const width = Math.sqrt(wx * wx + wy * wy) || 0;\n\n if (width > length) {\n swapHandles(start, end);\n swapHandles(start, perpendicularStart);\n swapHandles(end, perpendicularEnd);\n\n return Object.values(handles).find(h => h.moving === true);\n }\n\n return handle;\n}\n","/* jshint -W083 */\nimport external from './../../../externalModules.js';\nimport { state } from '../../../store/index.js';\nimport EVENTS from './../../../events.js';\nimport {\n removeToolState,\n getToolState,\n} from './../../../stateManagement/toolState.js';\nimport anyHandlesOutsideImage from './../../../manipulators/anyHandlesOutsideImage.js';\nimport getHandleNearImagePoint from './../../../manipulators/getHandleNearImagePoint.js';\nimport { moveAllHandles } from './../../../manipulators/index.js';\nimport moveHandle from './moveHandle/moveHandle.js';\nimport invertHandles from './invertHandles.js';\nimport { setToolCursor, hideToolCursor } from '../../../store/setToolCursor.js';\n\nexport default function(evt) {\n const eventData = evt.detail;\n\n const { element } = eventData;\n let data;\n\n const distanceThreshold = state.clickProximity;\n\n const handleDoneMove = handle => {\n data.invalidated = true;\n if (anyHandlesOutsideImage(eventData, data.handles)) {\n // Delete the measurement\n removeToolState(element, this.name, data);\n }\n\n // Update the handles to keep selected state\n if (handle) {\n handle.moving = false;\n handle.selected = true;\n }\n\n setToolCursor(this.element, this.svgCursor);\n\n external.cornerstone.updateImage(element);\n element.addEventListener(EVENTS.MOUSE_MOVE, this._moveCallback);\n element.addEventListener(EVENTS.TOUCH_START, this._moveCallback);\n };\n\n const coords = eventData.startPoints.canvas;\n const toolData = getToolState(evt.currentTarget, this.name);\n\n if (!toolData) {\n return;\n }\n\n // Now check to see if there is a handle we can move\n for (let i = 0; i < toolData.data.length; i++) {\n data = toolData.data[i];\n const handleParams = [element, data.handles, coords, distanceThreshold];\n let handle = getHandleNearImagePoint(...handleParams);\n\n if (handle) {\n element.removeEventListener(EVENTS.MOUSE_MOVE, this._moveCallback);\n element.removeEventListener(EVENTS.TOUCH_START, this._moveCallback);\n\n data.active = true;\n\n unselectAllHandles(data.handles);\n handle.moving = true;\n\n // Invert handles if needed\n handle = invertHandles(eventData, data, handle);\n\n /* Hide the cursor to improve precision while resizing the line or set to move\n if dragging text box\n */\n if (!handle.hasBoundingBox) {\n hideToolCursor(this.element);\n }\n\n moveHandle(eventData, this.name, data, handle, () =>\n handleDoneMove(handle)\n );\n\n preventPropagation(evt);\n\n return true;\n }\n }\n\n const getDoneMovingCallback = handles => () => {\n setHandlesMovingState(handles, false);\n handleDoneMove();\n };\n\n for (let i = 0; i < toolData.data.length; i++) {\n data = toolData.data[i];\n if (this.pointNearTool(element, data, coords, 'mouse')) {\n element.removeEventListener(EVENTS.MOUSE_MOVE, this._moveCallback);\n element.removeEventListener(EVENTS.TOUCH_START, this._moveCallback);\n data.active = true;\n\n unselectAllHandles(data.handles);\n setHandlesMovingState(data.handles, true);\n\n const doneMovingCallback = getDoneMovingCallback(data.handles);\n\n moveAllHandles(\n eventData,\n this.name,\n data,\n null,\n {\n deleteIfHandleOutsideImage: true,\n preventHandleOutsideImage: false,\n },\n 'mouse',\n doneMovingCallback\n );\n\n preventPropagation(evt);\n\n return true;\n }\n }\n}\n\n// Clear the selected state for the given handles object\nconst unselectAllHandles = handles => {\n let imageNeedsUpdate = false;\n\n Object.keys(handles).forEach(handleKey => {\n if (handleKey === 'textBox') {\n return;\n }\n handles[handleKey].selected = false;\n imageNeedsUpdate = handles[handleKey].active || imageNeedsUpdate;\n handles[handleKey].active = false;\n });\n\n return imageNeedsUpdate;\n};\n\nconst setHandlesMovingState = (handles, state) => {\n Object.keys(handles).forEach(handleKey => {\n if (handleKey === 'textBox') {\n return;\n }\n handles[handleKey].moving = state;\n });\n};\n\nconst preventPropagation = evt => {\n evt.stopImmediatePropagation();\n evt.stopPropagation();\n evt.preventDefault();\n};\n","import external from './../../../../externalModules.js';\nimport { state } from '../../../../store/index.js';\nimport EVENTS from './../../../../events.js';\nimport setHandlesPosition from './setHandlesPosition.js';\nimport getActiveTool from '../../../../util/getActiveTool';\nimport BaseAnnotationTool from '../../../base/BaseAnnotationTool';\n\nexport default function(\n mouseEventData,\n toolType,\n data,\n handle,\n doneMovingCallback,\n preventHandleOutsideImage\n) {\n const { element, image, buttons } = mouseEventData;\n const distanceFromTool = {\n x: handle.x - mouseEventData.currentPoints.image.x,\n y: handle.y - mouseEventData.currentPoints.image.y,\n };\n\n const _dragCallback = event => {\n const eventData = event.detail;\n\n handle.hasMoved = true;\n\n if (handle.index === undefined || handle.index === null) {\n handle.x = eventData.currentPoints.image.x + distanceFromTool.x;\n handle.y = eventData.currentPoints.image.y + distanceFromTool.y;\n } else {\n setHandlesPosition(handle, eventData, data, distanceFromTool);\n }\n\n if (preventHandleOutsideImage) {\n handle.x = Math.max(handle.x, 0);\n handle.x = Math.min(handle.x, eventData.image.width);\n\n handle.y = Math.max(handle.y, 0);\n handle.y = Math.min(handle.y, eventData.image.height);\n }\n\n data.invalidated = true;\n\n external.cornerstone.updateImage(element);\n\n const activeTool = getActiveTool(element, buttons, 'mouse');\n\n if (activeTool instanceof BaseAnnotationTool) {\n activeTool.updateCachedStats(image, element, data);\n }\n\n const modifiedEventData = {\n toolType,\n element,\n measurementData: data,\n };\n\n external.cornerstone.triggerEvent(\n element,\n EVENTS.MEASUREMENT_MODIFIED,\n modifiedEventData\n );\n };\n\n handle.active = true;\n state.isToolLocked = true;\n\n element.addEventListener(EVENTS.MOUSE_DRAG, _dragCallback);\n element.addEventListener(EVENTS.TOUCH_DRAG, _dragCallback);\n\n const currentImage = external.cornerstone.getImage(element);\n const imageRenderedHandler = () => {\n const newImage = external.cornerstone.getImage(element);\n\n // Check if the rendered image changed during measurement modifying and stop it if so\n if (newImage.imageId !== currentImage.imageId) {\n interactionEndCallback();\n }\n };\n\n // Bind the event listener for image rendering\n element.addEventListener(\n external.cornerstone.EVENTS.IMAGE_RENDERED,\n imageRenderedHandler\n );\n\n const interactionEndCallback = () => {\n handle.active = false;\n state.isToolLocked = false;\n\n element.removeEventListener(\n external.cornerstone.EVENTS.IMAGE_RENDERED,\n imageRenderedHandler\n );\n\n element.removeEventListener(EVENTS.MOUSE_DRAG, _dragCallback);\n element.removeEventListener(EVENTS.MOUSE_UP, interactionEndCallback);\n element.removeEventListener(EVENTS.MOUSE_CLICK, interactionEndCallback);\n\n element.removeEventListener(EVENTS.TOUCH_DRAG, _dragCallback);\n element.removeEventListener(EVENTS.TOUCH_DRAG_END, interactionEndCallback);\n element.removeEventListener(EVENTS.TAP, interactionEndCallback);\n\n external.cornerstone.updateImage(element);\n\n if (typeof doneMovingCallback === 'function') {\n doneMovingCallback();\n }\n };\n\n element.addEventListener(EVENTS.MOUSE_UP, interactionEndCallback);\n element.addEventListener(EVENTS.MOUSE_CLICK, interactionEndCallback);\n\n element.addEventListener(EVENTS.TOUCH_DRAG_END, interactionEndCallback);\n element.addEventListener(EVENTS.TAP, interactionEndCallback);\n}\n","import external from './../../../../externalModules.js';\nimport { state } from '../../../../store/index.js';\nimport EVENTS from './../../../../events.js';\nimport setHandlesPosition from './setHandlesPosition.js';\nimport getActiveTool from '../../../../util/getActiveTool';\nimport BaseAnnotationTool from '../../../base/BaseAnnotationTool';\n\nconst touchEndEvents = [\n EVENTS.TOUCH_END,\n EVENTS.TOUCH_DRAG_END,\n EVENTS.TOUCH_PINCH,\n EVENTS.TOUCH_PRESS,\n EVENTS.TAP,\n];\n\nexport default function(\n mouseEventData,\n toolType,\n data,\n handle,\n doneMovingCallback,\n preventHandleOutsideImage\n) {\n const { element, image, buttons } = mouseEventData;\n const distanceFromTool = {\n x: handle.x - mouseEventData.currentPoints.image.x,\n y: handle.y - mouseEventData.currentPoints.image.y,\n };\n\n const touchDragCallback = event => {\n const eventData = event.detail;\n\n handle.hasMoved = true;\n\n if (handle.index === undefined || handle.index === null) {\n handle.x = eventData.currentPoints.image.x + distanceFromTool.x;\n handle.y = eventData.currentPoints.image.y + distanceFromTool.y;\n } else {\n setHandlesPosition(handle, eventData, data, distanceFromTool);\n }\n\n if (preventHandleOutsideImage) {\n handle.x = Math.max(handle.x, 0);\n handle.x = Math.min(handle.x, eventData.image.width);\n\n handle.y = Math.max(handle.y, 0);\n handle.y = Math.min(handle.y, eventData.image.height);\n }\n\n data.invalidated = true;\n\n external.cornerstone.updateImage(element);\n\n const activeTool = getActiveTool(element, buttons, 'touch');\n\n if (activeTool instanceof BaseAnnotationTool) {\n activeTool.updateCachedStats(image, element, data);\n }\n\n const modifiedEventData = {\n toolType,\n element,\n measurementData: data,\n };\n\n external.cornerstone.triggerEvent(\n element,\n EVENTS.MEASUREMENT_MODIFIED,\n modifiedEventData\n );\n };\n\n handle.active = true;\n state.isToolLocked = true;\n\n element.addEventListener(EVENTS.TOUCH_DRAG, touchDragCallback);\n\n const touchEndCallback = () => {\n handle.active = false;\n state.isToolLocked = false;\n\n element.removeEventListener(EVENTS.TOUCH_DRAG, touchDragCallback);\n touchEndEvents.forEach(eventType => {\n element.removeEventListener(eventType, touchEndCallback);\n });\n\n external.cornerstone.updateImage(element);\n\n if (typeof doneMovingCallback === 'function') {\n doneMovingCallback();\n }\n };\n\n touchEndEvents.forEach(eventType => {\n element.addEventListener(eventType, touchEndCallback);\n });\n}\n","/* jshint -W083 */\nimport external from './../../../externalModules.js';\nimport { state } from '../../../store/index.js';\nimport EVENTS from './../../../events.js';\nimport {\n removeToolState,\n getToolState,\n} from './../../../stateManagement/toolState.js';\nimport anyHandlesOutsideImage from './../../../manipulators/anyHandlesOutsideImage.js';\nimport getHandleNearImagePoint from './../../../manipulators/getHandleNearImagePoint.js';\nimport { moveAllHandles } from './../../../manipulators/index.js';\nimport touchMoveHandle from './moveHandle/touchMoveHandle.js';\n\nexport default function(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n let data;\n\n const distanceThreshold = state.touchProximity;\n\n const handleDoneMove = handle => {\n data.invalidated = true;\n if (anyHandlesOutsideImage(eventData, data.handles)) {\n // Delete the measurement\n removeToolState(element, this.name, data);\n }\n\n // Update the handles to keep selected state\n if (handle) {\n handle.moving = false;\n handle.selected = true;\n }\n\n external.cornerstone.updateImage(element);\n element.addEventListener(EVENTS.TOUCH_DRAG, this._moveCallback);\n };\n\n const coords = eventData.startPoints.canvas;\n const toolData = getToolState(evt.currentTarget, this.name);\n\n if (!toolData) {\n return;\n }\n\n // Now check to see if there is a handle we can move\n for (let i = 0; i < toolData.data.length; i++) {\n data = toolData.data[i];\n const handleParams = [element, data.handles, coords, distanceThreshold];\n const handle = getHandleNearImagePoint(...handleParams);\n\n if (handle) {\n element.removeEventListener(EVENTS.TOUCH_DRAG, this._moveCallback);\n\n data.active = true;\n\n unselectAllHandles(data.handles);\n handle.moving = true;\n touchMoveHandle(eventData, this.name, data, handle, () =>\n handleDoneMove(handle)\n );\n preventPropagation(evt);\n\n return true;\n }\n }\n\n const getDoneMovingCallback = handles => () => {\n setHandlesMovingState(handles, false);\n handleDoneMove();\n };\n\n for (let i = 0; i < toolData.data.length; i++) {\n data = toolData.data[i];\n if (this.pointNearTool(element, data, coords, 'touch')) {\n element.removeEventListener(EVENTS.TOUCH_DRAG, this._moveCallback);\n data.active = true;\n\n unselectAllHandles(data.handles);\n setHandlesMovingState(data.handles, true);\n\n const doneMovingCallback = getDoneMovingCallback(data.handles);\n\n moveAllHandles(\n eventData,\n this.name,\n data,\n null,\n {\n deleteIfHandleOutsideImage: true,\n preventHandleOutsideImage: false,\n },\n 'touch',\n doneMovingCallback\n );\n\n preventPropagation(evt);\n\n return true;\n }\n }\n}\n\n// Clear the selected state for the given handles object\nconst unselectAllHandles = handles => {\n let imageNeedsUpdate = false;\n\n Object.keys(handles).forEach(handleKey => {\n if (handleKey === 'textBox') {\n return;\n }\n handles[handleKey].selected = false;\n imageNeedsUpdate = handles[handleKey].active || imageNeedsUpdate;\n handles[handleKey].active = false;\n });\n\n return imageNeedsUpdate;\n};\n\nconst setHandlesMovingState = (handles, state) => {\n Object.keys(handles).forEach(handleKey => {\n if (handleKey === 'textBox') {\n return;\n }\n handles[handleKey].moving = state;\n });\n};\n\nconst preventPropagation = evt => {\n evt.stopImmediatePropagation();\n evt.stopPropagation();\n evt.preventDefault();\n};\n","import BaseAnnotationTool from '../base/BaseAnnotationTool.js';\n\nimport createNewMeasurement from './bidirectionalTool/createNewMeasurement.js';\nimport pointNearTool from './bidirectionalTool/pointNearTool.js';\nimport renderToolData from './bidirectionalTool/renderToolData.js';\nimport addNewMeasurement from './bidirectionalTool/addNewMeasurement.js';\nimport _moveCallback from './bidirectionalTool/mouseMoveCallback.js';\nimport handleSelectedCallback from './bidirectionalTool/handleSelectedCallback.js';\nimport handleSelectedMouseCallback from './bidirectionalTool/handleSelectedMouseCallback.js';\nimport handleSelectedTouchCallback from './bidirectionalTool/handleSelectedTouchCallback.js';\nimport { bidirectionalCursor } from '../cursors/index.js';\nimport throttle from '../../util/throttle';\nimport getPixelSpacing from '../../util/getPixelSpacing';\nimport calculateLongestAndShortestDiameters from './bidirectionalTool/utils/calculateLongestAndShortestDiameters';\n\nconst emptyLocationCallback = (measurementData, eventData, doneCallback) =>\n doneCallback();\n\n/**\n * @public\n * @class BidirectionalTool\n * @memberof Tools.Annotation\n * @classdesc Create and position an annotation that measures the\n * length and width of a region.\n * @extends Tools.Base.BaseAnnotationTool\n */\n\nexport default class BidirectionalTool extends BaseAnnotationTool {\n constructor(props) {\n const defaultProps = {\n name: 'Bidirectional',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {\n changeMeasurementLocationCallback: emptyLocationCallback,\n getMeasurementLocationCallback: emptyLocationCallback,\n textBox: '',\n shadow: '',\n drawHandlesOnHover: true,\n additionalData: [],\n },\n svgCursor: bidirectionalCursor,\n };\n\n super(props, defaultProps);\n\n this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);\n\n this.createNewMeasurement = createNewMeasurement.bind(this);\n this.pointNearTool = pointNearTool.bind(this);\n this.renderToolData = renderToolData.bind(this);\n this.addNewMeasurement = addNewMeasurement.bind(this);\n this._moveCallback = _moveCallback.bind(this);\n\n this.handleSelectedCallback = handleSelectedCallback.bind(this);\n this.handleSelectedMouseCallback = handleSelectedMouseCallback.bind(this);\n this.handleSelectedTouchCallback = handleSelectedTouchCallback.bind(this);\n }\n\n updateCachedStats(image, element, data) {\n const pixelSpacing = getPixelSpacing(image);\n const {\n longestDiameter,\n shortestDiameter,\n } = calculateLongestAndShortestDiameters(data, pixelSpacing);\n\n // Set measurement text to show lesion table\n data.longestDiameter = longestDiameter;\n data.shortestDiameter = shortestDiameter;\n data.invalidated = false;\n }\n}\n","/**\n * Calculates longest and shortest diameters using measurement handles and pixelSpacing\n * @param {Object} measurementData\n * @param {Object} pixelSpacing pixelSpacing\n *\n *@returns {Object} longestDiameter and shortestDiameter\n */\nexport default function calculateLongestAndShortestDiameters(\n measurementData,\n pixelSpacing\n) {\n const { rowPixelSpacing, colPixelSpacing } = pixelSpacing;\n const {\n start,\n end,\n perpendicularStart,\n perpendicularEnd,\n } = measurementData.handles;\n\n // Calculate the long axis length\n const dx = (start.x - end.x) * (colPixelSpacing || 1);\n const dy = (start.y - end.y) * (rowPixelSpacing || 1);\n let length = Math.sqrt(dx * dx + dy * dy);\n\n // Calculate the short axis length\n const wx =\n (perpendicularStart.x - perpendicularEnd.x) * (colPixelSpacing || 1);\n const wy =\n (perpendicularStart.y - perpendicularEnd.y) * (rowPixelSpacing || 1);\n let width = Math.sqrt(wx * wx + wy * wy);\n\n if (!width) {\n width = 0;\n }\n\n // Length is always longer than width\n if (width > length) {\n const tempW = width;\n const tempL = length;\n\n length = tempW;\n width = tempL;\n }\n\n return {\n longestDiameter: length.toFixed(1),\n shortestDiameter: width.toFixed(1),\n };\n}\n","import external from '../externalModules.js';\n\n/**\n * Calculates a Standardized Uptake Value.\n * @export @public @method\n * @name calculateSUV\n *\n * @param {Object} image The image.\n * @param {number} storedPixelValue The raw pixel value.\n * @param {bool} [skipRescale=fale]\n * @returns {number} The SUV.\n */\nexport default function(image, storedPixelValue, skipRescale = false) {\n const cornerstone = external.cornerstone;\n const patientStudyModule = cornerstone.metaData.get(\n 'patientStudyModule',\n image.imageId\n );\n const seriesModule = cornerstone.metaData.get(\n 'generalSeriesModule',\n image.imageId\n );\n\n if (!patientStudyModule || !seriesModule) {\n return;\n }\n\n const modality = seriesModule.modality;\n\n // Image must be PET\n if (modality !== 'PT') {\n return;\n }\n\n const modalityPixelValue = skipRescale\n ? storedPixelValue\n : storedPixelValue * image.slope + image.intercept;\n\n const patientWeight = patientStudyModule.patientWeight; // In kg\n\n if (!patientWeight) {\n return;\n }\n\n const petSequenceModule = cornerstone.metaData.get(\n 'petIsotopeModule',\n image.imageId\n );\n\n if (!petSequenceModule) {\n return;\n }\n\n const radiopharmaceuticalInfo = petSequenceModule.radiopharmaceuticalInfo;\n const startTime = radiopharmaceuticalInfo.radiopharmaceuticalStartTime;\n const totalDose = radiopharmaceuticalInfo.radionuclideTotalDose;\n const halfLife = radiopharmaceuticalInfo.radionuclideHalfLife;\n const seriesAcquisitionTime = seriesModule.seriesTime;\n\n if (!startTime || !totalDose || !halfLife || !seriesAcquisitionTime) {\n return;\n }\n\n const acquisitionTimeInSeconds =\n fracToDec(seriesAcquisitionTime.fractionalSeconds || 0) +\n seriesAcquisitionTime.seconds +\n seriesAcquisitionTime.minutes * 60 +\n seriesAcquisitionTime.hours * 60 * 60;\n const injectionStartTimeInSeconds =\n fracToDec(startTime.fractionalSeconds) +\n startTime.seconds +\n startTime.minutes * 60 +\n startTime.hours * 60 * 60;\n const durationInSeconds =\n acquisitionTimeInSeconds - injectionStartTimeInSeconds;\n const correctedDose =\n totalDose * Math.exp((-durationInSeconds * Math.log(2)) / halfLife);\n const suv = ((modalityPixelValue * patientWeight) / correctedDose) * 1000;\n\n return suv;\n}\n\n/**\n * Returns a decimal value given a fractional value.\n * @private\n * @method\n * @name fracToDec\n *\n * @param {number} fractionalValue The value to convert.\n * @returns {number} The value converted to decimal.\n */\nfunction fracToDec(fractionalValue) {\n return parseFloat(`.${fractionalValue}`);\n}\n","/**\n * Returns true if a point is within an ellipse\n * @export @public @method\n * @name pointInEllipse\n *\n * @param {Object} ellipse Object defining the ellipse.\n * @param {Object} location The location of the point.\n * @returns {boolean} True if the point is within the ellipse.\n */\nexport default function(ellipse, location) {\n const xRadius = ellipse.width / 2;\n const yRadius = ellipse.height / 2;\n\n if (xRadius <= 0.0 || yRadius <= 0.0) {\n return false;\n }\n\n const center = {\n x: ellipse.left + xRadius,\n y: ellipse.top + yRadius,\n };\n\n /* This is a more general form of the circle equation\n *\n * X^2/a^2 + Y^2/b^2 <= 1\n */\n\n const normalized = {\n x: location.x - center.x,\n y: location.y - center.y,\n };\n\n const inEllipse =\n (normalized.x * normalized.x) / (xRadius * xRadius) +\n (normalized.y * normalized.y) / (yRadius * yRadius) <=\n 1.0;\n\n return inEllipse;\n}\n","import pointInEllipse from './pointInEllipse.js';\n\n/**\n * Calculates the statistics of an elliptical region of interest.\n *\n * @private\n * @function calculateEllipseStatistics\n *\n * @param {number[]} sp - Array of the image data's pixel values.\n * @param {Object} ellipse - { top, left, height, width } - An object describing the ellipse.\n * @returns {Object} { count, mean, variance, stdDev, min, max }\n */\nexport default function(sp, ellipse) {\n let sum = 0;\n let sumSquared = 0;\n let count = 0;\n let index = 0;\n let min = null;\n let max = null;\n\n for (let y = ellipse.top; y < ellipse.top + ellipse.height; y++) {\n for (let x = ellipse.left; x < ellipse.left + ellipse.width; x++) {\n const point = {\n x,\n y,\n };\n\n if (pointInEllipse(ellipse, point)) {\n if (min === null) {\n min = sp[index];\n max = sp[index];\n }\n\n sum += sp[index];\n sumSquared += sp[index] * sp[index];\n min = Math.min(min, sp[index]);\n max = Math.max(max, sp[index]);\n count++;\n }\n\n index++;\n }\n }\n\n if (count === 0) {\n return {\n count,\n mean: 0.0,\n variance: 0.0,\n stdDev: 0.0,\n min: 0.0,\n max: 0.0,\n };\n }\n\n const mean = sum / count;\n const variance = sumSquared / count - mean * mean;\n\n return {\n count,\n mean,\n variance,\n stdDev: Math.sqrt(variance),\n min,\n max,\n };\n}\n","import calculateEllipseStatistics from './calculateEllipseStatistics.js';\nimport pointInEllipse from './pointInEllipse.js';\n\n// Named\nexport { calculateEllipseStatistics, pointInEllipse };\n\n// Default\nexport default {\n calculateEllipseStatistics,\n pointInEllipse,\n};\n","/**\n * Determine the coordinates that will place the textbox to the right of the\n * annotation, taking rotation, hflip, and vflip into account.\n *\n * @param {Object} viewport - The object that stores rotation, hflip, and vflip.\n * @param {Object} handles - The handles of the annotation.\n * @returns {Object} - The coordinates for default placement of the textbox\n */\nexport default function getROITextBoxCoords(viewport, handles) {\n const corners = _determineCorners(handles);\n const centerX = (corners.left.x + corners.right.x) / 2;\n const centerY = (corners.top.y + corners.bottom.y) / 2;\n const textBox = {};\n\n if (viewport.rotation >= 0 && viewport.rotation < 90) {\n textBox.x = viewport.hflip ? corners.left.x : corners.right.x;\n textBox.y = centerY;\n }\n if (viewport.rotation >= 90 && viewport.rotation < 180) {\n textBox.x = centerX;\n textBox.y = viewport.vflip ? corners.bottom.y : corners.top.y;\n }\n if (viewport.rotation >= 180 && viewport.rotation < 270) {\n textBox.x = viewport.hflip ? corners.right.x : corners.left.x;\n textBox.y = centerY;\n }\n if (viewport.rotation >= 270 && viewport.rotation < 360) {\n textBox.x = centerX;\n textBox.y = viewport.vflip ? corners.top.y : corners.bottom.y;\n }\n\n return textBox;\n}\n\n/**\n * Determine the handles that have the min/max x and y values.\n *\n * @param {Object} handles - The handles of the annotation.\n * @returns {Object} - The top, left, bottom, and right handles\n */\nfunction _determineCorners(handles) {\n const handlesLeftToRight = [handles.start, handles.end].sort(_compareX);\n const handlesTopToBottom = [handles.start, handles.end].sort(_compareY);\n const left = handlesLeftToRight[0];\n const right = handlesLeftToRight[handlesLeftToRight.length - 1];\n const top = handlesTopToBottom[0];\n const bottom = handlesTopToBottom[handlesTopToBottom.length - 1];\n\n return {\n top,\n left,\n bottom,\n right,\n };\n\n function _compareX(a, b) {\n return a.x < b.x ? -1 : 1;\n }\n function _compareY(a, b) {\n return a.y < b.y ? -1 : 1;\n }\n}\n","/**\n * Converts a number to a string with comma separators.\n * http://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript\n * @export @public @method\n * @name numbersWithCommas\n *\n * @param {number} x The number to convert.\n * @returns {string} The pretty-printed number as a string.\n */\nexport default function(x) {\n const parts = x.toString().split('.');\n\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n\n return parts.join('.');\n}\n","import external from './../../externalModules.js';\nimport BaseAnnotationTool from '../base/BaseAnnotationTool.js';\n\n// State\nimport { getToolState } from './../../stateManagement/toolState.js';\nimport toolStyle from './../../stateManagement/toolStyle.js';\nimport toolColors from './../../stateManagement/toolColors.js';\n\n// Drawing\nimport {\n getNewContext,\n draw,\n setShadow,\n drawCircle,\n drawHandles,\n drawLinkedTextBox,\n} from './../../drawing/index.js';\n\n// Util\nimport calculateSUV from './../../util/calculateSUV.js';\nimport { calculateEllipseStatistics } from './../../util/ellipse/index.js';\nimport getROITextBoxCoords from '../../util/getROITextBoxCoords.js';\nimport numbersWithCommas from './../../util/numbersWithCommas.js';\nimport throttle from './../../util/throttle.js';\nimport { getLogger } from '../../util/logger.js';\nimport getPixelSpacing from '../../util/getPixelSpacing';\nimport { circleRoiCursor } from '../cursors/index.js';\nimport getCircleCoords from '../../util/getCircleCoords';\n\nconst logger = getLogger('tools:annotation:CircleRoiTool');\n\n/**\n * @public\n * @class CircleRoiTool\n * @memberof Tools.Annotation\n * @classdesc Tool for drawing circular regions of interest, and measuring\n * the statistics of the enclosed pixels.\n * @extends Tools.Base.BaseAnnotationTool\n */\nexport default class CircleRoiTool extends BaseAnnotationTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'CircleRoi',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: circleRoiCursor,\n };\n\n super(props, defaultProps);\n\n this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);\n }\n\n createNewMeasurement(eventData) {\n const goodEventData =\n eventData && eventData.currentPoints && eventData.currentPoints.image;\n\n if (!goodEventData) {\n logger.error(\n `required eventData not supplied to tool ${this.name}'s createNewMeasurement`\n );\n\n return;\n }\n\n return {\n visible: true,\n active: true,\n color: undefined,\n invalidated: true,\n handles: {\n start: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: false,\n },\n end: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: true,\n },\n initialRotation: eventData.viewport.rotation,\n textBox: {\n active: false,\n hasMoved: false,\n movesIndependently: false,\n drawnIndependently: true,\n allowedOutsideImage: true,\n hasBoundingBox: true,\n },\n },\n };\n }\n\n pointNearTool(element, data, coords, interactionType) {\n const hasStartAndEndHandles =\n data && data.handles && data.handles.start && data.handles.end;\n\n const getDistance = external.cornerstoneMath.point.distance;\n\n if (!hasStartAndEndHandles) {\n logger.warn(\n `invalid parameters supplied to tool ${this.name}'s pointNearTool`\n );\n }\n\n if (!hasStartAndEndHandles || data.visible === false) {\n return false;\n }\n\n const distance = interactionType === 'mouse' ? 15 : 25;\n\n const startCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.start\n );\n\n const endCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.end\n );\n\n // StartCanvas is the center of the circle\n const distanceFromCenter = getDistance(startCanvas, coords);\n\n // Getting radius of circle annotation in canvas\n const radius = getDistance(startCanvas, endCanvas);\n\n // Checking if point is near the tool by comparing its distance from the center of the circle\n return (\n distanceFromCenter > radius - distance / 2 &&\n distanceFromCenter < radius + distance / 2\n );\n }\n\n updateCachedStats(image, element, data) {\n const seriesModule =\n external.cornerstone.metaData.get('generalSeriesModule', image.imageId) ||\n {};\n const modality = seriesModule.modality;\n const pixelSpacing = getPixelSpacing(image);\n\n const stats = _calculateStats(\n image,\n element,\n data.handles,\n modality,\n pixelSpacing\n );\n\n data.cachedStats = stats;\n data.invalidated = false;\n }\n\n renderToolData(evt) {\n const toolData = getToolState(evt.currentTarget, this.name);\n\n if (!toolData) {\n return;\n }\n\n const getDistance = external.cornerstoneMath.point.distance;\n const eventData = evt.detail;\n const { image, element, canvasContext } = eventData;\n const lineWidth = toolStyle.getToolWidth();\n const { handleRadius, drawHandlesOnHover } = this.configuration;\n const newContext = getNewContext(canvasContext.canvas);\n const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);\n\n // Meta\n const seriesModule =\n external.cornerstone.metaData.get('generalSeriesModule', image.imageId) ||\n {};\n\n // Pixel Spacing\n const modality = seriesModule.modality;\n const hasPixelSpacing = rowPixelSpacing && colPixelSpacing;\n\n draw(newContext, context => {\n // If we have tool data for this element, iterate over each set and draw it\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n // Configure\n const color = toolColors.getColorIfActive(data);\n const handleOptions = {\n color,\n handleRadius,\n drawHandlesIfActive: drawHandlesOnHover,\n };\n\n setShadow(context, this.configuration);\n\n const startCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.start\n );\n\n const endCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.end\n );\n\n // Calculating the radius where startCanvas is the center of the circle to be drawn\n const radius = getDistance(startCanvas, endCanvas);\n\n // Draw Circle\n drawCircle(\n context,\n element,\n data.handles.start,\n radius,\n {\n color,\n },\n 'pixel'\n );\n\n drawHandles(context, eventData, data.handles, handleOptions);\n\n // Update textbox stats\n if (data.invalidated === true) {\n if (data.cachedStats) {\n this.throttledUpdateCachedStats(image, element, data);\n } else {\n this.updateCachedStats(image, element, data);\n }\n }\n\n // Default to textbox on right side of ROI\n if (!data.handles.textBox.hasMoved) {\n const defaultCoords = getROITextBoxCoords(\n eventData.viewport,\n data.handles\n );\n\n Object.assign(data.handles.textBox, defaultCoords);\n }\n\n const textBoxAnchorPoints = handles =>\n _findTextBoxAnchorPoints(handles.start, handles.end);\n\n const textBoxContent = _createTextBoxContent(\n context,\n image.color,\n data.cachedStats,\n modality,\n hasPixelSpacing,\n this.configuration\n );\n\n data.unit = _getUnit(modality, this.configuration.showHounsfieldUnits);\n\n drawLinkedTextBox(\n context,\n element,\n data.handles.textBox,\n textBoxContent,\n data.handles,\n textBoxAnchorPoints,\n color,\n lineWidth,\n 10,\n true\n );\n }\n });\n }\n}\n\n/**\n *\n *\n * @param {*} startHandle\n * @param {*} endHandle\n * @returns {Array.<{x: number, y: number}>}\n */\nfunction _findTextBoxAnchorPoints(startHandle, endHandle) {\n const { left, top, width, height } = getCircleCoords(startHandle, endHandle);\n\n return [\n {\n // Top middle point of ellipse\n x: left + width / 2,\n y: top,\n },\n {\n // Left middle point of ellipse\n x: left,\n y: top + height / 2,\n },\n {\n // Bottom middle point of ellipse\n x: left + width / 2,\n y: top + height,\n },\n {\n // Right middle point of ellipse\n x: left + width,\n y: top + height / 2,\n },\n ];\n}\n\nfunction _getUnit(modality, showHounsfieldUnits) {\n return modality === 'CT' && showHounsfieldUnits !== false ? 'HU' : '';\n}\n\n/**\n *\n *\n * @param {*} context\n * @param {*} isColorImage\n * @param {*} { area, mean, stdDev, min, max, meanStdDevSUV }\n * @param {*} modality\n * @param {*} hasPixelSpacing\n * @param {*} [options={}] - { showMinMax, showHounsfieldUnits }\n * @returns {string[]}\n */\nfunction _createTextBoxContent(\n context,\n isColorImage,\n { area, mean, stdDev, min, max, meanStdDevSUV } = {},\n modality,\n hasPixelSpacing,\n options = {}\n) {\n const showMinMax = options.showMinMax || false;\n const textLines = [];\n\n // Don't display mean/standardDev for color images\n const otherLines = [];\n\n if (!isColorImage) {\n const hasStandardUptakeValues = meanStdDevSUV && meanStdDevSUV.mean !== 0;\n const unit = _getUnit(modality, options.showHounsfieldUnits);\n\n let meanString = `Mean: ${numbersWithCommas(mean.toFixed(2))} ${unit}`;\n const stdDevString = `Std Dev: ${numbersWithCommas(\n stdDev.toFixed(2)\n )} ${unit}`;\n\n // If this image has SUV values to display, concatenate them to the text line\n if (hasStandardUptakeValues) {\n const SUVtext = ' SUV: ';\n\n const meanSuvString = `${SUVtext}${numbersWithCommas(\n meanStdDevSUV.mean.toFixed(2)\n )}`;\n const stdDevSuvString = `${SUVtext}${numbersWithCommas(\n meanStdDevSUV.stdDev.toFixed(2)\n )}`;\n\n const targetStringLength = Math.floor(\n context.measureText(`${stdDevString} `).width\n );\n\n while (context.measureText(meanString).width < targetStringLength) {\n meanString += ' ';\n }\n\n otherLines.push(`${meanString}${meanSuvString}`);\n otherLines.push(`${stdDevString} ${stdDevSuvString}`);\n } else {\n otherLines.push(`${meanString} ${stdDevString}`);\n }\n\n if (showMinMax) {\n let minString = `Min: ${min} ${unit}`;\n const maxString = `Max: ${max} ${unit}`;\n const targetStringLength = hasStandardUptakeValues\n ? Math.floor(context.measureText(`${stdDevString} `).width)\n : Math.floor(context.measureText(`${meanString} `).width);\n\n while (context.measureText(minString).width < targetStringLength) {\n minString += ' ';\n }\n\n otherLines.push(`${minString}${maxString}`);\n }\n }\n\n textLines.push(_formatArea(area, hasPixelSpacing));\n otherLines.forEach(x => textLines.push(x));\n\n return textLines;\n}\n\n/**\n *\n *\n * @param {*} area\n * @param {*} hasPixelSpacing\n * @returns {string} The formatted label for showing area\n */\nfunction _formatArea(area, hasPixelSpacing) {\n // This uses Char code 178 for a superscript 2\n const suffix = hasPixelSpacing\n ? ` mm${String.fromCharCode(178)}`\n : ` px${String.fromCharCode(178)}`;\n\n return `Area: ${numbersWithCommas(area.toFixed(2))}${suffix}`;\n}\n\n/**\n *\n *\n * @param {*} image\n * @param {*} element\n * @param {*} handles\n * @param {*} modality\n * @param {*} pixelSpacing\n * @returns {Object} The Stats object\n */\nfunction _calculateStats(image, element, handles, modality, pixelSpacing) {\n // Retrieve the bounds of the ellipse in image coordinates\n const circleCoordinates = getCircleCoords(handles.start, handles.end);\n\n // Retrieve the array of pixels that the ellipse bounds cover\n const pixels = external.cornerstone.getPixels(\n element,\n circleCoordinates.left,\n circleCoordinates.top,\n circleCoordinates.width,\n circleCoordinates.height\n );\n\n // Calculate the mean & standard deviation from the pixels and the ellipse details.\n const ellipseMeanStdDev = calculateEllipseStatistics(\n pixels,\n circleCoordinates\n );\n\n let meanStdDevSUV;\n\n if (modality === 'PT') {\n meanStdDevSUV = {\n mean: calculateSUV(image, ellipseMeanStdDev.mean, true) || 0,\n stdDev: calculateSUV(image, ellipseMeanStdDev.stdDev, true) || 0,\n };\n }\n\n const area =\n Math.PI *\n ((circleCoordinates.width * (pixelSpacing.colPixelSpacing || 1)) / 2) *\n ((circleCoordinates.height * (pixelSpacing.rowPixelSpacing || 1)) / 2);\n\n return {\n area: area || 0,\n count: ellipseMeanStdDev.count || 0,\n mean: ellipseMeanStdDev.mean || 0,\n variance: ellipseMeanStdDev.variance || 0,\n stdDev: ellipseMeanStdDev.stdDev || 0,\n min: ellipseMeanStdDev.min || 0,\n max: ellipseMeanStdDev.max || 0,\n meanStdDevSUV,\n };\n}\n","import external from './../../externalModules.js';\nimport BaseAnnotationTool from '../base/BaseAnnotationTool.js';\n// State\nimport textStyle from './../../stateManagement/textStyle.js';\nimport {\n addToolState,\n getToolState,\n} from './../../stateManagement/toolState.js';\nimport toolStyle from './../../stateManagement/toolStyle.js';\nimport toolColors from './../../stateManagement/toolColors.js';\n// Manipulators\nimport { moveNewHandle } from './../../manipulators/index.js';\n// Drawing\nimport {\n getNewContext,\n draw,\n setShadow,\n drawLine,\n} from './../../drawing/index.js';\nimport drawHandles from './../../drawing/drawHandles.js';\nimport drawLinkedTextBox from './../../drawing/drawLinkedTextBox.js';\nimport lineSegDistance from './../../util/lineSegDistance.js';\nimport roundToDecimal from './../../util/roundToDecimal.js';\nimport EVENTS from './../../events.js';\nimport { cobbAngleCursor } from '../cursors/index.js';\nimport triggerEvent from '../../util/triggerEvent.js';\nimport throttle from '../../util/throttle';\nimport getPixelSpacing from '../../util/getPixelSpacing';\n\n/**\n * @public\n * @class CobbAngleTool\n * @memberof Tools.Annotation\n * @classdesc Tool for measuring the angle between two straight lines.\n * @extends Tools.Base.BaseAnnotationTool\n */\nexport default class CobbAngleTool extends BaseAnnotationTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'CobbAngle',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: cobbAngleCursor,\n };\n\n super(props, defaultProps);\n\n this.hasIncomplete = false;\n\n this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);\n }\n\n createNewMeasurement(eventData) {\n // Create the measurement data for this tool with the end handle activated\n this.hasIncomplete = true;\n\n return {\n visible: true,\n active: true,\n color: undefined,\n invalidated: true,\n complete: false,\n value: '',\n handles: {\n start: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: false,\n },\n end: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: true,\n },\n start2: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: false,\n drawnIndependently: true,\n },\n end2: {\n x: eventData.currentPoints.image.x + 1,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: false,\n drawnIndependently: true,\n },\n textBox: {\n active: false,\n hasMoved: false,\n movesIndependently: false,\n drawnIndependently: true,\n allowedOutsideImage: true,\n hasBoundingBox: true,\n },\n },\n };\n }\n\n /**\n *\n *\n * @param {*} element\n * @param {*} data\n * @param {*} coords\n * @returns {Boolean}\n */\n pointNearTool(element, data, coords) {\n if (data.visible === false) {\n return false;\n }\n\n if (this.hasIncomplete) {\n return false;\n }\n\n return (\n lineSegDistance(element, data.handles.start, data.handles.end, coords) <\n 25 ||\n lineSegDistance(element, data.handles.start2, data.handles.end2, coords) <\n 25\n );\n }\n\n updateCachedStats(image, element, data) {\n const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);\n\n const dx1 =\n (Math.ceil(data.handles.start.x) - Math.ceil(data.handles.end.x)) *\n colPixelSpacing;\n const dy1 =\n (Math.ceil(data.handles.start.y) - Math.ceil(data.handles.end.y)) *\n rowPixelSpacing;\n const dx2 =\n (Math.ceil(data.handles.start2.x) - Math.ceil(data.handles.end2.x)) *\n colPixelSpacing;\n const dy2 =\n (Math.ceil(data.handles.start2.y) - Math.ceil(data.handles.end2.y)) *\n rowPixelSpacing;\n\n let angle = Math.acos(\n Math.abs(\n (dx1 * dx2 + dy1 * dy2) /\n (Math.sqrt(dx1 * dx1 + dy1 * dy1) * Math.sqrt(dx2 * dx2 + dy2 * dy2))\n )\n );\n\n angle *= 180 / Math.PI;\n\n data.rAngle = roundToDecimal(angle, 2);\n data.invalidated = false;\n }\n\n renderToolData(evt) {\n const eventData = evt.detail;\n const { handleRadius, drawHandlesOnHover } = this.configuration;\n // If we have no toolData for this element, return immediately as there is nothing to do\n const toolData = getToolState(evt.currentTarget, this.name);\n\n if (!toolData) {\n return;\n }\n\n // We have tool data for this element - iterate over each one and draw it\n const context = getNewContext(eventData.canvasContext.canvas);\n\n const lineWidth = toolStyle.getToolWidth();\n const font = textStyle.getFont();\n\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n draw(context, context => {\n setShadow(context, this.configuration);\n\n // Differentiate the color of activation tool\n const color = toolColors.getColorIfActive(data);\n\n drawLine(\n context,\n eventData.element,\n data.handles.start,\n data.handles.end,\n {\n color,\n }\n );\n\n if (data.complete) {\n drawLine(\n context,\n eventData.element,\n data.handles.start2,\n data.handles.end2,\n {\n color,\n }\n );\n }\n\n // Draw the handles\n const handleOptions = {\n color,\n handleRadius,\n drawHandlesIfActive: drawHandlesOnHover,\n };\n\n drawHandles(context, eventData, data.handles, handleOptions);\n\n // Draw the text\n context.fillStyle = color;\n\n const text = data.value;\n\n if (!data.handles.textBox.hasMoved) {\n const textCoords = {\n x: (data.handles.start.x + data.handles.end.x) / 2,\n y: (data.handles.start.y + data.handles.end.y) / 2 - 10,\n };\n\n context.font = font;\n data.handles.textBox.x = textCoords.x;\n data.handles.textBox.y = textCoords.y;\n }\n\n drawLinkedTextBox(\n context,\n eventData.element,\n data.handles.textBox,\n text,\n data.handles,\n textBoxAnchorPoints,\n color,\n lineWidth,\n 0,\n true\n );\n });\n }\n\n function textBoxAnchorPoints(handles) {\n return [handles.start, handles.start2, handles.end, handles.end2];\n }\n }\n\n getIncomplete(element) {\n const toolState = getToolState(element, this.name);\n\n if (toolState && Array.isArray(toolState.data)) {\n return toolState.data.find(({ complete }) => complete === false);\n }\n }\n\n addNewMeasurement(evt, interactionType) {\n evt.preventDefault();\n evt.stopPropagation();\n\n const eventData = evt.detail;\n\n let measurementData;\n let toMoveHandle;\n let doneMovingCallback;\n\n // Search for incomplete measurements\n const element = evt.detail.element;\n const pendingMeasurement = this.getIncomplete(element);\n\n if (pendingMeasurement) {\n measurementData = pendingMeasurement;\n measurementData.complete = true;\n measurementData.handles.start2 = {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n drawnIndependently: false,\n highlight: true,\n active: false,\n };\n measurementData.handles.end2 = {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n drawnIndependently: false,\n highlight: true,\n active: true,\n };\n toMoveHandle = measurementData.handles.end2;\n this.hasIncomplete = false;\n doneMovingCallback = () => {\n const eventType = EVENTS.MEASUREMENT_COMPLETED;\n const eventData = {\n toolType: this.name,\n element,\n measurementData,\n };\n\n triggerEvent(element, eventType, eventData);\n };\n } else {\n measurementData = this.createNewMeasurement(eventData);\n addToolState(element, this.name, measurementData);\n toMoveHandle = measurementData.handles.end;\n }\n\n // Associate this data with this imageId so we can render it and manipulate it\n external.cornerstone.updateImage(element);\n\n moveNewHandle(\n eventData,\n this.name,\n measurementData,\n toMoveHandle,\n this.options,\n interactionType,\n doneMovingCallback\n );\n }\n\n onMeasureModified(ev) {\n const { element } = ev.detail;\n const image = external.cornerstone.getEnabledElement(element).image;\n const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);\n\n if (ev.detail.toolName !== this.name) {\n return;\n }\n const data = ev.detail.measurementData;\n\n // Update textbox stats\n if (data.invalidated === true) {\n if (data.rAngle) {\n this.throttledUpdateCachedStats(image, element, data);\n } else {\n this.updateCachedStats(image, element, data);\n }\n }\n\n const { rAngle } = data;\n\n data.value = '';\n\n if (!Number.isNaN(rAngle)) {\n data.value = textBoxText(rAngle, rowPixelSpacing, colPixelSpacing);\n }\n\n function textBoxText(rAngle, rowPixelSpacing, colPixelSpacing) {\n const suffix = !rowPixelSpacing || !colPixelSpacing ? ' (isotropic)' : '';\n const str = '00B0'; // Degrees symbol\n\n return (\n rAngle.toString() + String.fromCharCode(parseInt(str, 16)) + suffix\n );\n }\n }\n\n activeCallback(element) {\n this.onMeasureModified = this.onMeasureModified.bind(this);\n element.addEventListener(\n EVENTS.MEASUREMENT_MODIFIED,\n this.onMeasureModified\n );\n }\n\n passiveCallback(element) {\n this.onMeasureModified = this.onMeasureModified.bind(this);\n element.addEventListener(\n EVENTS.MEASUREMENT_MODIFIED,\n this.onMeasureModified\n );\n }\n\n enabledCallback(element) {\n element.removeEventListener(\n EVENTS.MEASUREMENT_MODIFIED,\n this.onMeasureModified\n );\n }\n\n disabledCallback(element) {\n element.removeEventListener(\n EVENTS.MEASUREMENT_MODIFIED,\n this.onMeasureModified\n );\n }\n}\n","import external from './../../externalModules.js';\nimport BaseAnnotationTool from '../base/BaseAnnotationTool.js';\n\n// State\nimport { getToolState } from './../../stateManagement/toolState.js';\nimport toolStyle from './../../stateManagement/toolStyle.js';\nimport toolColors from './../../stateManagement/toolColors.js';\n\n// Drawing\nimport {\n getNewContext,\n draw,\n setShadow,\n drawEllipse,\n drawHandles,\n drawLinkedTextBox,\n} from './../../drawing/index.js';\n\n// Util\nimport calculateSUV from './../../util/calculateSUV.js';\nimport {\n pointInEllipse,\n calculateEllipseStatistics,\n} from './../../util/ellipse/index.js';\nimport getROITextBoxCoords from '../../util/getROITextBoxCoords.js';\nimport numbersWithCommas from './../../util/numbersWithCommas.js';\nimport throttle from './../../util/throttle.js';\nimport { ellipticalRoiCursor } from '../cursors/index.js';\nimport { getLogger } from '../../util/logger.js';\nimport getPixelSpacing from '../../util/getPixelSpacing';\n\nconst logger = getLogger('tools:annotation:EllipticalRoiTool');\n\n/**\n * @public\n * @class EllipticalRoiTool\n * @memberof Tools.Annotation\n * @classdesc Tool for drawing elliptical regions of interest, and measuring\n * the statistics of the enclosed pixels.\n * @extends Tools.Base.BaseAnnotationTool\n */\nexport default class EllipticalRoiTool extends BaseAnnotationTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'EllipticalRoi',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {\n // showMinMax: false,\n // showHounsfieldUnits: true,\n },\n svgCursor: ellipticalRoiCursor,\n };\n\n super(props, defaultProps);\n\n this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);\n }\n\n createNewMeasurement(eventData) {\n const goodEventData =\n eventData && eventData.currentPoints && eventData.currentPoints.image;\n\n if (!goodEventData) {\n logger.error(\n `required eventData not supplied to tool ${this.name}'s createNewMeasurement`\n );\n\n return;\n }\n\n return {\n visible: true,\n active: true,\n color: undefined,\n invalidated: true,\n handles: {\n start: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: false,\n },\n end: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: true,\n },\n initialRotation: eventData.viewport.rotation,\n textBox: {\n active: false,\n hasMoved: false,\n movesIndependently: false,\n drawnIndependently: true,\n allowedOutsideImage: true,\n hasBoundingBox: true,\n },\n },\n };\n }\n\n pointNearTool(element, data, coords, interactionType) {\n const hasStartAndEndHandles =\n data && data.handles && data.handles.start && data.handles.end;\n const validParameters = hasStartAndEndHandles;\n\n if (!validParameters) {\n logger.warn(\n `invalid parameters supplied to tool ${this.name}'s pointNearTool`\n );\n }\n\n if (!validParameters || data.visible === false) {\n return false;\n }\n\n const distance = interactionType === 'mouse' ? 15 : 25;\n const startCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.start\n );\n const endCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.end\n );\n\n const minorEllipse = {\n left: Math.min(startCanvas.x, endCanvas.x) + distance / 2,\n top: Math.min(startCanvas.y, endCanvas.y) + distance / 2,\n width: Math.abs(startCanvas.x - endCanvas.x) - distance,\n height: Math.abs(startCanvas.y - endCanvas.y) - distance,\n };\n\n const majorEllipse = {\n left: Math.min(startCanvas.x, endCanvas.x) - distance / 2,\n top: Math.min(startCanvas.y, endCanvas.y) - distance / 2,\n width: Math.abs(startCanvas.x - endCanvas.x) + distance,\n height: Math.abs(startCanvas.y - endCanvas.y) + distance,\n };\n\n const pointInMinorEllipse = pointInEllipse(minorEllipse, coords);\n const pointInMajorEllipse = pointInEllipse(majorEllipse, coords);\n\n if (pointInMajorEllipse && !pointInMinorEllipse) {\n return true;\n }\n\n return false;\n }\n\n updateCachedStats(image, element, data) {\n const seriesModule =\n external.cornerstone.metaData.get('generalSeriesModule', image.imageId) ||\n {};\n const modality = seriesModule.modality;\n const pixelSpacing = getPixelSpacing(image);\n\n const stats = _calculateStats(\n image,\n element,\n data.handles,\n modality,\n pixelSpacing\n );\n\n data.cachedStats = stats;\n data.invalidated = false;\n }\n\n renderToolData(evt) {\n const toolData = getToolState(evt.currentTarget, this.name);\n\n if (!toolData) {\n return;\n }\n\n const eventData = evt.detail;\n const { image, element } = eventData;\n const lineWidth = toolStyle.getToolWidth();\n const { handleRadius, drawHandlesOnHover } = this.configuration;\n const context = getNewContext(eventData.canvasContext.canvas);\n const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);\n\n // Meta\n const seriesModule =\n external.cornerstone.metaData.get('generalSeriesModule', image.imageId) ||\n {};\n\n // Pixel Spacing\n const modality = seriesModule.modality;\n const hasPixelSpacing = rowPixelSpacing && colPixelSpacing;\n\n draw(context, context => {\n // If we have tool data for this element - iterate over each set and draw it\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n // Configure\n const color = toolColors.getColorIfActive(data);\n const handleOptions = {\n color,\n handleRadius,\n drawHandlesIfActive: drawHandlesOnHover,\n };\n\n setShadow(context, this.configuration);\n\n // Draw\n drawEllipse(\n context,\n element,\n data.handles.start,\n data.handles.end,\n {\n color,\n },\n 'pixel',\n data.handles.initialRotation\n );\n drawHandles(context, eventData, data.handles, handleOptions);\n\n // Update textbox stats\n if (data.invalidated === true) {\n if (data.cachedStats) {\n this.throttledUpdateCachedStats(image, element, data);\n } else {\n this.updateCachedStats(image, element, data);\n }\n }\n\n // Default to textbox on right side of ROI\n if (!data.handles.textBox.hasMoved) {\n const defaultCoords = getROITextBoxCoords(\n eventData.viewport,\n data.handles\n );\n\n Object.assign(data.handles.textBox, defaultCoords);\n }\n\n const textBoxAnchorPoints = handles =>\n _findTextBoxAnchorPoints(handles.start, handles.end);\n const textBoxContent = _createTextBoxContent(\n context,\n image.color,\n data.cachedStats,\n modality,\n hasPixelSpacing,\n this.configuration\n );\n\n data.unit = _getUnit(modality, this.configuration.showHounsfieldUnits);\n\n drawLinkedTextBox(\n context,\n element,\n data.handles.textBox,\n textBoxContent,\n data.handles,\n textBoxAnchorPoints,\n color,\n lineWidth,\n 10,\n true\n );\n }\n });\n }\n}\n\n/**\n *\n *\n * @param {*} startHandle\n * @param {*} endHandle\n * @returns {Array.<{x: number, y: number}>}\n */\nfunction _findTextBoxAnchorPoints(startHandle, endHandle) {\n const { left, top, width, height } = _getEllipseImageCoordinates(\n startHandle,\n endHandle\n );\n\n return [\n {\n // Top middle point of ellipse\n x: left + width / 2,\n y: top,\n },\n {\n // Left middle point of ellipse\n x: left,\n y: top + height / 2,\n },\n {\n // Bottom middle point of ellipse\n x: left + width / 2,\n y: top + height,\n },\n {\n // Right middle point of ellipse\n x: left + width,\n y: top + height / 2,\n },\n ];\n}\n\nfunction _getUnit(modality, showHounsfieldUnits) {\n return modality === 'CT' && showHounsfieldUnits !== false ? 'HU' : '';\n}\n\n/**\n *\n *\n * @param {*} context\n * @param {*} isColorImage\n * @param {*} { area, mean, stdDev, min, max, meanStdDevSUV }\n * @param {*} modality\n * @param {*} hasPixelSpacing\n * @param {*} [options={}] - { showMinMax, showHounsfieldUnits }\n * @returns {string[]}\n */\nfunction _createTextBoxContent(\n context,\n isColorImage,\n { area, mean, stdDev, min, max, meanStdDevSUV } = {},\n modality,\n hasPixelSpacing,\n options = {}\n) {\n const showMinMax = options.showMinMax || false;\n const textLines = [];\n\n // Don't display mean/standardDev for color images\n const otherLines = [];\n\n if (!isColorImage) {\n const hasStandardUptakeValues = meanStdDevSUV && meanStdDevSUV.mean !== 0;\n const unit = _getUnit(modality, options.showHounsfieldUnits);\n\n let meanString = `Mean: ${numbersWithCommas(mean.toFixed(2))} ${unit}`;\n const stdDevString = `Std Dev: ${numbersWithCommas(\n stdDev.toFixed(2)\n )} ${unit}`;\n\n // If this image has SUV values to display, concatenate them to the text line\n if (hasStandardUptakeValues) {\n const SUVtext = ' SUV: ';\n\n const meanSuvString = `${SUVtext}${numbersWithCommas(\n meanStdDevSUV.mean.toFixed(2)\n )}`;\n const stdDevSuvString = `${SUVtext}${numbersWithCommas(\n meanStdDevSUV.stdDev.toFixed(2)\n )}`;\n\n const targetStringLength = Math.floor(\n context.measureText(`${stdDevString} `).width\n );\n\n while (context.measureText(meanString).width < targetStringLength) {\n meanString += ' ';\n }\n\n otherLines.push(`${meanString}${meanSuvString}`);\n otherLines.push(`${stdDevString} ${stdDevSuvString}`);\n } else {\n otherLines.push(`${meanString} ${stdDevString}`);\n }\n\n if (showMinMax) {\n let minString = `Min: ${min} ${unit}`;\n const maxString = `Max: ${max} ${unit}`;\n const targetStringLength = hasStandardUptakeValues\n ? Math.floor(context.measureText(`${stdDevString} `).width)\n : Math.floor(context.measureText(`${meanString} `).width);\n\n while (context.measureText(minString).width < targetStringLength) {\n minString += ' ';\n }\n\n otherLines.push(`${minString}${maxString}`);\n }\n }\n\n textLines.push(_formatArea(area, hasPixelSpacing));\n otherLines.forEach(x => textLines.push(x));\n\n return textLines;\n}\n\n/**\n *\n *\n * @param {*} area\n * @param {*} hasPixelSpacing\n * @returns {string} The formatted label for showing area\n */\nfunction _formatArea(area, hasPixelSpacing) {\n // This uses Char code 178 for a superscript 2\n const suffix = hasPixelSpacing\n ? ` mm${String.fromCharCode(178)}`\n : ` px${String.fromCharCode(178)}`;\n\n return `Area: ${numbersWithCommas(area.toFixed(2))}${suffix}`;\n}\n\n/**\n *\n *\n * @param {*} image\n * @param {*} element\n * @param {*} handles\n * @param {*} modality\n * @param {*} pixelSpacing\n * @returns {Object} The Stats object\n */\nfunction _calculateStats(image, element, handles, modality, pixelSpacing) {\n // Retrieve the bounds of the ellipse in image coordinates\n const ellipseCoordinates = _getEllipseImageCoordinates(\n handles.start,\n handles.end\n );\n\n // Retrieve the array of pixels that the ellipse bounds cover\n const pixels = external.cornerstone.getPixels(\n element,\n ellipseCoordinates.left,\n ellipseCoordinates.top,\n ellipseCoordinates.width,\n ellipseCoordinates.height\n );\n\n // Calculate the mean & standard deviation from the pixels and the ellipse details.\n const ellipseMeanStdDev = calculateEllipseStatistics(\n pixels,\n ellipseCoordinates\n );\n\n let meanStdDevSUV;\n\n if (modality === 'PT') {\n meanStdDevSUV = {\n mean: calculateSUV(image, ellipseMeanStdDev.mean, true) || 0,\n stdDev: calculateSUV(image, ellipseMeanStdDev.stdDev, true) || 0,\n };\n }\n\n // Calculate the image area from the ellipse dimensions and pixel spacing\n const area =\n Math.PI *\n ((ellipseCoordinates.width * (pixelSpacing.colPixelSpacing || 1)) / 2) *\n ((ellipseCoordinates.height * (pixelSpacing.rowPixelSpacing || 1)) / 2);\n\n return {\n area: area || 0,\n count: ellipseMeanStdDev.count || 0,\n mean: ellipseMeanStdDev.mean || 0,\n variance: ellipseMeanStdDev.variance || 0,\n stdDev: ellipseMeanStdDev.stdDev || 0,\n min: ellipseMeanStdDev.min || 0,\n max: ellipseMeanStdDev.max || 0,\n meanStdDevSUV,\n };\n}\n\n/**\n * Retrieve the bounds of the ellipse in image coordinates\n *\n * @param {*} startHandle\n * @param {*} endHandle\n * @returns {{ left: number, top: number, width: number, height: number }}\n */\nfunction _getEllipseImageCoordinates(startHandle, endHandle) {\n return {\n left: Math.round(Math.min(startHandle.x, endHandle.x)),\n top: Math.round(Math.min(startHandle.y, endHandle.y)),\n width: Math.round(Math.abs(startHandle.x - endHandle.x)),\n height: Math.round(Math.abs(startHandle.y - endHandle.y)),\n };\n}\n","/**\n * Calculates whether \"location\" is inside the polygon defined by dataHandles\n * by counting the number of times a ray originating from \"point\" crosses the\n * edges of the polygon. Odd === inside, Even === outside.\n * @export @public @method\n * @name pointInFreehand\n *\n * @param {Object} dataHandles Data object associated with the tool.\n * @param {Object} location The coordinates being queried.\n * @returns {boolean} True if the location is inside the polygon defined by dataHandles.\n */\nexport default function(dataHandles, location) {\n let inROI = false;\n\n // Cycle round pairs of points\n let j = dataHandles.length - 1; // The last vertex is the previous one to the first\n\n for (let i = 0; i < dataHandles.length; i++) {\n if (rayFromPointCrosssesLine(location, dataHandles[i], dataHandles[j])) {\n inROI = !inROI;\n }\n\n j = i; // Here j is previous vertex to i\n }\n\n return inROI;\n}\n\n/**\n * Returns true if the y-position yp is enclosed within y-positions y1 and y2.\n * @private\n * @method\n * @name isEnclosedY\n *\n * @param {number} yp The y position of point p.\n * @param {number} y1 The y position of point 1.\n * @param {number} y2 The y position of point 2.\n * @returns {boolean} True if the y-position yp is enclosed within y-positions y1 and y2.\n */\nfunction isEnclosedY(yp, y1, y2) {\n if ((y1 < yp && yp < y2) || (y2 < yp && yp < y1)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns true if the line segment is to the right of the point.\n * @private\n * @method\n * @name isLineRightOfPoint\n *\n * @param {Object} point The point being queried.\n * @param {Object} lp1 The first point of the line segment.\n * @param {Object} lp2 The second point of the line segment.\n * @returns {boolean} True if the line is to the right of the point.\n */\nfunction isLineRightOfPoint(point, lp1, lp2) {\n // If both right of point return true\n if (lp1.x > point.x && lp2.x > point.x) {\n return true;\n }\n\n // Catch when line is vertical.\n if (lp1.x === lp2.x) {\n return point.x < lp1.x;\n }\n\n // Put leftmost point in lp1\n if (lp1.x > lp2.x) {\n const lptemp = lp1;\n\n lp1 = lp2;\n lp2 = lptemp;\n }\n const lPointY = lineSegmentAtPoint(point, lp1, lp2);\n\n // If the lp1.x and lp2.x enclose point.x check gradient of line and see if\n // Point is above or below the line to calculate if it inside.\n if (Math.sign(lPointY.gradient) * point.y > lPointY.value) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns the y value of the line segment at the x value of the point.\n * @private\n * @method\n * @name lineSegmentAtPoint\n *\n * @param {Object} point The point being queried.\n * @param {Object} lp1 The first point of the line segment.\n * @param {Object} lp2 The second point of the line segment.\n * @returns {Object} An object containing the y value as well as the gradient of the line segment.\n */\nfunction lineSegmentAtPoint(point, lp1, lp2) {\n const dydx = (lp2.y - lp1.y) / (lp2.x - lp1.x);\n const fx = {\n value: lp1.x + dydx * (point.x - lp1.x),\n gradient: dydx,\n };\n\n return fx;\n}\n\n/**\n * Returns true if a rightwards ray originating from the point crosses the line defined by handleI and handleJ.\n * @private\n * @method\n * @name rayFromPointCrosssesLine\n *\n * @param {Object} point The point being queried.\n * @param {Object} handleI The first handle of the line segment.\n * @param {Object} handleJ The second handle of the line segment.\n * @returns {boolean} True if a rightwards ray originating from the point crosses the line defined by handleI and handleJ.\n */\nfunction rayFromPointCrosssesLine(point, handleI, handleJ) {\n if (\n isEnclosedY(point.y, handleI.y, handleJ.y) &&\n isLineRightOfPoint(point, handleI, handleJ)\n ) {\n return true;\n }\n\n return false;\n}\n","import pointInFreehand from './pointInFreehand.js';\n\n/**\n * Calculates the statistics of all the pixels within the freehand object.\n * @export @public @method\n * @name calculateFreehandStatistics\n *\n * @param {Object} sp An array of the pixel data.\n * @param {Object} boundingBox Rectangular box enclosing the polygon.\n * @param {Object} dataHandles Data object associated with the tool.\n * @returns {Object} Object containing the derived statistics.\n */\nexport default function(sp, boundingBox, dataHandles) {\n const statisticsObj = {\n count: 0,\n mean: 0.0,\n variance: 0.0,\n stdDev: 0.0,\n };\n\n const sum = getSum(sp, boundingBox, dataHandles);\n\n if (sum.count === 0) {\n return statisticsObj;\n }\n\n statisticsObj.count = sum.count;\n statisticsObj.mean = sum.value / sum.count;\n statisticsObj.variance =\n sum.squared / sum.count - statisticsObj.mean * statisticsObj.mean;\n statisticsObj.stdDev = Math.sqrt(statisticsObj.variance);\n\n return statisticsObj;\n}\n\n/**\n * Calculates the sum, squared sum and count of all pixels within the polygon.\n * @private\n * @method\n * @name getSum\n *\n * @param {Object} sp An array of the pixel data.\n * @param {Object} boundingBox Rectangular box enclosing the polygon.\n * @param {Object} dataHandles Data object associated with the tool.\n * @returns {Object} Object containing the sum, squared sum and pixel count.\n */\nfunction getSum(sp, boundingBox, dataHandles) {\n const sum = {\n value: 0,\n squared: 0,\n count: 0,\n };\n let index = 0;\n\n for (let y = boundingBox.top; y < boundingBox.top + boundingBox.height; y++) {\n for (\n let x = boundingBox.left;\n x < boundingBox.left + boundingBox.width;\n x++\n ) {\n const point = {\n x,\n y,\n };\n\n sumPointIfInFreehand(dataHandles, point, sum, sp[index]);\n index++;\n }\n }\n\n return sum;\n}\n\n/**\n * Adds the pixel to the workingSum if it is within the polygon.\n * @private\n * @method sumPointIfInFreehand\n *\n * @param {Object} dataHandles Data object associated with the tool.\n * @param {Object} point The pixel coordinates.\n * @param {Object} workingSum The working sum, squared sum and pixel count.\n * @param {Object} pixelValue The pixel value. // @modifies {workingSum}\n * @returns {undefined}\n */\nfunction sumPointIfInFreehand(dataHandles, point, workingSum, pixelValue) {\n if (pointInFreehand(dataHandles, point)) {\n workingSum.value += pixelValue;\n workingSum.squared += pixelValue * pixelValue;\n workingSum.count++;\n }\n}\n","/**\n * @public\n * @name ClickedLineData\n * @classdesc Creates an object containing information about the clicked line.\n * @property {number} toolIndex ID of the tool that the line corresponds to.\n * @property {Object} handleIndexArray An array of the handle indicies that correspond to the line segment.\n */\nexport default class ClickedLineData {\n /**\n * Constructs an object containing information about the clicked line.\n * @param {number} toolIndex - The ID of the tool the line corresponds to.\n * @param {Object} handleIndexArray - An array of the handle indicies that correspond to the line segment.\n */\n constructor(toolIndex, handleIndexArray) {\n this.toolIndex = toolIndex;\n this.handleIndexArray = handleIndexArray;\n }\n}\n","/**\n * @public\n * @name FreehandHandleData\n * @classdesc Creates a single handle for the freehand tool.\n *\n * @property {number} x The x position.\n * @property {number} y The y position.\n * @property {boolean} highlight Whether the handle should be rendered as the highlighted color.\n * @property {boolean} active Whether the handle is active.\n * @property {Object} lines An array of lines associated with the handle.\n */\nexport default class FreehandHandleData {\n /**\n * Constructs a a single handle for the freehand tool\n *\n * @param {Object} position - The position of the handle.\n * @param {boolean} highlight - whether the handle should be rendered as the highlighted color.\n * @param {boolean} active - whether the handle is active.\n */\n constructor(position, highlight = true, active = true) {\n this.x = position.x;\n this.y = position.y;\n this.highlight = highlight;\n this.active = active;\n this.lines = [];\n }\n}\n","/**\n * Orientation algoritm to determine if two lines cross.\n * Credit and details: geeksforgeeks.org/check-if-two-given-line-segments-intersect/\n */\n\n/**\n * Determines whether a new handle causes an intersection of the lines of the polygon.\n * @public\n * @function newHandle\n *\n * @param {Object} candidateHandle The new handle to check.\n * @param {Object} dataHandles data object associated with the tool.\n * @returns {boolean} - Whether the new line intersects with any other lines of the polygon.\n */\nfunction newHandle(candidateHandle, dataHandles) {\n // Check if the proposed line will intersect any existent line\n const lastHandleId = dataHandles.length - 1;\n const lastHandle = getCoords(dataHandles[lastHandleId]);\n const newHandle = getCoords(candidateHandle);\n\n return doesIntersectOtherLines(dataHandles, lastHandle, newHandle, [\n lastHandleId,\n ]);\n}\n\n/**\n * Checks if the last line of a polygon will intersect the other lines of the polgyon.\n * @public\n * @function end\n *\n * @param {Object} dataHandles data object associated with the tool.\n * @returns {boolean} Whether the last line intersects with any other lines of the polygon.\n */\nfunction end(dataHandles) {\n const lastHandleId = dataHandles.length - 1;\n const lastHandle = getCoords(dataHandles[lastHandleId]);\n const firstHandle = getCoords(dataHandles[0]);\n\n return doesIntersectOtherLines(dataHandles, lastHandle, firstHandle, [\n lastHandleId,\n 0,\n ]);\n}\n\n/**\n * Checks whether the modification of a handle's position causes intersection of the lines of the polygon.\n * @public\n * @method modify\n *\n * @param {Object} dataHandles Data object associated with the tool.\n * @param {number} modifiedHandleId The id of the handle being modified.\n * @returns {boolean} Whether the modfication causes any intersections.\n */\nfunction modify(dataHandles, modifiedHandleId) {\n // Check if the modifiedHandle's previous and next lines will intersect any other line in the polygon\n const modifiedHandle = getCoords(dataHandles[modifiedHandleId]);\n\n // Previous neightbor handle\n let neighborHandleId = modifiedHandleId - 1;\n\n if (modifiedHandleId === 0) {\n neighborHandleId = dataHandles.length - 1;\n }\n\n let neighborHandle = getCoords(dataHandles[neighborHandleId]);\n\n if (\n doesIntersectOtherLines(dataHandles, modifiedHandle, neighborHandle, [\n modifiedHandleId,\n neighborHandleId,\n ])\n ) {\n return true;\n }\n\n // Next neightbor handle\n if (modifiedHandleId === dataHandles.length - 1) {\n neighborHandleId = 0;\n } else {\n neighborHandleId = modifiedHandleId + 1;\n }\n\n neighborHandle = getCoords(dataHandles[neighborHandleId]);\n\n return doesIntersectOtherLines(dataHandles, modifiedHandle, neighborHandle, [\n modifiedHandleId,\n neighborHandleId,\n ]);\n}\n\n/**\n * Checks whether the line (p1,q1) intersects any of the other lines in the polygon.\n * @private\n * @function doesIntersectOtherLines\n *\n * @param {Object} dataHandles Data object associated with the tool.\n * @param {Object} p1 Coordinates of the start of the line.\n * @param {Object} q1 Coordinates of the end of the line.\n * @param {Object} ignoredHandleIds Ids of handles to ignore (i.e. lines that share a vertex with the line being tested).\n * @returns {boolean} Whether the line intersects any of the other lines in the polygon.\n */\nfunction doesIntersectOtherLines(dataHandles, p1, q1, ignoredHandleIds) {\n let j = dataHandles.length - 1;\n\n for (let i = 0; i < dataHandles.length; i++) {\n if (\n ignoredHandleIds.indexOf(i) !== -1 ||\n ignoredHandleIds.indexOf(j) !== -1\n ) {\n j = i;\n continue;\n }\n\n const p2 = getCoords(dataHandles[j]);\n const q2 = getCoords(dataHandles[i]);\n\n if (doesIntersect(p1, q1, p2, q2)) {\n return true;\n }\n\n j = i;\n }\n\n return false;\n}\n\n/**\n * Checks whether the line (p1,q1) intersects the line (p2,q2) via an orientation algorithm.\n * @private\n * @function doesIntersect\n *\n * @param {Object} p1 Coordinates of the start of the line 1.\n * @param {Object} q1 Coordinates of the end of the line 1.\n * @param {Object} p2 Coordinates of the start of the line 2.\n * @param {Object} q2 Coordinates of the end of the line 2.\n * @returns {boolean} Whether lines (p1,q1) and (p2,q2) intersect.\n */\nfunction doesIntersect(p1, q1, p2, q2) {\n let result = false;\n\n const orient = [\n orientation(p1, q1, p2),\n orientation(p1, q1, q2),\n orientation(p2, q2, p1),\n orientation(p2, q2, q1),\n ];\n\n // General Case\n if (orient[0] !== orient[1] && orient[2] !== orient[3]) {\n return true;\n }\n\n // Special Cases\n if (orient[0] === 0 && onSegment(p1, p2, q1)) {\n // If p1, q1 and p2 are colinear and p2 lies on segment p1q1\n result = true;\n } else if (orient[1] === 0 && onSegment(p1, q2, q1)) {\n // If p1, q1 and p2 are colinear and q2 lies on segment p1q1\n result = true;\n } else if (orient[2] === 0 && onSegment(p2, p1, q2)) {\n // If p2, q2 and p1 are colinear and p1 lies on segment p2q2\n result = true;\n } else if (orient[3] === 0 && onSegment(p2, q1, q2)) {\n // If p2, q2 and q1 are colinear and q1 lies on segment p2q2\n result = true;\n }\n\n return result;\n}\n\n/**\n * Returns an object with two properties, x and y, from a heavier FreehandHandleData object.\n * @private\n * @function getCoords\n *\n * @param {Object} dataHandle Data object associated with a single handle in the freehand tool.\n * @returns {Object} An object containing position propeties x and y.\n */\nfunction getCoords(dataHandle) {\n return {\n x: dataHandle.x,\n y: dataHandle.y,\n };\n}\n\n/**\n * Checks the orientation of 3 points.\n * @private\n * @function orientation\n *\n * @param {Object} p First point.\n * @param {Object} q Second point.\n * @param {Object} r Third point.\n * @returns {number} - 0: Colinear, 1: Clockwise, 2: Anticlockwise\n */\nfunction orientation(p, q, r) {\n const orientationValue =\n (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);\n\n if (orientationValue === 0) {\n return 0; // Colinear\n }\n\n return orientationValue > 0 ? 1 : 2;\n}\n\n/**\n * Checks if point q lines on the segment (p,r).\n * @private\n * @function onSegment\n *\n * @param {Object} p Point p.\n * @param {Object} q Point q.\n * @param {Object} r Point r.\n * @returns {boolean} - If q lies on line segment (p,r).\n */\nfunction onSegment(p, q, r) {\n if (\n q.x <= Math.max(p.x, r.x) &&\n q.x >= Math.min(p.x, r.x) &&\n q.y <= Math.max(p.y, r.y) &&\n q.y >= Math.min(p.y, r.y)\n ) {\n return true;\n }\n\n return false;\n}\n\nexport default {\n newHandle,\n end,\n modify,\n};\n","import { getToolState } from '../../stateManagement/toolState.js';\nimport external from '../../externalModules.js';\nimport ClickedLineData from './ClickedLineData.js';\n\nconst distanceThreshold = 10;\n\n/**\n * @public\n * @class FreehandLineFinder\n * @classdesc Class that finds lines of freehand ROIs based on click proximity.\n */\nexport default class FreehandLineFinder {\n /**\n * Creates an instance of FreehandLineFinder.\n * @param {*} eventData - Data object associated with the event.\n * @param {string} toolName - The tool name\n * @memberof FreehandLineFinder\n */\n constructor(eventData, toolName) {\n this._eventData = eventData;\n this._toolName = toolName;\n }\n\n /**\n * Looks for lines near the mouse cursor.\n *\n * @public\n * @method\n * @returns {ClickedLineData} Data object corresponding to the clicked line.\n */\n findLine() {\n const closestToolIndex = this.findTool();\n\n if (closestToolIndex === null) {\n return null;\n }\n\n const closeLines = this._getCloseLinesInTool(closestToolIndex);\n\n if (closeLines) {\n const clickedLineData = this._findCorrectLine(\n closestToolIndex,\n closeLines\n );\n\n // Note: clickedLineData may be null if no valid projections are found.\n return clickedLineData;\n }\n\n // Return null if no valid close lines found.\n return null;\n }\n\n /**\n * Looks for tools near the mouse cursor.\n *\n * @public\n * @method\n *\n * @returns {ClickedLineData} Data object corresponding to the clicked line.\n */\n findTool() {\n this._toolData = getToolState(this._eventData.element, this._toolName);\n this._mousePoint = this._eventData.currentPoints.canvas;\n\n if (!this._toolData) {\n return null;\n }\n\n const closestHandle = this._nearestHandleToPointAllTools();\n\n return closestHandle.toolIndex;\n }\n\n /**\n * Finds the nearest handle to the mouse cursor for all tools.\n * @private\n * @method\n * @returns {Object} The handle closest to the point.\n */\n _nearestHandleToPointAllTools() {\n const toolData = this._toolData;\n\n let closestHandle = {\n toolIndex: null,\n handleIndex: null,\n distance: Infinity, // Some large number\n };\n\n for (let toolIndex = 0; toolIndex < toolData.data.length; toolIndex++) {\n const closestHandleForToolI = this._nearestHandleToPoint(toolIndex);\n\n if (closestHandleForToolI === null) {\n continue;\n }\n\n if (closestHandleForToolI.distance < closestHandle.distance) {\n closestHandle = closestHandleForToolI;\n }\n }\n\n return closestHandle;\n }\n\n /**\n * Finds the nearest handle to the mouse cursor for a specific tool.\n * @private\n * @method\n *\n * @param {number} toolIndex The index of the particular freehand tool.\n * @returns {Object} An object containing information about the closest handle.\n */\n _nearestHandleToPoint(toolIndex) {\n const eventData = this._eventData;\n const toolData = this._toolData;\n\n const data = toolData.data[toolIndex];\n const points = data.handles.points;\n\n if (points === undefined) {\n return null;\n }\n\n if (data.visible === false) {\n return null;\n }\n\n const closest = {\n toolIndex,\n handleIndex: null,\n distance: Infinity, // Some large number\n };\n\n for (let i = 0; i < points.length; i++) {\n const handleCanvas = external.cornerstone.pixelToCanvas(\n eventData.element,\n points[i]\n );\n const handleDistanceFromMousePoint = external.cornerstoneMath.point.distance(\n handleCanvas,\n this._mousePoint\n );\n\n if (handleDistanceFromMousePoint < closest.distance) {\n closest.handleIndex = i;\n closest.distance = handleDistanceFromMousePoint;\n }\n }\n\n return closest;\n }\n\n /**\n * Finds all the lines close to the mouse point for a particular tool.\n * @private\n * @method\n *\n * @param {number} toolIndex The index of the particular freehand tool.\n * @returns {Object} An array of lines close to the mouse point.\n */\n _getCloseLinesInTool(toolIndex) {\n const toolData = this._toolData;\n const points = toolData.data[toolIndex].handles.points;\n\n const closeLines = [];\n\n for (let i = 0; i < points.length; i++) {\n const nextIndex = FreehandLineFinder.getNextHandleIndex(i, points.length);\n const d = this._distanceOfPointfromLine(points[i], points[nextIndex]);\n\n if (d < distanceThreshold) {\n closeLines.push([i, nextIndex]);\n }\n }\n\n return closeLines;\n }\n\n /**\n * Finds the line the user clicked on from an array of close lines.\\\n * @private\n * @method\n *\n * @param {number} toolIndex The index of the particular freehand tool.\n * @param {Object} closeLines An array of lines close to the mouse point.\n * @returns {ClickedLineData|null} An instance of ClickedLineData containing information about the line, or null if no line is correct.\n */\n _findCorrectLine(toolIndex, closeLines) {\n // Test if any candidate lines can be projected onto by the mousePoint\n for (let i = 0; i < closeLines.length; i++) {\n if (this._pointProjectsToLineSegment(toolIndex, closeLines[i])) {\n return new ClickedLineData(toolIndex, closeLines[i]);\n }\n }\n\n // No valid line found\n return null;\n }\n\n /**\n * Returns true if the mouse point projects onto the line segment.\n * @private\n * @method\n *\n * @param {number} toolIndex The index of the particular freehand tool.\n * @param {Object} handleIndexArray An array of indicies corresponding to the line segment.\n * @returns {boolean} True if the mouse point projects onto the line segment\n */\n _pointProjectsToLineSegment(toolIndex, handleIndexArray) {\n const eventData = this._eventData;\n const toolData = this._toolData;\n const data = toolData.data[toolIndex];\n const points = data.handles.points;\n\n if (data.handles.points === undefined) {\n return;\n }\n\n if (data.visible === false) {\n return false;\n }\n\n const handle1 = points[handleIndexArray[0]];\n const handle2 = points[handleIndexArray[1]];\n\n const p = FreehandLineFinder.getCanvasPointsFromHandles(\n handle1,\n handle2,\n eventData.element\n );\n\n const r = FreehandLineFinder.getLineAsVector(p);\n const m = this._getLineOriginToMouseAsVector(p);\n\n // Project vector m onto r to see if the point is within bounds of line segment\n const mProj = (m[0] * r[0] + m[1] * r[1]) / r.magnitude;\n\n if (mProj > 0 && mProj < r.magnitude) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Returns the canvas positions from the handle's pixel positions.\n *\n * @static\n * @public\n * @method\n * @param {FreehandHandleData} handle1 The first handle.\n * @param {FreehandHandleData} handle2 The second handle.\n * @param {Object} element The element on which the handles reside.\n * @returns {Object} An array contsining the handle positions in canvas coordinates.\n */\n static getCanvasPointsFromHandles(handle1, handle2, element) {\n const p = [];\n\n // Point r from left to right so that we only have one orientation to test.\n if (handle1.x < handle2.x) {\n p.push(external.cornerstone.pixelToCanvas(element, handle1));\n p.push(external.cornerstone.pixelToCanvas(element, handle2));\n } else {\n p.push(external.cornerstone.pixelToCanvas(element, handle2));\n p.push(external.cornerstone.pixelToCanvas(element, handle1));\n }\n\n return p;\n }\n\n /**\n * Converts a line segment to a vector.\n *\n * @static\n * @public\n * @method\n * @param {Object} p An array of two points respresenting the line segment.\n * @returns {Object} An array containing the x and y components of the vector, as well as a magnitude property.\n */\n static getLineAsVector(p) {\n const r = [p[1].x - p[0].x, p[1].y - p[0].y];\n\n r.magnitude = external.cornerstoneMath.point.distance(p[0], p[1]);\n\n return r;\n }\n\n /**\n * Constructs a vector from the direction and magnitude of the line from the the line origin to the mouse cursor.\n * @private\n * @method\n *\n * @param {Object} p An array of two points respresenting the line segment.\n * @returns {Object} An array containing the x and y components of the vector.\n */\n _getLineOriginToMouseAsVector(p) {\n const m = [this._mousePoint.x - p[0].x, this._mousePoint.y - p[0].y];\n\n return m;\n }\n\n /**\n * Calculates the perpendicular distance of the mouse cursor from a line segment.\n * @private\n * @method\n *\n * @param {FreehandHandleData} handle1 The first handle.\n * @param {FreehandHandleData} handle2 The first handle.\n * @returns {number} The perpendicular distance of the mouse cursor from the line segment.\n */\n _distanceOfPointfromLine(handle1, handle2) {\n const eventData = this._eventData;\n\n const p1 = external.cornerstone.pixelToCanvas(eventData.element, handle1);\n const p2 = external.cornerstone.pixelToCanvas(eventData.element, handle2);\n const pMouse = this._mousePoint;\n\n // Perpendicular distance of point from line:\n // = 2* area of triangle(p1,p2,pm) / length of triangle's base |p2 - p1|\n const twiceAreaOfTriangle = Math.abs(\n (p2.y - p1.y) * pMouse.x -\n (p2.x - p1.x) * pMouse.y +\n p2.x * p1.y -\n p2.y * p1.x\n );\n const rMagnitude = external.cornerstoneMath.point.distance(p1, p2);\n const d = twiceAreaOfTriangle / rMagnitude;\n\n return d;\n }\n\n /**\n * Gets the next handl index from a cyclical array of points.\n *\n * @static\n * @public\n * @method\n *\n * @param {number} currentIndex The current index.\n * @param {number} length The number of handles in the polygon.\n * @returns {number} The index of the next handle.\n */\n static getNextHandleIndex(currentIndex, length) {\n let nextIndex;\n\n if (currentIndex < length - 1) {\n nextIndex = currentIndex + 1;\n } else {\n nextIndex = 0;\n }\n\n return nextIndex;\n }\n}\n","/**\n * AddLine - Adds a line to a specifc index of a freehand tool points array.\n *\n * @param {Object[]} points The array of points.\n * @param {Number} insertIndex The index to insert the line.\n * @returns {Null} description\n */\nexport default function(points, insertIndex) {\n // Add the line from the inserted handle to the handle after\n if (insertIndex === points.length - 1) {\n points[insertIndex].lines.push(points[0]);\n } else {\n points[insertIndex].lines.push(points[insertIndex + 1]);\n }\n}\n","import FreehandLineFinder from './FreehandLineFinder.js';\nimport FreehandHandleData from './FreehandHandleData.js';\nimport { getToolState } from '../../stateManagement/toolState.js';\nimport external from '../../externalModules.js';\nimport addLine from './addLine.js';\n\n/**\n * Inserts or deletes a point from a freehand tool.\n * @export @public @method\n * @name insertOrDelete\n *\n * @param {Object} evt The event.\n * @param {Object} nearby Object containing information about a nearby handle.\n * @returns {void}\n */\nexport default function(evt, nearby) {\n const eventData = evt.detail;\n\n if (nearby && nearby.handleNearby !== null) {\n const deleteInfo = {\n toolIndex: nearby.toolIndex,\n handleIndex: nearby.handleNearby,\n };\n\n _deletePoint.call(this, eventData, deleteInfo);\n } else {\n const freehandLineFinder = new FreehandLineFinder(eventData, this.name);\n const insertInfo = freehandLineFinder.findLine();\n\n if (insertInfo) {\n _insertPoint.call(this, eventData, insertInfo);\n }\n }\n}\n\n/**\n * Deletes a point from a freehand tool.\n * @private\n * @method\n *\n * @param {Object} eventData The data object associated with the event.\n * @param {Object} deleteInfo Object containing information about which point to delete.\n * @returns {void}\n */\nfunction _deletePoint(eventData, deleteInfo) {\n const toolData = getToolState(eventData.element, this.name);\n\n if (toolData === undefined) {\n return;\n }\n\n const deleteHandle = deleteInfo.handleIndex;\n const toolIndex = deleteInfo.toolIndex;\n\n // Get the toolData from insertInfo\n const data = toolData.data[toolIndex];\n\n const points = data.handles.points;\n\n // Only allow delete if > 3 points\n if (points.length <= 3) {\n return;\n }\n\n // Link the line of the previous handle to the one after handles[deleteHandle];\n if (deleteHandle === points.length - 1) {\n points[deleteHandle - 1].lines.pop();\n points[deleteHandle - 1].lines.push(points[0]);\n } else if (deleteHandle === 0) {\n points[points.length - 1].lines.pop();\n points[points.length - 1].lines.push(points[deleteHandle + 1]);\n } else {\n points[deleteHandle - 1].lines.pop();\n points[deleteHandle - 1].lines.push(points[deleteHandle + 1]);\n }\n\n // Remove the handle\n points.splice(deleteHandle, 1);\n\n data.invalidated = true;\n data.active = true;\n data.highlight = true;\n\n // Force onImageRendered to fire\n external.cornerstone.updateImage(eventData.element);\n}\n\n/**\n * Inserts a new point into a freehand tool.\n * @private\n * @method\n *\n * @param {Object} eventData - The data object associated with the event.\n * @param {Object} insertInfo - Object containing information about where to insert the point.\n * @returns {void}\n */\nfunction _insertPoint(eventData, insertInfo) {\n const toolData = getToolState(eventData.element, this.name);\n\n if (toolData === undefined) {\n return;\n }\n\n // Get the toolData from insertInfo\n const data = toolData.data[insertInfo.toolIndex];\n\n const insertIndex = _getInsertionIndex(insertInfo);\n\n if (insertIndex === Infinity) {\n return;\n }\n\n const handleData = new FreehandHandleData(eventData.currentPoints.image);\n\n const points = data.handles.points;\n\n // Add the new handle\n points.splice(insertIndex, 0, handleData);\n\n // Add the line from the previous handle to the inserted handle (note the tool is now one increment longer)\n points[insertIndex - 1].lines.pop();\n points[insertIndex - 1].lines.push(eventData.currentPoints.image);\n\n addLine(points, insertIndex);\n\n data.active = true;\n data.highlight = true;\n\n // Force onImageRendered to fire\n data.invalidated = true;\n external.cornerstone.updateImage(eventData.element);\n}\n\n/**\n * Gets the handle index of a tool in which to insert the new point.\n * @private\n * @method\n *\n * @param {Object} insertInfo - Object containing information about where to insert the point.\n * @returns {void}\n */\nfunction _getInsertionIndex(insertInfo) {\n // Get lowest index that isn't zero\n const handleIndexArray = insertInfo.handleIndexArray;\n let insertIndex = Infinity;\n const arrayContainsZero = handleIndexArray.includes(0);\n\n for (let i = 0; i < handleIndexArray.length; i++) {\n const index = handleIndexArray[i];\n\n if (index !== 0 && index < insertIndex) {\n insertIndex = index;\n }\n }\n\n // Treat the special case of handleIndexArray === [0,1] || [1,0]\n if (arrayContainsZero && insertIndex === 1) {\n insertIndex = 0;\n }\n\n // The insertion index shall be just after the lower index\n insertIndex++;\n\n return insertIndex;\n}\n","import calculateFreehandStatistics from './calculateFreehandStatistics.js';\nimport ClickedLineData from './ClickedLineData.js';\nimport freehandArea from './freehandArea.js';\nimport FreehandHandleData from './FreehandHandleData.js';\nimport freehandIntersect from './freehandIntersect.js';\nimport FreehandLineFinder from './FreehandLineFinder.js';\nimport insertOrDelete from './insertOrDelete.js';\nimport pointInFreehand from './pointInFreehand.js';\nimport addLine from './addLine.js';\n\nexport default {\n calculateFreehandStatistics,\n ClickedLineData,\n freehandArea,\n FreehandHandleData,\n freehandIntersect,\n FreehandLineFinder,\n insertOrDelete,\n pointInFreehand,\n addLine,\n};\n","/**\n * Calculates the area of a freehand tool polygon.\n * @export @public @method\n * @name freehandArea\n *\n * @param {Object} dataHandles Data object associated with the tool.\n * @param {Object} scaling Area scaling of image.\n * @returns {number} The area of the polygon.\n */\nexport default function(dataHandles, scaling) {\n let freeHandArea = 0;\n let j = dataHandles.length - 1; // The last vertex is the previous one to the first\n\n scaling = scaling || 1; // If scaling is falsy, set scaling to 1\n\n for (let i = 0; i < dataHandles.length; i++) {\n freeHandArea +=\n (dataHandles[j].x + dataHandles[i].x) *\n (dataHandles[j].y - dataHandles[i].y);\n j = i; // Here j is previous vertex to i\n }\n\n return Math.abs((freeHandArea * scaling) / 2.0);\n}\n","import EVENTS from './../../events.js';\nimport external from './../../externalModules.js';\nimport BaseAnnotationTool from './../base/BaseAnnotationTool.js';\n// State\nimport {\n addToolState,\n getToolState,\n removeToolState,\n} from './../../stateManagement/toolState.js';\nimport toolStyle from './../../stateManagement/toolStyle.js';\nimport toolColors from './../../stateManagement/toolColors.js';\nimport { state } from '../../store/index.js';\nimport triggerEvent from '../../util/triggerEvent.js';\n// Manipulators\nimport { moveHandleNearImagePoint } from '../../util/findAndMoveHelpers.js';\n// Implementation Logic\nimport pointInsideBoundingBox from '../../util/pointInsideBoundingBox.js';\nimport calculateSUV from '../../util/calculateSUV.js';\nimport numbersWithCommas from '../../util/numbersWithCommas.js';\n\n// Drawing\nimport { getNewContext, draw, drawJoinedLines } from '../../drawing/index.js';\nimport drawLinkedTextBox from '../../drawing/drawLinkedTextBox.js';\nimport drawHandles from '../../drawing/drawHandles.js';\nimport { clipToBox } from '../../util/clip.js';\nimport { hideToolCursor, setToolCursor } from '../../store/setToolCursor.js';\nimport { freehandRoiCursor } from '../cursors/index.js';\nimport freehandUtils from '../../util/freehand/index.js';\nimport { getLogger } from '../../util/logger.js';\nimport throttle from '../../util/throttle';\n\nconst logger = getLogger('tools:annotation:FreehandRoiTool');\n\nconst {\n insertOrDelete,\n freehandArea,\n calculateFreehandStatistics,\n freehandIntersect,\n FreehandHandleData,\n} = freehandUtils;\n\n/**\n * @public\n * @class FreehandRoiTool\n * @memberof Tools.Annotation\n * @classdesc Tool for drawing arbitrary polygonal regions of interest, and\n * measuring the statistics of the enclosed pixels.\n * @extends Tools.Base.BaseAnnotationTool\n */\nexport default class FreehandRoiTool extends BaseAnnotationTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'FreehandRoi',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: defaultFreehandConfiguration(),\n svgCursor: freehandRoiCursor,\n };\n\n super(props, defaultProps);\n\n this.isMultiPartTool = true;\n\n this._drawing = false;\n this._dragging = false;\n this._modifying = false;\n\n // Create bound callback functions for private event loops\n this._drawingMouseDownCallback = this._drawingMouseDownCallback.bind(this);\n this._drawingMouseMoveCallback = this._drawingMouseMoveCallback.bind(this);\n this._drawingMouseDragCallback = this._drawingMouseDragCallback.bind(this);\n this._drawingMouseUpCallback = this._drawingMouseUpCallback.bind(this);\n this._drawingMouseDoubleClickCallback = this._drawingMouseDoubleClickCallback.bind(\n this\n );\n this._editMouseUpCallback = this._editMouseUpCallback.bind(this);\n this._editMouseDragCallback = this._editMouseDragCallback.bind(this);\n\n this._drawingTouchStartCallback = this._drawingTouchStartCallback.bind(\n this\n );\n this._drawingTouchDragCallback = this._drawingTouchDragCallback.bind(this);\n this._drawingDoubleTapClickCallback = this._drawingDoubleTapClickCallback.bind(\n this\n );\n this._editTouchDragCallback = this._editTouchDragCallback.bind(this);\n\n this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);\n }\n\n createNewMeasurement(eventData) {\n const goodEventData =\n eventData && eventData.currentPoints && eventData.currentPoints.image;\n\n if (!goodEventData) {\n logger.error(\n `required eventData not supplied to tool ${this.name}'s createNewMeasurement`\n );\n\n return;\n }\n\n const measurementData = {\n visible: true,\n active: true,\n invalidated: true,\n color: undefined,\n handles: {\n points: [],\n },\n };\n\n measurementData.handles.textBox = {\n active: false,\n hasMoved: false,\n movesIndependently: false,\n drawnIndependently: true,\n allowedOutsideImage: true,\n hasBoundingBox: true,\n };\n\n return measurementData;\n }\n\n /**\n *\n *\n * @param {*} element element\n * @param {*} data data\n * @param {*} coords coords\n * @returns {Boolean}\n */\n pointNearTool(element, data, coords) {\n const validParameters = data && data.handles && data.handles.points;\n\n if (!validParameters) {\n throw new Error(\n `invalid parameters supplied to tool ${this.name}'s pointNearTool`\n );\n }\n\n if (!validParameters || data.visible === false) {\n return false;\n }\n\n const isPointNearTool = this._pointNearHandle(element, data, coords);\n\n if (isPointNearTool !== undefined) {\n return true;\n }\n\n return false;\n }\n\n /**\n * @param {*} element\n * @param {*} data\n * @param {*} coords\n * @returns {number} the distance in px from the provided coordinates to the\n * closest rendered portion of the annotation. -1 if the distance cannot be\n * calculated.\n */\n distanceFromPoint(element, data, coords) {\n let distance = Infinity;\n\n for (let i = 0; i < data.handles.points.length; i++) {\n const distanceI = external.cornerstoneMath.point.distance(\n data.handles.points[i],\n coords\n );\n\n distance = Math.min(distance, distanceI);\n }\n\n // If an error caused distance not to be calculated, return -1.\n if (distance === Infinity) {\n return -1;\n }\n\n return distance;\n }\n\n /**\n * @param {*} element\n * @param {*} data\n * @param {*} coords\n * @returns {number} the distance in canvas units from the provided coordinates to the\n * closest rendered portion of the annotation. -1 if the distance cannot be\n * calculated.\n */\n distanceFromPointCanvas(element, data, coords) {\n let distance = Infinity;\n\n if (!data) {\n return -1;\n }\n\n const canvasCoords = external.cornerstone.pixelToCanvas(element, coords);\n\n const points = data.handles.points;\n\n for (let i = 0; i < points.length; i++) {\n const handleCanvas = external.cornerstone.pixelToCanvas(\n element,\n points[i]\n );\n\n const distanceI = external.cornerstoneMath.point.distance(\n handleCanvas,\n canvasCoords\n );\n\n distance = Math.min(distance, distanceI);\n }\n\n // If an error caused distance not to be calculated, return -1.\n if (distance === Infinity) {\n return -1;\n }\n\n return distance;\n }\n\n /**\n *\n *\n *\n * @param {Object} image image\n * @param {Object} element element\n * @param {Object} data data\n *\n * @returns {void} void\n */\n updateCachedStats(image, element, data) {\n // Define variables for the area and mean/standard deviation\n let meanStdDev, meanStdDevSUV;\n\n const seriesModule = external.cornerstone.metaData.get(\n 'generalSeriesModule',\n image.imageId\n );\n const modality = seriesModule ? seriesModule.modality : null;\n\n const points = data.handles.points;\n // If the data has been invalidated, and the tool is not currently active,\n // We need to calculate it again.\n\n // Retrieve the bounds of the ROI in image coordinates\n const bounds = {\n left: points[0].x,\n right: points[0].x,\n bottom: points[0].y,\n top: points[0].x,\n };\n\n for (let i = 0; i < points.length; i++) {\n bounds.left = Math.min(bounds.left, points[i].x);\n bounds.right = Math.max(bounds.right, points[i].x);\n bounds.bottom = Math.min(bounds.bottom, points[i].y);\n bounds.top = Math.max(bounds.top, points[i].y);\n }\n\n const polyBoundingBox = {\n left: bounds.left,\n top: bounds.bottom,\n width: Math.abs(bounds.right - bounds.left),\n height: Math.abs(bounds.top - bounds.bottom),\n };\n\n // Store the bounding box information for the text box\n data.polyBoundingBox = polyBoundingBox;\n\n // First, make sure this is not a color image, since no mean / standard\n // Deviation will be calculated for color images.\n if (!image.color) {\n // Retrieve the array of pixels that the ROI bounds cover\n const pixels = external.cornerstone.getPixels(\n element,\n polyBoundingBox.left,\n polyBoundingBox.top,\n polyBoundingBox.width,\n polyBoundingBox.height\n );\n\n // Calculate the mean & standard deviation from the pixels and the object shape\n meanStdDev = calculateFreehandStatistics.call(\n this,\n pixels,\n polyBoundingBox,\n data.handles.points\n );\n\n if (modality === 'PT') {\n // If the image is from a PET scan, use the DICOM tags to\n // Calculate the SUV from the mean and standard deviation.\n\n // Note that because we are using modality pixel values from getPixels, and\n // The calculateSUV routine also rescales to modality pixel values, we are first\n // Returning the values to storedPixel values before calcuating SUV with them.\n // TODO: Clean this up? Should we add an option to not scale in calculateSUV?\n meanStdDevSUV = {\n mean: calculateSUV(\n image,\n (meanStdDev.mean - image.intercept) / image.slope\n ),\n stdDev: calculateSUV(\n image,\n (meanStdDev.stdDev - image.intercept) / image.slope\n ),\n };\n }\n\n // If the mean and standard deviation values are sane, store them for later retrieval\n if (meanStdDev && !isNaN(meanStdDev.mean)) {\n data.meanStdDev = meanStdDev;\n data.meanStdDevSUV = meanStdDevSUV;\n }\n }\n\n // Retrieve the pixel spacing values, and if they are not\n // Real non-zero values, set them to 1\n const columnPixelSpacing = image.columnPixelSpacing || 1;\n const rowPixelSpacing = image.rowPixelSpacing || 1;\n const scaling = columnPixelSpacing * rowPixelSpacing;\n\n const area = freehandArea(data.handles.points, scaling);\n\n // If the area value is sane, store it for later retrieval\n if (!isNaN(area)) {\n data.area = area;\n }\n\n // Set the invalidated flag to false so that this data won't automatically be recalculated\n data.invalidated = false;\n }\n\n /**\n *\n *\n * @param {*} evt\n * @returns {undefined}\n */\n renderToolData(evt) {\n const eventData = evt.detail;\n\n // If we have no toolState for this element, return immediately as there is nothing to do\n const toolState = getToolState(evt.currentTarget, this.name);\n\n if (!toolState) {\n return;\n }\n\n const { image, element } = eventData;\n const config = this.configuration;\n const seriesModule = external.cornerstone.metaData.get(\n 'generalSeriesModule',\n image.imageId\n );\n const modality = seriesModule ? seriesModule.modality : null;\n\n // We have tool data for this element - iterate over each one and draw it\n const context = getNewContext(eventData.canvasContext.canvas);\n const lineWidth = toolStyle.getToolWidth();\n\n for (let i = 0; i < toolState.data.length; i++) {\n const data = toolState.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n draw(context, context => {\n let color = toolColors.getColorIfActive(data);\n let fillColor;\n\n if (data.active) {\n if (data.handles.invalidHandlePlacement) {\n color = config.invalidColor;\n fillColor = config.invalidColor;\n } else {\n color = toolColors.getColorIfActive(data);\n fillColor = toolColors.getFillColor();\n }\n } else {\n fillColor = toolColors.getToolColor();\n }\n\n if (data.handles.points.length) {\n for (let j = 0; j < data.handles.points.length; j++) {\n const lines = [...data.handles.points[j].lines];\n const points = data.handles.points;\n\n if (j === points.length - 1 && !data.polyBoundingBox) {\n // If it's still being actively drawn, keep the last line to\n // The mouse location\n lines.push(config.mouseLocation.handles.start);\n }\n drawJoinedLines(context, element, data.handles.points[j], lines, {\n color,\n });\n }\n }\n\n // Draw handles\n\n const options = {\n color,\n fill: fillColor,\n };\n\n if (config.alwaysShowHandles || (data.active && data.polyBoundingBox)) {\n // Render all handles\n options.handleRadius = config.activeHandleRadius;\n drawHandles(context, eventData, data.handles.points, options);\n }\n\n if (data.canComplete) {\n // Draw large handle at the origin if can complete drawing\n options.handleRadius = config.completeHandleRadius;\n const handle = data.handles.points[0];\n\n drawHandles(context, eventData, [handle], options);\n }\n\n if (data.active && !data.polyBoundingBox) {\n // Draw handle at origin and at mouse if actively drawing\n options.handleRadius = config.activeHandleRadius;\n drawHandles(\n context,\n eventData,\n config.mouseLocation.handles,\n options\n );\n\n const firstHandle = data.handles.points[0];\n\n drawHandles(context, eventData, [firstHandle], options);\n }\n\n // Update textbox stats\n if (data.invalidated === true && !data.active) {\n if (data.meanStdDev && data.meanStdDevSUV && data.area) {\n this.throttledUpdateCachedStats(image, element, data);\n } else {\n this.updateCachedStats(image, element, data);\n }\n }\n\n // Only render text if polygon ROI has been completed and freehand 'shiftKey' mode was not used:\n if (data.polyBoundingBox && !data.handles.textBox.freehand) {\n // If the textbox has not been moved by the user, it should be displayed on the right-most\n // Side of the tool.\n if (!data.handles.textBox.hasMoved) {\n // Find the rightmost side of the polyBoundingBox at its vertical center, and place the textbox here\n // Note that this calculates it in image coordinates\n data.handles.textBox.x =\n data.polyBoundingBox.left + data.polyBoundingBox.width;\n data.handles.textBox.y =\n data.polyBoundingBox.top + data.polyBoundingBox.height / 2;\n }\n\n const text = textBoxText.call(this, data);\n\n drawLinkedTextBox(\n context,\n element,\n data.handles.textBox,\n text,\n data.handles.points,\n textBoxAnchorPoints,\n color,\n lineWidth,\n 0,\n true\n );\n }\n });\n }\n\n function textBoxText(data) {\n const { meanStdDev, meanStdDevSUV, area } = data;\n // Define an array to store the rows of text for the textbox\n const textLines = [];\n\n // If the mean and standard deviation values are present, display them\n if (meanStdDev && meanStdDev.mean !== undefined) {\n // If the modality is CT, add HU to denote Hounsfield Units\n let moSuffix = '';\n\n if (modality === 'CT') {\n moSuffix = 'HU';\n }\n data.unit = moSuffix;\n\n // Create a line of text to display the mean and any units that were specified (i.e. HU)\n let meanText = `Mean: ${numbersWithCommas(\n meanStdDev.mean.toFixed(2)\n )} ${moSuffix}`;\n // Create a line of text to display the standard deviation and any units that were specified (i.e. HU)\n let stdDevText = `StdDev: ${numbersWithCommas(\n meanStdDev.stdDev.toFixed(2)\n )} ${moSuffix}`;\n\n // If this image has SUV values to display, concatenate them to the text line\n if (meanStdDevSUV && meanStdDevSUV.mean !== undefined) {\n const SUVtext = ' SUV: ';\n\n meanText +=\n SUVtext + numbersWithCommas(meanStdDevSUV.mean.toFixed(2));\n stdDevText +=\n SUVtext + numbersWithCommas(meanStdDevSUV.stdDev.toFixed(2));\n }\n\n // Add these text lines to the array to be displayed in the textbox\n textLines.push(meanText);\n textLines.push(stdDevText);\n }\n\n // If the area is a sane value, display it\n if (area) {\n // Determine the area suffix based on the pixel spacing in the image.\n // If pixel spacing is present, use millimeters. Otherwise, use pixels.\n // This uses Char code 178 for a superscript 2\n let suffix = ` mm${String.fromCharCode(178)}`;\n\n if (!image.rowPixelSpacing || !image.columnPixelSpacing) {\n suffix = ` pixels${String.fromCharCode(178)}`;\n }\n\n // Create a line of text to display the area and its units\n const areaText = `Area: ${numbersWithCommas(area.toFixed(2))}${suffix}`;\n\n // Add this text line to the array to be displayed in the textbox\n textLines.push(areaText);\n }\n\n return textLines;\n }\n\n function textBoxAnchorPoints(handles) {\n return handles;\n }\n }\n\n addNewMeasurement(evt) {\n const eventData = evt.detail;\n\n this._startDrawing(evt);\n this._addPoint(eventData);\n\n preventPropagation(evt);\n }\n\n preMouseDownCallback(evt) {\n const eventData = evt.detail;\n const nearby = this._pointNearHandleAllTools(eventData);\n\n if (eventData.event.ctrlKey) {\n if (nearby !== undefined && nearby.handleNearby.hasBoundingBox) {\n // Ctrl + clicked textBox, do nothing but still consume event.\n } else {\n insertOrDelete.call(this, evt, nearby);\n }\n\n preventPropagation(evt);\n\n return true;\n }\n\n return false;\n }\n\n handleSelectedCallback(evt, toolData, handle, interactionType = 'mouse') {\n const { element } = evt.detail;\n const toolState = getToolState(element, this.name);\n\n if (handle.hasBoundingBox) {\n // Use default move handler.\n moveHandleNearImagePoint(evt, this, toolData, handle, interactionType);\n\n return;\n }\n\n const config = this.configuration;\n\n config.dragOrigin = {\n x: handle.x,\n y: handle.y,\n };\n\n // Iterating over handles of all toolData instances to find the indices of the selected handle\n for (let toolIndex = 0; toolIndex < toolState.data.length; toolIndex++) {\n const points = toolState.data[toolIndex].handles.points;\n\n for (let p = 0; p < points.length; p++) {\n if (points[p] === handle) {\n config.currentHandle = p;\n config.currentTool = toolIndex;\n }\n }\n }\n\n this._modifying = true;\n\n this._activateModify(element);\n\n // Interupt eventDispatchers\n preventPropagation(evt);\n }\n\n /**\n * Event handler for MOUSE_MOVE during drawing event loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _drawingMouseMoveCallback(evt) {\n const eventData = evt.detail;\n const { currentPoints, element } = eventData;\n const toolState = getToolState(element, this.name);\n\n const config = this.configuration;\n const currentTool = config.currentTool;\n\n const data = toolState.data[currentTool];\n const coords = currentPoints.canvas;\n\n // Set the mouseLocation handle\n this._getMouseLocation(eventData);\n this._checkInvalidHandleLocation(data, eventData);\n\n // Mouse move -> Polygon Mode\n const handleNearby = this._pointNearHandle(element, data, coords);\n const points = data.handles.points;\n // If there is a handle nearby to snap to\n // (and it's not the actual mouse handle)\n\n if (\n handleNearby !== undefined &&\n !handleNearby.hasBoundingBox &&\n handleNearby < points.length - 1\n ) {\n config.mouseLocation.handles.start.x = points[handleNearby].x;\n config.mouseLocation.handles.start.y = points[handleNearby].y;\n }\n\n // Force onImageRendered\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Event handler for MOUSE_DRAG during drawing event loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _drawingMouseDragCallback(evt) {\n if (!this.options.mouseButtonMask.includes(evt.detail.buttons)) {\n return;\n }\n\n this._drawingDrag(evt);\n }\n\n /**\n * Event handler for TOUCH_DRAG during drawing event loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _drawingTouchDragCallback(evt) {\n this._drawingDrag(evt);\n }\n\n _drawingDrag(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n\n const toolState = getToolState(element, this.name);\n\n const config = this.configuration;\n const currentTool = config.currentTool;\n\n const data = toolState.data[currentTool];\n\n // Set the mouseLocation handle\n this._getMouseLocation(eventData);\n this._checkInvalidHandleLocation(data, eventData);\n this._addPointPencilMode(eventData, data.handles.points);\n this._dragging = true;\n\n // Force onImageRendered\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Event handler for MOUSE_UP during drawing event loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _drawingMouseUpCallback(evt) {\n const { element } = evt.detail;\n\n if (!this._dragging) {\n return;\n }\n\n this._dragging = false;\n\n const config = this.configuration;\n const currentTool = config.currentTool;\n const toolState = getToolState(element, this.name);\n const data = toolState.data[currentTool];\n\n if (!freehandIntersect.end(data.handles.points) && data.canComplete) {\n const lastHandlePlaced = config.currentHandle;\n\n this._endDrawing(element, lastHandlePlaced);\n }\n\n preventPropagation(evt);\n\n return;\n }\n\n /**\n * Event handler for MOUSE_DOWN during drawing event loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _drawingMouseDownCallback(evt) {\n const eventData = evt.detail;\n const { buttons, currentPoints, element } = eventData;\n\n if (!this.options.mouseButtonMask.includes(buttons)) {\n return;\n }\n\n const coords = currentPoints.canvas;\n\n const config = this.configuration;\n const currentTool = config.currentTool;\n const toolState = getToolState(element, this.name);\n const data = toolState.data[currentTool];\n\n const handleNearby = this._pointNearHandle(element, data, coords);\n\n if (!freehandIntersect.end(data.handles.points) && data.canComplete) {\n const lastHandlePlaced = config.currentHandle;\n\n this._endDrawing(element, lastHandlePlaced);\n } else if (handleNearby === undefined) {\n this._addPoint(eventData);\n }\n\n preventPropagation(evt);\n\n return;\n }\n\n /**\n * Event handler for TOUCH_START during drawing event loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _drawingTouchStartCallback(evt) {\n const eventData = evt.detail;\n const { currentPoints, element } = eventData;\n\n const coords = currentPoints.canvas;\n\n const config = this.configuration;\n const currentTool = config.currentTool;\n const toolState = getToolState(element, this.name);\n const data = toolState.data[currentTool];\n\n const handleNearby = this._pointNearHandle(element, data, coords);\n\n if (!freehandIntersect.end(data.handles.points) && data.canComplete) {\n const lastHandlePlaced = config.currentHandle;\n\n this._endDrawing(element, lastHandlePlaced);\n } else if (handleNearby === undefined) {\n this._addPoint(eventData);\n }\n\n preventPropagation(evt);\n\n return;\n }\n\n /** Ends the active drawing loop and completes the polygon.\n *\n * @public\n * @param {Object} element - The element on which the roi is being drawn.\n * @returns {null}\n */\n completeDrawing(element) {\n if (!this._drawing) {\n return;\n }\n const toolState = getToolState(element, this.name);\n const config = this.configuration;\n const data = toolState.data[config.currentTool];\n\n if (\n !freehandIntersect.end(data.handles.points) &&\n data.handles.points.length >= 2\n ) {\n const lastHandlePlaced = config.currentHandle;\n\n data.polyBoundingBox = {};\n this._endDrawing(element, lastHandlePlaced);\n }\n }\n\n /**\n * Event handler for MOUSE_DOUBLE_CLICK during drawing event loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _drawingMouseDoubleClickCallback(evt) {\n const { element } = evt.detail;\n\n this.completeDrawing(element);\n\n preventPropagation(evt);\n }\n\n /**\n * Event handler for DOUBLE_TAP during drawing event loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _drawingDoubleTapClickCallback(evt) {\n const { element } = evt.detail;\n\n this.completeDrawing(element);\n\n preventPropagation(evt);\n }\n\n /**\n * Event handler for MOUSE_DRAG during handle drag event loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _editMouseDragCallback(evt) {\n const eventData = evt.detail;\n const { element, buttons } = eventData;\n\n if (!this.options.mouseButtonMask.includes(buttons)) {\n return;\n }\n\n const toolState = getToolState(element, this.name);\n\n const config = this.configuration;\n const data = toolState.data[config.currentTool];\n const currentHandle = config.currentHandle;\n const points = data.handles.points;\n let handleIndex = -1;\n\n // Set the mouseLocation handle\n this._getMouseLocation(eventData);\n\n data.handles.invalidHandlePlacement = freehandIntersect.modify(\n points,\n currentHandle\n );\n data.active = true;\n data.highlight = true;\n points[currentHandle].x = config.mouseLocation.handles.start.x;\n points[currentHandle].y = config.mouseLocation.handles.start.y;\n\n handleIndex = this._getPrevHandleIndex(currentHandle, points);\n\n if (currentHandle >= 0) {\n const lastLineIndex = points[handleIndex].lines.length - 1;\n const lastLine = points[handleIndex].lines[lastLineIndex];\n\n lastLine.x = config.mouseLocation.handles.start.x;\n lastLine.y = config.mouseLocation.handles.start.y;\n }\n\n // Update the image\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Event handler for TOUCH_DRAG during handle drag event loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {void}\n */\n _editTouchDragCallback(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n\n const toolState = getToolState(element, this.name);\n\n const config = this.configuration;\n const data = toolState.data[config.currentTool];\n const currentHandle = config.currentHandle;\n const points = data.handles.points;\n let handleIndex = -1;\n\n // Set the mouseLocation handle\n this._getMouseLocation(eventData);\n\n data.handles.invalidHandlePlacement = freehandIntersect.modify(\n points,\n currentHandle\n );\n data.active = true;\n data.highlight = true;\n points[currentHandle].x = config.mouseLocation.handles.start.x;\n points[currentHandle].y = config.mouseLocation.handles.start.y;\n\n handleIndex = this._getPrevHandleIndex(currentHandle, points);\n\n if (currentHandle >= 0) {\n const lastLineIndex = points[handleIndex].lines.length - 1;\n const lastLine = points[handleIndex].lines[lastLineIndex];\n\n lastLine.x = config.mouseLocation.handles.start.x;\n lastLine.y = config.mouseLocation.handles.start.y;\n }\n\n // Update the image\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Returns the previous handle to the current one.\n * @param {Number} currentHandle - the current handle index\n * @param {Array} points - the handles Array of the freehand data\n * @returns {Number} - The index of the previos handle\n */\n _getPrevHandleIndex(currentHandle, points) {\n if (currentHandle === 0) {\n return points.length - 1;\n }\n\n return currentHandle - 1;\n }\n\n /**\n * Event handler for MOUSE_UP during handle drag event loop.\n *\n * @private\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _editMouseUpCallback(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n const toolState = getToolState(element, this.name);\n\n this._deactivateModify(element);\n\n this._dropHandle(eventData, toolState);\n this._endDrawing(element);\n\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Places a handle of the freehand tool if the new location is valid.\n * If the new location is invalid the handle snaps back to its previous position.\n *\n * @private\n * @param {Object} eventData - Data object associated with the event.\n * @param {Object} toolState - The data associated with the freehand tool.\n * @modifies {toolState}\n * @returns {undefined}\n */\n _dropHandle(eventData, toolState) {\n const config = this.configuration;\n const currentTool = config.currentTool;\n const handles = toolState.data[currentTool].handles;\n const points = handles.points;\n\n // Don't allow the line being modified to intersect other lines\n if (handles.invalidHandlePlacement) {\n const currentHandle = config.currentHandle;\n const currentHandleData = points[currentHandle];\n let previousHandleData;\n\n if (currentHandle === 0) {\n const lastHandleID = points.length - 1;\n\n previousHandleData = points[lastHandleID];\n } else {\n previousHandleData = points[currentHandle - 1];\n }\n\n // Snap back to previous position\n currentHandleData.x = config.dragOrigin.x;\n currentHandleData.y = config.dragOrigin.y;\n previousHandleData.lines[0] = currentHandleData;\n\n handles.invalidHandlePlacement = false;\n }\n }\n\n /**\n * Begining of drawing loop when tool is active and a click event happens far\n * from existing handles.\n *\n * @private\n * @param {Object} evt - The event.\n * @returns {undefined}\n */\n _startDrawing(evt) {\n const eventData = evt.detail;\n const measurementData = this.createNewMeasurement(eventData);\n const { element } = eventData;\n const config = this.configuration;\n let interactionType;\n\n if (evt.type === EVENTS.MOUSE_DOWN_ACTIVATE) {\n interactionType = 'Mouse';\n } else if (evt.type === EVENTS.TOUCH_START_ACTIVE) {\n interactionType = 'Touch';\n }\n this._activateDraw(element, interactionType);\n this._getMouseLocation(eventData);\n\n addToolState(element, this.name, measurementData);\n\n const toolState = getToolState(element, this.name);\n\n config.currentTool = toolState.data.length - 1;\n\n this._activeDrawingToolReference = toolState.data[config.currentTool];\n }\n\n /**\n * Adds a point on mouse click in polygon mode.\n *\n * @private\n * @param {Object} eventData - data object associated with an event.\n * @returns {undefined}\n */\n _addPoint(eventData) {\n const { currentPoints, element } = eventData;\n const toolState = getToolState(element, this.name);\n\n // Get the toolState from the last-drawn polygon\n const config = this.configuration;\n const data = toolState.data[config.currentTool];\n\n if (data.handles.invalidHandlePlacement) {\n return;\n }\n\n const newHandleData = new FreehandHandleData(currentPoints.image);\n\n // If this is not the first handle\n if (data.handles.points.length) {\n // Add the line from the current handle to the new handle\n data.handles.points[config.currentHandle - 1].lines.push(\n currentPoints.image\n );\n }\n\n // Add the new handle\n data.handles.points.push(newHandleData);\n\n // Increment the current handle value\n config.currentHandle += 1;\n\n // Force onImageRendered to fire\n external.cornerstone.updateImage(element);\n this.fireModifiedEvent(element, data);\n }\n\n /**\n * If in pencilMode, check the mouse position is farther than the minimum\n * distance between points, then add a point.\n *\n * @private\n * @param {Object} eventData - Data object associated with an event.\n * @param {Object} points - Data object associated with the tool.\n * @returns {undefined}\n */\n _addPointPencilMode(eventData, points) {\n const config = this.configuration;\n const { element } = eventData;\n const mousePoint = config.mouseLocation.handles.start;\n\n const handleFurtherThanMinimumSpacing = handle =>\n this._isDistanceLargerThanSpacing(element, handle, mousePoint);\n\n if (points.every(handleFurtherThanMinimumSpacing)) {\n this._addPoint(eventData);\n }\n }\n\n /**\n * Ends the active drawing loop and completes the polygon.\n *\n * @private\n * @param {Object} element - The element on which the roi is being drawn.\n * @param {Object} handleNearby - the handle nearest to the mouse cursor.\n * @returns {undefined}\n */\n _endDrawing(element, handleNearby) {\n const toolState = getToolState(element, this.name);\n const config = this.configuration;\n const data = toolState.data[config.currentTool];\n\n data.active = false;\n data.highlight = false;\n data.handles.invalidHandlePlacement = false;\n\n // Connect the end handle to the origin handle\n if (handleNearby !== undefined) {\n const points = data.handles.points;\n\n points[config.currentHandle - 1].lines.push(points[0]);\n }\n\n if (this._modifying) {\n this._modifying = false;\n data.invalidated = true;\n }\n\n // Reset the current handle\n config.currentHandle = 0;\n config.currentTool = -1;\n data.canComplete = false;\n\n if (this._drawing) {\n this._deactivateDraw(element);\n }\n\n external.cornerstone.updateImage(element);\n\n this.fireModifiedEvent(element, data);\n this.fireCompletedEvent(element, data);\n }\n\n /**\n * Returns a handle of a particular tool if it is close to the mouse cursor\n *\n * @private\n * @param {Object} element - The element on which the roi is being drawn.\n * @param {Object} data Data object associated with the tool.\n * @param {*} coords\n * @returns {Number|Object|Boolean}\n */\n _pointNearHandle(element, data, coords) {\n if (data.handles === undefined || data.handles.points === undefined) {\n return;\n }\n\n if (data.visible === false) {\n return;\n }\n\n for (let i = 0; i < data.handles.points.length; i++) {\n const handleCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.points[i]\n );\n\n if (external.cornerstoneMath.point.distance(handleCanvas, coords) < 6) {\n return i;\n }\n }\n\n // Check to see if mouse in bounding box of textbox\n if (data.handles.textBox) {\n if (pointInsideBoundingBox(data.handles.textBox, coords)) {\n return data.handles.textBox;\n }\n }\n }\n\n /**\n * Returns a handle if it is close to the mouse cursor (all tools)\n *\n * @private\n * @param {Object} eventData - data object associated with an event.\n * @returns {Object}\n */\n _pointNearHandleAllTools(eventData) {\n const { currentPoints, element } = eventData;\n const coords = currentPoints.canvas;\n const toolState = getToolState(element, this.name);\n\n if (!toolState) {\n return;\n }\n\n let handleNearby;\n\n for (let toolIndex = 0; toolIndex < toolState.data.length; toolIndex++) {\n handleNearby = this._pointNearHandle(\n element,\n toolState.data[toolIndex],\n coords\n );\n if (handleNearby !== undefined) {\n return {\n handleNearby,\n toolIndex,\n };\n }\n }\n }\n\n /**\n * Gets the current mouse location and stores it in the configuration object.\n *\n * @private\n * @param {Object} eventData The data assoicated with the event.\n * @returns {undefined}\n */\n _getMouseLocation(eventData) {\n const { currentPoints, image } = eventData;\n // Set the mouseLocation handle\n const config = this.configuration;\n\n config.mouseLocation.handles.start.x = currentPoints.image.x;\n config.mouseLocation.handles.start.y = currentPoints.image.y;\n clipToBox(config.mouseLocation.handles.start, image);\n }\n\n /**\n * Returns true if the proposed location of a new handle is invalid.\n *\n * @private\n * @param {Object} data Data object associated with the tool.\n * @param {Object} eventData The data assoicated with the event.\n * @returns {Boolean}\n */\n _checkInvalidHandleLocation(data, eventData) {\n if (data.handles.points.length < 2) {\n return true;\n }\n\n let invalidHandlePlacement;\n\n if (this._dragging) {\n invalidHandlePlacement = this._checkHandlesPencilMode(data, eventData);\n } else {\n invalidHandlePlacement = this._checkHandlesPolygonMode(data, eventData);\n }\n\n data.handles.invalidHandlePlacement = invalidHandlePlacement;\n }\n\n /**\n * Returns true if the proposed location of a new handle is invalid (in polygon mode).\n *\n * @private\n *\n * @param {Object} data - data object associated with the tool.\n * @param {Object} eventData The data assoicated with the event.\n * @returns {Boolean}\n */\n _checkHandlesPolygonMode(data, eventData) {\n const config = this.configuration;\n const { element } = eventData;\n const mousePoint = config.mouseLocation.handles.start;\n const points = data.handles.points;\n let invalidHandlePlacement = false;\n\n data.canComplete = false;\n\n const mouseAtOriginHandle = this._isDistanceSmallerThanCompleteSpacingCanvas(\n element,\n points[0],\n mousePoint\n );\n\n if (\n mouseAtOriginHandle &&\n !freehandIntersect.end(points) &&\n points.length > 2\n ) {\n data.canComplete = true;\n invalidHandlePlacement = false;\n } else {\n invalidHandlePlacement = freehandIntersect.newHandle(mousePoint, points);\n }\n\n return invalidHandlePlacement;\n }\n\n /**\n * Returns true if the proposed location of a new handle is invalid (in pencilMode).\n *\n * @private\n * @param {Object} data - data object associated with the tool.\n * @param {Object} eventData The data associated with the event.\n * @returns {Boolean}\n */\n _checkHandlesPencilMode(data, eventData) {\n const config = this.configuration;\n const mousePoint = config.mouseLocation.handles.start;\n const points = data.handles.points;\n let invalidHandlePlacement = freehandIntersect.newHandle(\n mousePoint,\n points\n );\n\n if (invalidHandlePlacement === false) {\n invalidHandlePlacement = this._invalidHandlePencilMode(data, eventData);\n }\n\n return invalidHandlePlacement;\n }\n\n /**\n * Returns true if the mouse position is far enough from previous points (in pencilMode).\n *\n * @private\n * @param {Object} data - data object associated with the tool.\n * @param {Object} eventData The data associated with the event.\n * @returns {Boolean}\n */\n _invalidHandlePencilMode(data, eventData) {\n const config = this.configuration;\n const { element } = eventData;\n const mousePoint = config.mouseLocation.handles.start;\n const points = data.handles.points;\n\n const mouseAtOriginHandle = this._isDistanceSmallerThanCompleteSpacingCanvas(\n element,\n points[0],\n mousePoint\n );\n\n if (mouseAtOriginHandle) {\n data.canComplete = true;\n\n return false;\n }\n\n data.canComplete = false;\n\n // Compare with all other handles appart from the last one\n for (let i = 1; i < points.length - 1; i++) {\n if (this._isDistanceSmallerThanSpacing(element, points[i], mousePoint)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Returns true if two points are closer than this.configuration.spacing.\n *\n * @private\n * @param {Object} element The element on which the roi is being drawn.\n * @param {Object} p1 The first point, in pixel space.\n * @param {Object} p2 The second point, in pixel space.\n * @returns {boolean} True if the distance is smaller than the\n * allowed canvas spacing.\n */\n _isDistanceSmallerThanCompleteSpacingCanvas(element, p1, p2) {\n const p1Canvas = external.cornerstone.pixelToCanvas(element, p1);\n const p2Canvas = external.cornerstone.pixelToCanvas(element, p2);\n\n let completeHandleRadius;\n\n if (this._drawingInteractionType === 'Mouse') {\n completeHandleRadius = this.configuration.completeHandleRadius;\n } else if (this._drawingInteractionType === 'Touch') {\n completeHandleRadius = this.configuration.completeHandleRadiusTouch;\n }\n\n return this._compareDistanceToSpacing(\n element,\n p1Canvas,\n p2Canvas,\n '<',\n completeHandleRadius\n );\n }\n\n /**\n * Returns true if two points are closer than this.configuration.spacing.\n *\n * @private\n * @param {Object} element The element on which the roi is being drawn.\n * @param {Object} p1 The first point, in pixel space.\n * @param {Object} p2 The second point, in pixel space.\n * @returns {boolean} True if the distance is smaller than the\n * allowed canvas spacing.\n */\n _isDistanceSmallerThanSpacing(element, p1, p2) {\n return this._compareDistanceToSpacing(element, p1, p2, '<');\n }\n\n /**\n * Returns true if two points are farther than this.configuration.spacing.\n *\n * @private\n * @param {Object} element The element on which the roi is being drawn.\n * @param {Object} p1 The first point, in pixel space.\n * @param {Object} p2 The second point, in pixel space.\n * @returns {boolean} True if the distance is smaller than the\n * allowed canvas spacing.\n */\n _isDistanceLargerThanSpacing(element, p1, p2) {\n return this._compareDistanceToSpacing(element, p1, p2, '>');\n }\n\n /**\n * Compares the distance between two points to this.configuration.spacing.\n *\n * @private\n * @param {Object} element The element on which the roi is being drawn.\n * @param {Object} p1 The first point, in pixel space.\n * @param {Object} p2 The second point, in pixel space.\n * @param {string} comparison The comparison to make.\n * @param {number} spacing The allowed canvas spacing\n * @returns {boolean} True if the distance is smaller than the\n * allowed canvas spacing.\n */\n _compareDistanceToSpacing(\n element,\n p1,\n p2,\n comparison = '>',\n spacing = this.configuration.spacing\n ) {\n if (comparison === '>') {\n return external.cornerstoneMath.point.distance(p1, p2) > spacing;\n }\n\n return external.cornerstoneMath.point.distance(p1, p2) < spacing;\n }\n\n /**\n * Adds drawing loop event listeners.\n *\n * @private\n * @param {Object} element - The viewport element to add event listeners to.\n * @param {string} interactionType - The interactionType used for the loop.\n * @modifies {element}\n * @returns {undefined}\n */\n _activateDraw(element, interactionType = 'Mouse') {\n this._drawing = true;\n this._drawingInteractionType = interactionType;\n\n state.isMultiPartToolActive = true;\n hideToolCursor(this.element);\n\n // Polygonal Mode\n element.addEventListener(EVENTS.MOUSE_DOWN, this._drawingMouseDownCallback);\n element.addEventListener(EVENTS.MOUSE_MOVE, this._drawingMouseMoveCallback);\n element.addEventListener(\n EVENTS.MOUSE_DOUBLE_CLICK,\n this._drawingMouseDoubleClickCallback\n );\n\n // Drag/Pencil Mode\n element.addEventListener(EVENTS.MOUSE_DRAG, this._drawingMouseDragCallback);\n element.addEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);\n\n // Touch\n element.addEventListener(\n EVENTS.TOUCH_START,\n this._drawingMouseMoveCallback\n );\n element.addEventListener(\n EVENTS.TOUCH_START,\n this._drawingTouchStartCallback\n );\n\n element.addEventListener(EVENTS.TOUCH_DRAG, this._drawingTouchDragCallback);\n element.addEventListener(EVENTS.TOUCH_END, this._drawingMouseUpCallback);\n element.addEventListener(\n EVENTS.DOUBLE_TAP,\n this._drawingDoubleTapClickCallback\n );\n\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Removes drawing loop event listeners.\n *\n * @private\n * @param {Object} element - The viewport element to add event listeners to.\n * @modifies {element}\n * @returns {undefined}\n */\n _deactivateDraw(element) {\n this._drawing = false;\n state.isMultiPartToolActive = false;\n this._activeDrawingToolReference = null;\n this._drawingInteractionType = null;\n setToolCursor(this.element, this.svgCursor);\n\n element.removeEventListener(\n EVENTS.MOUSE_DOWN,\n this._drawingMouseDownCallback\n );\n element.removeEventListener(\n EVENTS.MOUSE_MOVE,\n this._drawingMouseMoveCallback\n );\n element.removeEventListener(\n EVENTS.MOUSE_DOUBLE_CLICK,\n this._drawingMouseDoubleClickCallback\n );\n element.removeEventListener(\n EVENTS.MOUSE_DRAG,\n this._drawingMouseDragCallback\n );\n element.removeEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);\n\n // Touch\n element.removeEventListener(\n EVENTS.TOUCH_START,\n this._drawingTouchStartCallback\n );\n element.removeEventListener(\n EVENTS.TOUCH_DRAG,\n this._drawingTouchDragCallback\n );\n element.removeEventListener(\n EVENTS.TOUCH_START,\n this._drawingMouseMoveCallback\n );\n element.removeEventListener(EVENTS.TOUCH_END, this._drawingMouseUpCallback);\n\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Adds modify loop event listeners.\n *\n * @private\n * @param {Object} element - The viewport element to add event listeners to.\n * @modifies {element}\n * @returns {undefined}\n */\n _activateModify(element) {\n state.isToolLocked = true;\n\n element.addEventListener(EVENTS.MOUSE_UP, this._editMouseUpCallback);\n element.addEventListener(EVENTS.MOUSE_DRAG, this._editMouseDragCallback);\n element.addEventListener(EVENTS.MOUSE_CLICK, this._editMouseUpCallback);\n\n element.addEventListener(EVENTS.TOUCH_END, this._editMouseUpCallback);\n element.addEventListener(EVENTS.TOUCH_DRAG, this._editTouchDragCallback);\n\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Removes modify loop event listeners.\n *\n * @private\n * @param {Object} element - The viewport element to add event listeners to.\n * @modifies {element}\n * @returns {undefined}\n */\n _deactivateModify(element) {\n state.isToolLocked = false;\n\n element.removeEventListener(EVENTS.MOUSE_UP, this._editMouseUpCallback);\n element.removeEventListener(EVENTS.MOUSE_DRAG, this._editMouseDragCallback);\n element.removeEventListener(EVENTS.MOUSE_CLICK, this._editMouseUpCallback);\n\n element.removeEventListener(EVENTS.TOUCH_END, this._editMouseUpCallback);\n element.removeEventListener(EVENTS.TOUCH_DRAG, this._editTouchDragCallback);\n\n external.cornerstone.updateImage(element);\n }\n\n passiveCallback(element) {\n this._closeToolIfDrawing(element);\n }\n\n enabledCallback(element) {\n this._closeToolIfDrawing(element);\n }\n\n disabledCallback(element) {\n this._closeToolIfDrawing(element);\n }\n\n _closeToolIfDrawing(element) {\n if (this._drawing) {\n // Actively drawing but changed mode.\n const config = this.configuration;\n const lastHandlePlaced = config.currentHandle;\n\n this._endDrawing(element, lastHandlePlaced);\n external.cornerstone.updateImage(element);\n }\n }\n\n /**\n * Fire MEASUREMENT_MODIFIED event on provided element\n * @param {any} element which freehand data has been modified\n * @param {any} measurementData the measurment data\n * @returns {void}\n */\n fireModifiedEvent(element, measurementData) {\n const eventType = EVENTS.MEASUREMENT_MODIFIED;\n const eventData = {\n toolName: this.name,\n element,\n measurementData,\n };\n\n triggerEvent(element, eventType, eventData);\n }\n\n fireCompletedEvent(element, measurementData) {\n const eventType = EVENTS.MEASUREMENT_COMPLETED;\n const eventData = {\n toolName: this.name,\n element,\n measurementData,\n };\n\n triggerEvent(element, eventType, eventData);\n }\n\n // ===================================================================\n // Public Configuration API. .\n // ===================================================================\n\n get spacing() {\n return this.configuration.spacing;\n }\n\n set spacing(value) {\n if (typeof value !== 'number') {\n throw new Error(\n 'Attempting to set freehand spacing to a value other than a number.'\n );\n }\n\n this.configuration.spacing = value;\n external.cornerstone.updateImage(this.element);\n }\n\n get activeHandleRadius() {\n return this.configuration.activeHandleRadius;\n }\n\n set activeHandleRadius(value) {\n if (typeof value !== 'number') {\n throw new Error(\n 'Attempting to set freehand activeHandleRadius to a value other than a number.'\n );\n }\n\n this.configuration.activeHandleRadius = value;\n external.cornerstone.updateImage(this.element);\n }\n\n get completeHandleRadius() {\n return this.configuration.completeHandleRadius;\n }\n\n set completeHandleRadius(value) {\n if (typeof value !== 'number') {\n throw new Error(\n 'Attempting to set freehand completeHandleRadius to a value other than a number.'\n );\n }\n\n this.configuration.completeHandleRadius = value;\n external.cornerstone.updateImage(this.element);\n }\n\n get alwaysShowHandles() {\n return this.configuration.alwaysShowHandles;\n }\n\n set alwaysShowHandles(value) {\n if (typeof value !== 'boolean') {\n throw new Error(\n 'Attempting to set freehand alwaysShowHandles to a value other than a boolean.'\n );\n }\n\n this.configuration.alwaysShowHandles = value;\n external.cornerstone.updateImage(this.element);\n }\n\n get invalidColor() {\n return this.configuration.invalidColor;\n }\n\n set invalidColor(value) {\n /*\n It'd be easy to check if the color was e.g. a valid rgba color. However\n it'd be difficult to check if the color was a named CSS color without\n bloating the library, so we don't. If the canvas can't intepret the color\n it'll show up grey.\n */\n\n this.configuration.invalidColor = value;\n external.cornerstone.updateImage(this.element);\n }\n\n /**\n * Ends the active drawing loop and removes the polygon.\n *\n * @public\n * @param {Object} element - The element on which the roi is being drawn.\n * @returns {null}\n */\n cancelDrawing(element) {\n if (!this._drawing) {\n return;\n }\n const toolState = getToolState(element, this.name);\n\n const config = this.configuration;\n\n const data = toolState.data[config.currentTool];\n\n data.active = false;\n data.highlight = false;\n data.handles.invalidHandlePlacement = false;\n\n // Reset the current handle\n config.currentHandle = 0;\n config.currentTool = -1;\n data.canComplete = false;\n\n removeToolState(element, this.name, data);\n\n this._deactivateDraw(element);\n\n external.cornerstone.updateImage(element);\n }\n\n /**\n * New image event handler.\n *\n * @public\n * @param {Object} evt The event.\n * @returns {null}\n */\n newImageCallback(evt) {\n const config = this.configuration;\n\n if (!(this._drawing && this._activeDrawingToolReference)) {\n return;\n }\n\n // Actively drawing but scrolled to different image.\n\n const element = evt.detail.element;\n const data = this._activeDrawingToolReference;\n\n data.active = false;\n data.highlight = false;\n data.handles.invalidHandlePlacement = false;\n\n // Connect the end handle to the origin handle\n const points = data.handles.points;\n\n points[config.currentHandle - 1].lines.push(points[0]);\n\n // Reset the current handle\n config.currentHandle = 0;\n config.currentTool = -1;\n data.canComplete = false;\n\n this._deactivateDraw(element);\n\n external.cornerstone.updateImage(element);\n }\n}\n\nfunction defaultFreehandConfiguration() {\n return {\n mouseLocation: {\n handles: {\n start: {\n highlight: true,\n active: true,\n },\n },\n },\n spacing: 1,\n activeHandleRadius: 3,\n completeHandleRadius: 6,\n completeHandleRadiusTouch: 28,\n alwaysShowHandles: false,\n invalidColor: 'crimson',\n currentHandle: 0,\n currentTool: -1,\n };\n}\n\nfunction preventPropagation(evt) {\n evt.stopImmediatePropagation();\n evt.stopPropagation();\n evt.preventDefault();\n}\n","import BaseAnnotationTool from '../base/BaseAnnotationTool.js';\n// State\nimport { getToolState } from './../../stateManagement/toolState.js';\nimport toolStyle from './../../stateManagement/toolStyle.js';\nimport toolColors from './../../stateManagement/toolColors.js';\n// Drawing\nimport {\n getNewContext,\n draw,\n setShadow,\n drawLine,\n} from './../../drawing/index.js';\nimport drawLinkedTextBox from './../../drawing/drawLinkedTextBox.js';\nimport drawHandles from './../../drawing/drawHandles.js';\nimport lineSegDistance from './../../util/lineSegDistance.js';\nimport { lengthCursor } from '../cursors/index.js';\nimport { getLogger } from '../../util/logger.js';\nimport getPixelSpacing from '../../util/getPixelSpacing';\nimport throttle from '../../util/throttle';\n\nconst logger = getLogger('tools:annotation:LengthTool');\n\n/**\n * @public\n * @class LengthTool\n * @memberof Tools.Annotation\n * @classdesc Tool for measuring distances.\n * @extends Tools.Base.BaseAnnotationTool\n */\nexport default class LengthTool extends BaseAnnotationTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Length',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: lengthCursor,\n };\n\n super(props, defaultProps);\n\n this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);\n }\n\n createNewMeasurement(eventData) {\n const goodEventData =\n eventData && eventData.currentPoints && eventData.currentPoints.image;\n\n if (!goodEventData) {\n logger.error(\n `required eventData not supplied to tool ${this.name}'s createNewMeasurement`\n );\n\n return;\n }\n\n const { x, y } = eventData.currentPoints.image;\n\n return {\n visible: true,\n active: true,\n color: undefined,\n invalidated: true,\n handles: {\n start: {\n x,\n y,\n highlight: true,\n active: false,\n },\n end: {\n x,\n y,\n highlight: true,\n active: true,\n },\n textBox: {\n active: false,\n hasMoved: false,\n movesIndependently: false,\n drawnIndependently: true,\n allowedOutsideImage: true,\n hasBoundingBox: true,\n },\n },\n };\n }\n\n /**\n *\n *\n * @param {*} element\n * @param {*} data\n * @param {*} coords\n * @returns {Boolean}\n */\n pointNearTool(element, data, coords) {\n const hasStartAndEndHandles =\n data && data.handles && data.handles.start && data.handles.end;\n const validParameters = hasStartAndEndHandles;\n\n if (!validParameters) {\n logger.warn(\n `invalid parameters supplied to tool ${this.name}'s pointNearTool`\n );\n\n return false;\n }\n\n if (data.visible === false) {\n return false;\n }\n\n return (\n lineSegDistance(element, data.handles.start, data.handles.end, coords) <\n 25\n );\n }\n\n updateCachedStats(image, element, data) {\n const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);\n\n // Set rowPixelSpacing and columnPixelSpacing to 1 if they are undefined (or zero)\n const dx =\n (data.handles.end.x - data.handles.start.x) * (colPixelSpacing || 1);\n const dy =\n (data.handles.end.y - data.handles.start.y) * (rowPixelSpacing || 1);\n\n // Calculate the length, and create the text variable with the millimeters or pixels suffix\n const length = Math.sqrt(dx * dx + dy * dy);\n\n // Store the length inside the tool for outside access\n data.length = length;\n data.invalidated = false;\n }\n\n renderToolData(evt) {\n const eventData = evt.detail;\n const { handleRadius, drawHandlesOnHover } = this.configuration;\n const toolData = getToolState(evt.currentTarget, this.name);\n\n if (!toolData) {\n return;\n }\n\n // We have tool data for this element - iterate over each one and draw it\n const context = getNewContext(eventData.canvasContext.canvas);\n const { image, element } = eventData;\n const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);\n\n const lineWidth = toolStyle.getToolWidth();\n\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n draw(context, context => {\n // Configurable shadow\n setShadow(context, this.configuration);\n\n const color = toolColors.getColorIfActive(data);\n\n // Draw the measurement line\n drawLine(context, element, data.handles.start, data.handles.end, {\n color,\n });\n\n // Draw the handles\n const handleOptions = {\n color,\n handleRadius,\n drawHandlesIfActive: drawHandlesOnHover,\n };\n\n drawHandles(context, eventData, data.handles, handleOptions);\n\n if (!data.handles.textBox.hasMoved) {\n const coords = {\n x: Math.max(data.handles.start.x, data.handles.end.x),\n };\n\n // Depending on which handle has the largest x-value,\n // Set the y-value for the text box\n if (coords.x === data.handles.start.x) {\n coords.y = data.handles.start.y;\n } else {\n coords.y = data.handles.end.y;\n }\n\n data.handles.textBox.x = coords.x;\n data.handles.textBox.y = coords.y;\n }\n\n // Move the textbox slightly to the right and upwards\n // So that it sits beside the length tool handle\n const xOffset = 10;\n\n // Update textbox stats\n if (data.invalidated === true) {\n if (data.length) {\n this.throttledUpdateCachedStats(image, element, data);\n } else {\n this.updateCachedStats(image, element, data);\n }\n }\n\n const text = textBoxText(data, rowPixelSpacing, colPixelSpacing);\n\n drawLinkedTextBox(\n context,\n element,\n data.handles.textBox,\n text,\n data.handles,\n textBoxAnchorPoints,\n color,\n lineWidth,\n xOffset,\n true\n );\n });\n }\n\n function textBoxText(data, rowPixelSpacing, colPixelSpacing) {\n // Set the length text suffix depending on whether or not pixelSpacing is available\n let suffix = 'mm';\n\n if (!rowPixelSpacing || !colPixelSpacing) {\n suffix = 'pixels';\n }\n\n data.unit = suffix;\n\n return `${data.length.toFixed(2)} ${suffix}`;\n }\n\n function textBoxAnchorPoints(handles) {\n const midpoint = {\n x: (handles.start.x + handles.end.x) / 2,\n y: (handles.start.y + handles.end.y) / 2,\n };\n\n return [handles.start, midpoint, handles.end];\n }\n }\n}\n","import external from '../externalModules.js';\n\n/**\n * Gets pixels of an RGB image.\n * @export @public @method\n * @name getRGBPixels\n *\n * @param {HTMLElement} element The element.\n * @param {number} x The x position of the top-left corner of the region.\n * @param {number} y The y position of the top-left corner of the region.\n * @param {number} width The width of the region.\n * @param {number} height The height of the region\n * @returns {number[]} The pixel data.\n */\nexport default function(element, x, y, width, height) {\n if (!element) {\n throw new Error('getRGBPixels: parameter element must not be undefined');\n }\n\n x = Math.round(x);\n y = Math.round(y);\n const enabledElement = external.cornerstone.getEnabledElement(element);\n const storedPixelData = [];\n let index = 0;\n const pixelData = enabledElement.image.getPixelData();\n let spIndex, row, column;\n\n if (enabledElement.image.color) {\n for (row = 0; row < height; row++) {\n for (column = 0; column < width; column++) {\n spIndex = ((row + y) * enabledElement.image.columns + (column + x)) * 4;\n const red = pixelData[spIndex];\n const green = pixelData[spIndex + 1];\n const blue = pixelData[spIndex + 2];\n const alpha = pixelData[spIndex + 3];\n\n storedPixelData[index++] = red;\n storedPixelData[index++] = green;\n storedPixelData[index++] = blue;\n storedPixelData[index++] = alpha;\n }\n }\n }\n\n return storedPixelData;\n}\n","import external from '../../externalModules.js';\nimport BaseAnnotationTool from '../base/BaseAnnotationTool.js';\n// State\nimport { getToolState } from '../../stateManagement/toolState.js';\nimport textStyle from '../../stateManagement/textStyle.js';\nimport toolColors from '../../stateManagement/toolColors.js';\n// Drawing\nimport { getNewContext, draw } from '../../drawing/index.js';\nimport drawTextBox from '../../drawing/drawTextBox.js';\nimport drawHandles from '../../drawing/drawHandles.js';\n// Utilities\nimport getRGBPixels from '../../util/getRGBPixels.js';\nimport calculateSUV from '../../util/calculateSUV.js';\nimport { probeCursor } from '../cursors/index.js';\nimport { getLogger } from '../../util/logger.js';\nimport throttle from '../../util/throttle';\n\nconst logger = getLogger('tools:annotation:ProbeTool');\n\n/**\n * @public\n * @class ProbeTool\n * @memberof Tools.Annotation\n * @classdesc Tool which provides a probe of the image data at the\n * desired position.\n * @extends Tools.Base.BaseAnnotationTool\n */\nexport default class ProbeTool extends BaseAnnotationTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Probe',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: probeCursor,\n };\n\n super(props, defaultProps);\n\n this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);\n }\n\n createNewMeasurement(eventData) {\n const goodEventData =\n eventData && eventData.currentPoints && eventData.currentPoints.image;\n\n if (!goodEventData) {\n logger.error(\n `required eventData not supplied to tool ${this.name}'s createNewMeasurement`\n );\n\n return;\n }\n\n return {\n visible: true,\n active: true,\n color: undefined,\n invalidated: true,\n handles: {\n end: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: true,\n },\n },\n };\n }\n\n /**\n *\n *\n * @param {*} element\n * @param {*} data\n * @param {*} coords\n * @returns {Boolean}\n */\n pointNearTool(element, data, coords) {\n const hasEndHandle = data && data.handles && data.handles.end;\n const validParameters = hasEndHandle;\n\n if (!validParameters) {\n logger.warn(\n `invalid parameters supplied to tool ${this.name}'s pointNearTool`\n );\n }\n\n if (!validParameters || data.visible === false) {\n return false;\n }\n\n const probeCoords = external.cornerstone.pixelToCanvas(\n element,\n data.handles.end\n );\n\n return external.cornerstoneMath.point.distance(probeCoords, coords) < 5;\n }\n\n updateCachedStats(image, element, data) {\n const x = Math.round(data.handles.end.x);\n const y = Math.round(data.handles.end.y);\n\n const stats = {};\n\n if (x >= 0 && y >= 0 && x < image.columns && y < image.rows) {\n stats.x = x;\n stats.y = y;\n\n if (image.color) {\n stats.storedPixels = getRGBPixels(element, x, y, 1, 1);\n } else {\n stats.storedPixels = external.cornerstone.getStoredPixels(\n element,\n x,\n y,\n 1,\n 1\n );\n stats.sp = stats.storedPixels[0];\n stats.mo = stats.sp * image.slope + image.intercept;\n stats.suv = calculateSUV(image, stats.sp);\n }\n }\n\n data.cachedStats = stats;\n data.invalidated = false;\n }\n\n renderToolData(evt) {\n const eventData = evt.detail;\n const { handleRadius } = this.configuration;\n const toolData = getToolState(evt.currentTarget, this.name);\n\n if (!toolData) {\n return;\n }\n\n // We have tool data for this element - iterate over each one and draw it\n const context = getNewContext(eventData.canvasContext.canvas);\n const { image, element } = eventData;\n const fontHeight = textStyle.getFontSize();\n\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n draw(context, context => {\n const color = toolColors.getColorIfActive(data);\n\n // Draw the handles\n drawHandles(context, eventData, data.handles, {\n handleRadius,\n color,\n });\n\n // Update textbox stats\n if (data.invalidated === true) {\n if (data.cachedStats) {\n this.throttledUpdateCachedStats(image, element, data);\n } else {\n this.updateCachedStats(image, element, data);\n }\n }\n\n let text, str;\n\n const { x, y, storedPixels, sp, mo, suv } = data.cachedStats;\n\n if (x >= 0 && y >= 0 && x < image.columns && y < image.rows) {\n text = `${x}, ${y}`;\n\n if (image.color) {\n str = `R: ${storedPixels[0]} G: ${storedPixels[1]} B: ${\n storedPixels[2]\n }`;\n } else {\n // Draw text\n str = `SP: ${sp} MO: ${parseFloat(mo.toFixed(3))}`;\n if (suv) {\n str += ` SUV: ${parseFloat(suv.toFixed(3))}`;\n }\n }\n\n // Coords for text\n const coords = {\n // Translate the x/y away from the cursor\n x: data.handles.end.x + 3,\n y: data.handles.end.y - 3,\n };\n const textCoords = external.cornerstone.pixelToCanvas(\n eventData.element,\n coords\n );\n\n drawTextBox(\n context,\n str,\n textCoords.x,\n textCoords.y + fontHeight + 5,\n color\n );\n drawTextBox(context, text, textCoords.x, textCoords.y, color);\n }\n });\n }\n }\n}\n","import external from './../../externalModules.js';\nimport BaseAnnotationTool from '../base/BaseAnnotationTool.js';\n\n// State\nimport { getToolState } from './../../stateManagement/toolState.js';\nimport toolStyle from './../../stateManagement/toolStyle.js';\nimport toolColors from './../../stateManagement/toolColors.js';\n\n// Drawing\nimport {\n getNewContext,\n draw,\n drawHandles,\n drawRect,\n drawLinkedTextBox,\n setShadow,\n} from './../../drawing/index.js';\n\n// Util\nimport calculateSUV from './../../util/calculateSUV.js';\nimport getROITextBoxCoords from '../../util/getROITextBoxCoords.js';\nimport numbersWithCommas from './../../util/numbersWithCommas.js';\nimport throttle from './../../util/throttle.js';\nimport { rectangleRoiCursor } from '../cursors/index.js';\nimport { getLogger } from '../../util/logger.js';\nimport getPixelSpacing from '../../util/getPixelSpacing';\n\nconst logger = getLogger('tools:annotation:RectangleRoiTool');\n\n/**\n * @public\n * @class RectangleRoiTool\n * @memberof Tools.Annotation\n * @classdesc Tool for drawing rectangular regions of interest, and measuring\n * the statistics of the enclosed pixels.\n * @extends Tools.Base.BaseAnnotationTool\n */\nexport default class RectangleRoiTool extends BaseAnnotationTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'RectangleRoi',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {\n // showMinMax: false,\n // showHounsfieldUnits: true\n },\n svgCursor: rectangleRoiCursor,\n };\n\n super(props, defaultProps);\n\n this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);\n }\n\n createNewMeasurement(eventData) {\n const goodEventData =\n eventData && eventData.currentPoints && eventData.currentPoints.image;\n\n if (!goodEventData) {\n logger.error(\n `required eventData not supplied to tool ${this.name}'s createNewMeasurement`\n );\n\n return;\n }\n\n return {\n visible: true,\n active: true,\n color: undefined,\n invalidated: true,\n handles: {\n start: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: false,\n },\n end: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: true,\n },\n initialRotation: eventData.viewport.rotation,\n textBox: {\n active: false,\n hasMoved: false,\n movesIndependently: false,\n drawnIndependently: true,\n allowedOutsideImage: true,\n hasBoundingBox: true,\n },\n },\n };\n }\n\n pointNearTool(element, data, coords, interactionType) {\n const hasStartAndEndHandles =\n data && data.handles && data.handles.start && data.handles.end;\n const validParameters = hasStartAndEndHandles;\n\n if (!validParameters) {\n logger.warn(\n `invalid parameters supplied to tool ${this.name}'s pointNearTool`\n );\n }\n\n if (!validParameters || data.visible === false) {\n return false;\n }\n\n const distance = interactionType === 'mouse' ? 15 : 25;\n const startCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.start\n );\n const endCanvas = external.cornerstone.pixelToCanvas(\n element,\n data.handles.end\n );\n\n const rect = {\n left: Math.min(startCanvas.x, endCanvas.x),\n top: Math.min(startCanvas.y, endCanvas.y),\n width: Math.abs(startCanvas.x - endCanvas.x),\n height: Math.abs(startCanvas.y - endCanvas.y),\n };\n\n const distanceToPoint = external.cornerstoneMath.rect.distanceToPoint(\n rect,\n coords\n );\n\n return distanceToPoint < distance;\n }\n\n updateCachedStats(image, element, data) {\n const seriesModule =\n external.cornerstone.metaData.get('generalSeriesModule', image.imageId) ||\n {};\n const modality = seriesModule.modality;\n const pixelSpacing = getPixelSpacing(image);\n\n const stats = _calculateStats(\n image,\n element,\n data.handles,\n modality,\n pixelSpacing\n );\n\n data.cachedStats = stats;\n data.invalidated = false;\n }\n\n renderToolData(evt) {\n const toolData = getToolState(evt.currentTarget, this.name);\n\n if (!toolData) {\n return;\n }\n\n const eventData = evt.detail;\n const { image, element } = eventData;\n const lineWidth = toolStyle.getToolWidth();\n const { handleRadius, drawHandlesOnHover } = this.configuration;\n const context = getNewContext(eventData.canvasContext.canvas);\n const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);\n\n // Meta\n const seriesModule =\n external.cornerstone.metaData.get('generalSeriesModule', image.imageId) ||\n {};\n\n // Pixel Spacing\n const modality = seriesModule.modality;\n const hasPixelSpacing = rowPixelSpacing && colPixelSpacing;\n\n draw(context, context => {\n // If we have tool data for this element - iterate over each set and draw it\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n // Configure\n const color = toolColors.getColorIfActive(data);\n const handleOptions = {\n color,\n handleRadius,\n drawHandlesIfActive: drawHandlesOnHover,\n };\n\n setShadow(context, this.configuration);\n\n // Draw\n drawRect(\n context,\n element,\n data.handles.start,\n data.handles.end,\n {\n color,\n },\n 'pixel',\n data.handles.initialRotation\n );\n drawHandles(context, eventData, data.handles, handleOptions);\n\n // Update textbox stats\n if (data.invalidated === true) {\n if (data.cachedStats) {\n this.throttledUpdateCachedStats(image, element, data);\n } else {\n this.updateCachedStats(image, element, data);\n }\n }\n\n // Default to textbox on right side of ROI\n if (!data.handles.textBox.hasMoved) {\n const defaultCoords = getROITextBoxCoords(\n eventData.viewport,\n data.handles\n );\n\n Object.assign(data.handles.textBox, defaultCoords);\n }\n\n const textBoxAnchorPoints = handles =>\n _findTextBoxAnchorPoints(handles.start, handles.end);\n const textBoxContent = _createTextBoxContent(\n context,\n image.color,\n data.cachedStats,\n modality,\n hasPixelSpacing,\n this.configuration\n );\n\n data.unit = _getUnit(modality, this.configuration.showHounsfieldUnits);\n\n drawLinkedTextBox(\n context,\n element,\n data.handles.textBox,\n textBoxContent,\n data.handles,\n textBoxAnchorPoints,\n color,\n lineWidth,\n 10,\n true\n );\n }\n });\n }\n}\n\n/**\n * TODO: This is the same method (+ GetPixels) for the other ROIs\n * TODO: The pixel filtering is the unique bit\n *\n * @param {*} startHandle\n * @param {*} endHandle\n * @returns {{ left: number, top: number, width: number, height: number}}\n */\nfunction _getRectangleImageCoordinates(startHandle, endHandle) {\n return {\n left: Math.min(startHandle.x, endHandle.x),\n top: Math.min(startHandle.y, endHandle.y),\n width: Math.abs(startHandle.x - endHandle.x),\n height: Math.abs(startHandle.y - endHandle.y),\n };\n}\n\n/**\n *\n *\n * @param {*} image\n * @param {*} element\n * @param {*} handles\n * @param {*} modality\n * @param {*} pixelSpacing\n * @returns {Object} The Stats object\n */\nfunction _calculateStats(image, element, handles, modality, pixelSpacing) {\n // Retrieve the bounds of the rectangle in image coordinates\n const roiCoordinates = _getRectangleImageCoordinates(\n handles.start,\n handles.end\n );\n\n // Retrieve the array of pixels that the rectangle bounds cover\n const pixels = external.cornerstone.getPixels(\n element,\n roiCoordinates.left,\n roiCoordinates.top,\n roiCoordinates.width,\n roiCoordinates.height\n );\n\n // Calculate the mean & standard deviation from the pixels and the rectangle details\n const roiMeanStdDev = _calculateRectangleStats(pixels, roiCoordinates);\n\n let meanStdDevSUV;\n\n if (modality === 'PT') {\n meanStdDevSUV = {\n mean: calculateSUV(image, roiMeanStdDev.mean, true) || 0,\n stdDev: calculateSUV(image, roiMeanStdDev.stdDev, true) || 0,\n };\n }\n\n // Calculate the image area from the rectangle dimensions and pixel spacing\n const area =\n roiCoordinates.width *\n (pixelSpacing.colPixelSpacing || 1) *\n (roiCoordinates.height * (pixelSpacing.rowPixelSpacing || 1));\n\n return {\n area: area || 0,\n count: roiMeanStdDev.count || 0,\n mean: roiMeanStdDev.mean || 0,\n variance: roiMeanStdDev.variance || 0,\n stdDev: roiMeanStdDev.stdDev || 0,\n min: roiMeanStdDev.min || 0,\n max: roiMeanStdDev.max || 0,\n meanStdDevSUV,\n };\n}\n\n/**\n *\n *\n * @param {*} sp\n * @param {*} rectangle\n * @returns {{ count, number, mean: number, variance: number, stdDev: number, min: number, max: number }}\n */\nfunction _calculateRectangleStats(sp, rectangle) {\n let sum = 0;\n let sumSquared = 0;\n let count = 0;\n let index = 0;\n let min = sp ? sp[0] : null;\n let max = sp ? sp[0] : null;\n\n for (let y = rectangle.top; y < rectangle.top + rectangle.height; y++) {\n for (let x = rectangle.left; x < rectangle.left + rectangle.width; x++) {\n sum += sp[index];\n sumSquared += sp[index] * sp[index];\n min = Math.min(min, sp[index]);\n max = Math.max(max, sp[index]);\n count++; // TODO: Wouldn't this just be sp.length?\n index++;\n }\n }\n\n if (count === 0) {\n return {\n count,\n mean: 0.0,\n variance: 0.0,\n stdDev: 0.0,\n min: 0.0,\n max: 0.0,\n };\n }\n\n const mean = sum / count;\n const variance = sumSquared / count - mean * mean;\n\n return {\n count,\n mean,\n variance,\n stdDev: Math.sqrt(variance),\n min,\n max,\n };\n}\n\n/**\n *\n *\n * @param {*} startHandle\n * @param {*} endHandle\n * @returns {Array.<{x: number, y: number}>}\n */\nfunction _findTextBoxAnchorPoints(startHandle, endHandle) {\n const { left, top, width, height } = _getRectangleImageCoordinates(\n startHandle,\n endHandle\n );\n\n return [\n {\n // Top middle point of rectangle\n x: left + width / 2,\n y: top,\n },\n {\n // Left middle point of rectangle\n x: left,\n y: top + height / 2,\n },\n {\n // Bottom middle point of rectangle\n x: left + width / 2,\n y: top + height,\n },\n {\n // Right middle point of rectangle\n x: left + width,\n y: top + height / 2,\n },\n ];\n}\n\n/**\n *\n *\n * @param {*} area\n * @param {*} hasPixelSpacing\n * @returns {string} The formatted label for showing area\n */\nfunction _formatArea(area, hasPixelSpacing) {\n // This uses Char code 178 for a superscript 2\n const suffix = hasPixelSpacing\n ? ` mm${String.fromCharCode(178)}`\n : ` px${String.fromCharCode(178)}`;\n\n return `Area: ${numbersWithCommas(area.toFixed(2))}${suffix}`;\n}\n\nfunction _getUnit(modality, showHounsfieldUnits) {\n return modality === 'CT' && showHounsfieldUnits !== false ? 'HU' : '';\n}\n\n/**\n * TODO: This is identical to EllipticalROI's same fn\n * TODO: We may want to make this a utility for ROIs with these values?\n *\n * @param {*} context\n * @param {*} isColorImage\n * @param {*} { area, mean, stdDev, min, max, meanStdDevSUV }\n * @param {*} modality\n * @param {*} hasPixelSpacing\n * @param {*} [options={}]\n * @returns {string[]}\n */\nfunction _createTextBoxContent(\n context,\n isColorImage,\n { area, mean, stdDev, min, max, meanStdDevSUV },\n modality,\n hasPixelSpacing,\n options = {}\n) {\n const showMinMax = options.showMinMax || false;\n const textLines = [];\n\n const otherLines = [];\n\n if (!isColorImage) {\n const hasStandardUptakeValues = meanStdDevSUV && meanStdDevSUV.mean !== 0;\n const unit = _getUnit(modality, options.showHounsfieldUnits);\n\n let meanString = `Mean: ${numbersWithCommas(mean.toFixed(2))} ${unit}`;\n const stdDevString = `Std Dev: ${numbersWithCommas(\n stdDev.toFixed(2)\n )} ${unit}`;\n\n // If this image has SUV values to display, concatenate them to the text line\n if (hasStandardUptakeValues) {\n const SUVtext = ' SUV: ';\n\n const meanSuvString = `${SUVtext}${numbersWithCommas(\n meanStdDevSUV.mean.toFixed(2)\n )}`;\n const stdDevSuvString = `${SUVtext}${numbersWithCommas(\n meanStdDevSUV.stdDev.toFixed(2)\n )}`;\n\n const targetStringLength = Math.floor(\n context.measureText(`${stdDevString} `).width\n );\n\n while (context.measureText(meanString).width < targetStringLength) {\n meanString += ' ';\n }\n\n otherLines.push(`${meanString}${meanSuvString}`);\n otherLines.push(`${stdDevString} ${stdDevSuvString}`);\n } else {\n otherLines.push(`${meanString} ${stdDevString}`);\n }\n\n if (showMinMax) {\n let minString = `Min: ${min} ${unit}`;\n const maxString = `Max: ${max} ${unit}`;\n const targetStringLength = hasStandardUptakeValues\n ? Math.floor(context.measureText(`${stdDevString} `).width)\n : Math.floor(context.measureText(`${meanString} `).width);\n\n while (context.measureText(minString).width < targetStringLength) {\n minString += ' ';\n }\n\n otherLines.push(`${minString}${maxString}`);\n }\n }\n\n textLines.push(_formatArea(area, hasPixelSpacing));\n otherLines.forEach(x => textLines.push(x));\n\n return textLines;\n}\n","import BaseAnnotationTool from '../base/BaseAnnotationTool.js';\nimport external from './../../externalModules.js';\nimport pointInsideBoundingBox from './../../util/pointInsideBoundingBox.js';\nimport toolColors from './../../stateManagement/toolColors.js';\nimport { getNewContext, draw, setShadow } from './../../drawing/index.js';\nimport drawTextBox from './../../drawing/drawTextBox.js';\nimport {\n removeToolState,\n getToolState,\n} from './../../stateManagement/toolState.js';\nimport { textMarkerCursor } from '../cursors/index.js';\n\n/**\n * @public\n * @class TextMarkerTool\n * @memberof Tools.Annotation\n *\n * @classdesc Tool for annotating an image with text markers.\n * @extends Tools.Base.BaseAnnotationTool\n */\nexport default class TextMarkerTool extends BaseAnnotationTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'TextMarker',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {\n markers: [],\n current: '',\n ascending: true,\n loop: false,\n changeTextCallback,\n },\n svgCursor: textMarkerCursor,\n };\n\n super(props, defaultProps);\n this.touchPressCallback = this._changeText.bind(this);\n this.doubleClickCallback = this._changeText.bind(this);\n }\n\n createNewMeasurement(eventData) {\n const config = this.configuration;\n\n if (!config.current) {\n return;\n }\n\n // Create the measurement data for this tool with the end handle activated\n const measurementData = {\n visible: true,\n active: true,\n text: config.current,\n color: undefined,\n handles: {\n end: {\n x: eventData.currentPoints.image.x,\n y: eventData.currentPoints.image.y,\n highlight: true,\n active: true,\n hasBoundingBox: true,\n },\n },\n };\n\n // Create a rectangle representing the image\n const imageRect = {\n left: 0,\n top: 0,\n width: eventData.image.width,\n height: eventData.image.height,\n };\n\n // Check if the current handle is outside the image,\n // If it is, prevent the handle creation\n if (\n !external.cornerstoneMath.point.insideRect(\n measurementData.handles.end,\n imageRect\n )\n ) {\n return;\n }\n\n // Update the current marker for the next marker\n let currentIndex = config.markers.indexOf(config.current);\n\n const increment = config.ascending ? 1 : -1;\n\n currentIndex += increment;\n\n if (currentIndex >= config.markers.length) {\n currentIndex = config.loop ? 0 : -1;\n } else if (currentIndex < 0) {\n currentIndex = config.loop ? config.markers.length : -1;\n }\n\n config.current = config.markers[currentIndex];\n\n return measurementData;\n }\n\n pointNearTool(element, data, coords) {\n if (data.visible === false) {\n return false;\n }\n\n if (!data.handles.end.boundingBox) {\n return;\n }\n\n const distanceToPoint = external.cornerstoneMath.rect.distanceToPoint(\n data.handles.end.boundingBox,\n coords\n );\n const insideBoundingBox = pointInsideBoundingBox(data.handles.end, coords);\n\n return distanceToPoint < 10 || insideBoundingBox;\n }\n\n updateCachedStats() {\n // Implementing to satisfy BaseAnnotationTool\n }\n\n renderToolData(evt) {\n const eventData = evt.detail;\n const config = this.configuration;\n\n // If we have no toolData for this element, return immediately as there is nothing to do\n const toolData = getToolState(eventData.element, this.name);\n\n if (!toolData) {\n return;\n }\n\n // We have tool data for this element - iterate over each one and draw it\n const context = getNewContext(eventData.canvasContext.canvas);\n\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n if (data.visible === false) {\n continue;\n }\n\n const color = toolColors.getColorIfActive(data);\n\n draw(context, context => {\n setShadow(context, config);\n\n const textCoords = external.cornerstone.pixelToCanvas(\n eventData.element,\n data.handles.end\n );\n\n const options = {\n centering: {\n x: true,\n y: true,\n },\n };\n\n data.handles.end.boundingBox = drawTextBox(\n context,\n data.text,\n textCoords.x,\n textCoords.y - 10,\n color,\n options\n );\n });\n }\n }\n\n _changeText(evt) {\n const eventData = evt.detail;\n const { element, currentPoints } = eventData;\n let data;\n\n function doneChangingTextCallback(data, updatedText, deleteTool) {\n if (deleteTool === true) {\n removeToolState(element, this.name, data);\n } else {\n data.text = updatedText;\n }\n\n data.active = false;\n external.cornerstone.updateImage(element);\n }\n\n const config = this.configuration;\n const coords = currentPoints.canvas;\n const toolData = getToolState(element, this.name);\n\n // Now check to see if there is a handle we can move\n if (!toolData) {\n return;\n }\n\n for (let i = 0; i < toolData.data.length; i++) {\n data = toolData.data[i];\n if (this.pointNearTool(element, data, coords)) {\n data.active = true;\n external.cornerstone.updateImage(element);\n\n // Allow relabelling via a callback\n config.changeTextCallback(data, eventData, doneChangingTextCallback);\n\n evt.stopImmediatePropagation();\n evt.preventDefault();\n evt.stopPropagation();\n\n return;\n }\n }\n }\n}\n\n/**\n * This function is a callback to be overwriten in order to provide the wanted feature\n * modal, overlay, popup or any kind of interaction with the user to be able to update\n * the text marker label.\n *\n * @param {Object} data\n * @param {Object} eventData\n * @param {doneChangingTextCallback} doneChangingTextCallback\n * @returns {void}\n */\nconst changeTextCallback = (data, eventData, doneChangingTextCallback) => {\n // eslint-disable-next-line no-alert\n doneChangingTextCallback(data, prompt('Change your annotation:'));\n};\n\n/**\n * @callback doneChangingTextCallback\n * @param {Object} data\n * @param {string} text - The new text\n */\n","import external from './../../externalModules.js';\nimport { BaseBrushTool } from '../base';\nimport { getModule } from './../../store/index.js';\nimport { drawBrushPixels, getCircle } from '../../util/segmentation/index.js';\nimport { getLogger } from '../../util/logger.js';\n\nconst logger = getLogger('tools:BrushTool');\n\nconst segmentationModule = getModule('segmentation');\n\n/**\n * @public\n * @class BrushTool\n * @memberof Tools.Brush\n * @classdesc Tool for drawing segmentations on an image.\n * @extends Tools.Base.BaseBrushTool\n */\nexport default class BrushTool extends BaseBrushTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Brush',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {},\n mixins: ['renderBrushMixin'],\n };\n\n super(props, defaultProps);\n\n this.touchDragCallback = this._paint.bind(this);\n }\n\n /**\n * Paints the data to the labelmap.\n *\n * @protected\n * @param {Object} evt The data object associated with the event.\n * @returns {void}\n */\n _paint(evt) {\n const { configuration } = segmentationModule;\n const eventData = evt.detail;\n const element = eventData.element;\n const { rows, columns } = eventData.image;\n const { x, y } = eventData.currentPoints.image;\n\n if (x < 0 || x > columns || y < 0 || y > rows) {\n return;\n }\n\n const radius = configuration.radius;\n const pointerArray = getCircle(radius, rows, columns, x, y);\n\n const { labelmap2D, labelmap3D, shouldErase } = this.paintEventData;\n\n // Draw / Erase the active color.\n drawBrushPixels(\n pointerArray,\n labelmap2D.pixelData,\n labelmap3D.activeSegmentIndex,\n columns,\n shouldErase\n );\n\n external.cornerstone.updateImage(evt.detail.element);\n }\n}\n","import external from './../../externalModules.js';\nimport BaseBrushTool from './../base/BaseBrushTool.js';\nimport { getModule } from './../../store/index.js';\nimport {\n drawBrushPixels,\n getCircle,\n triggerLabelmapModifiedEvent,\n} from './../../util/segmentation';\nimport { getToolState } from '../../stateManagement/toolState.js';\nimport { getLogger } from '../../util/logger.js';\nimport { getDiffBetweenPixelData } from '../../util/segmentation';\n\nconst logger = getLogger('tools:SphericalBrushTool');\n\nconst segmentationModule = getModule('segmentation');\n\n/**\n * @public\n * @class BrushTool\n * @memberof Tools.Brush\n * @classdesc Tool for drawing segmentations on an image.\n * @extends Tools.Base.BaseBrushTool\n */\nexport default class SphericalBrushTool extends BaseBrushTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'SphericalBrush',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: { alwaysEraseOnClick: false },\n mixins: ['renderBrushMixin'],\n };\n\n super(props, defaultProps);\n\n this.touchDragCallback = this._paint.bind(this);\n }\n\n /**\n * Initialise painting with BaseBrushTool.\n *\n * @abstract\n * @event\n * @param {Object} evt - The event.\n * @returns {void}\n */\n _startPainting(evt) {\n const { configuration, getters } = segmentationModule;\n const eventData = evt.detail;\n const { element, image } = eventData;\n const { cornerstone } = external;\n const radius = configuration.radius;\n const { rows, columns } = image;\n const pixelSpacing = Math.max(\n image.rowPixelSpacing,\n image.columnPixelSpacing\n );\n\n const stackState = getToolState(element, 'stack');\n const stackData = stackState.data[0];\n const { imageIds } = stackData;\n\n const {\n labelmap2D,\n labelmap3D,\n currentImageIdIndex,\n activeLabelmapIndex,\n } = getters.labelmap2D(element);\n\n const shouldErase =\n this._isCtrlDown(eventData) || this.configuration.alwaysEraseOnClick;\n\n const imagePlaneOfCurrentImage = cornerstone.metaData.get(\n 'imagePlaneModule',\n image.imageId\n );\n\n let imagesInRange;\n\n if (imagePlaneOfCurrentImage) {\n const ippOfCurrentImage = imagePlaneOfCurrentImage.imagePositionPatient;\n\n imagesInRange = this._getImagesInRange(\n currentImageIdIndex,\n ippOfCurrentImage,\n imageIds,\n radius,\n pixelSpacing\n );\n } else {\n logger.warn(\n `No imagePlane metadata found for image, defaulting to circle brush application.`\n );\n\n imagesInRange = [\n // The current image.\n {\n imageIdIndex: currentImageIdIndex,\n radiusOnImage: radius,\n },\n ];\n }\n\n this.paintEventData = {\n labelmap2D,\n labelmap3D,\n currentImageIdIndex,\n activeLabelmapIndex,\n shouldErase,\n imagesInRange,\n };\n\n if (configuration.storeHistory) {\n const previousPixeldataForImagesInRange = [];\n\n for (let i = 0; i < imagesInRange.length; i++) {\n const { imageIdIndex } = imagesInRange[i];\n const labelmap2DForImageIdIndex = getters.labelmap2DByImageIdIndex(\n labelmap3D,\n imageIdIndex,\n rows,\n columns\n );\n\n const previousPixeldata = labelmap2DForImageIdIndex.pixelData.slice();\n\n previousPixeldataForImagesInRange.push(previousPixeldata);\n }\n\n this.paintEventData.previousPixeldataForImagesInRange = previousPixeldataForImagesInRange;\n }\n }\n\n /**\n * Paints the data to the labelmap.\n *\n * @private\n * @param {Object} evt The data object associated with the event.\n * @returns {void}\n */\n _paint(evt) {\n const { getters } = segmentationModule;\n const eventData = evt.detail;\n const element = eventData.element;\n const image = eventData.image;\n const { rows, columns } = image;\n const { x, y } = eventData.currentPoints.image;\n\n if (x < 0 || x > columns || y < 0 || y > rows) {\n return;\n }\n\n const { labelmap3D, imagesInRange, shouldErase } = this.paintEventData;\n\n for (let i = 0; i < imagesInRange.length; i++) {\n const { imageIdIndex, radiusOnImage } = imagesInRange[i];\n const pointerArray = getCircle(radiusOnImage, rows, columns, x, y);\n\n // Cache the view on this image if its not present.\n const labelmap2DForImageIdIndex = getters.labelmap2DByImageIdIndex(\n labelmap3D,\n imageIdIndex,\n rows,\n columns\n );\n\n // Draw / Erase the active color.\n drawBrushPixels(\n pointerArray,\n labelmap2DForImageIdIndex.pixelData,\n labelmap3D.activeSegmentIndex,\n columns,\n shouldErase\n );\n }\n\n external.cornerstone.updateImage(evt.detail.element);\n }\n\n /**\n * _getImagesInRange - Returns an array of image Ids within range of the\n * sphere, and the in-plane brush radii of those images.\n *\n * @param {string} currentImageIdIndex The imageId of the image displayed on\n * the cornerstone enabled element.\n * @param {number[]} ippOfCurrentImage The image position patient of the image.\n * @param {string[]} imageIds An array of images in the stack.\n * @param {number} radius The radius of the sphere.\n * @param {number} pixelSpacing The pixelSpacing.\n * @returns {Object[]} An array of imageIds in range and their\n * in plane brush radii.\n */\n _getImagesInRange(\n currentImageIdIndex,\n ippOfCurrentImage,\n imageIds,\n radius,\n pixelSpacing\n ) {\n const radiusInMM = radius * pixelSpacing;\n const imagesInRange = [\n // The current image.\n {\n imageIdIndex: currentImageIdIndex,\n radiusOnImage: radius,\n },\n ];\n\n // Check images above\n for (let i = currentImageIdIndex + 1; i < imageIds.length; i++) {\n const radiusOnImage = this._getRadiusOnImage(\n imageIds[i],\n ippOfCurrentImage,\n radiusInMM,\n pixelSpacing\n );\n\n if (!radiusOnImage) {\n break;\n }\n\n imagesInRange.push({\n imageIdIndex: i,\n radiusOnImage,\n });\n }\n\n // Check images below\n for (let i = currentImageIdIndex - 1; i >= 0; i--) {\n const radiusOnImage = this._getRadiusOnImage(\n imageIds[i],\n ippOfCurrentImage,\n radiusInMM,\n pixelSpacing\n );\n\n if (!radiusOnImage) {\n break;\n }\n\n imagesInRange.push({\n imageIdIndex: i,\n radiusOnImage,\n });\n }\n\n return imagesInRange;\n }\n\n /**\n * _getRadiusOnImage - If the image is in range of the spherical brush, returns\n * the in-plane brush radius on that image.\n *\n * @param {string} imageId The cornerstone imageId of the image.\n * @param {number[]} ippOfCurrentImage The image position patient of the current image.\n * @param {number} radiusInMM The radius of the sphere in millimeters.\n * @param {string} pixelSpacing The pixelspacing.\n * @returns {number|undefined} The brush radius on the image, undefined if\n * the image is out of range of the sphere.\n */\n _getRadiusOnImage(imageId, ippOfCurrentImage, radiusInMM, pixelSpacing) {\n const imagePlane = external.cornerstone.metaData.get(\n 'imagePlaneModule',\n imageId\n );\n\n if (!imagePlane) {\n logger.warn(\n `Can't find imagePlane metadata for image, cancelling spherical brushing on: ${imageId},`\n );\n\n return;\n }\n\n const ipp = imagePlane.imagePositionPatient;\n\n const distance = Math.sqrt(\n Math.pow(ipp[0] - ippOfCurrentImage[0], 2) +\n Math.pow(ipp[1] - ippOfCurrentImage[1], 2) +\n Math.pow(ipp[2] - ippOfCurrentImage[2], 2)\n );\n\n if (distance > radiusInMM) {\n // Image too far away, break!\n return;\n }\n\n return Math.floor(\n Math.sqrt(Math.pow(radiusInMM, 2) - Math.pow(distance, 2)) / pixelSpacing\n );\n }\n\n _endPainting(evt) {\n const { labelmap3D, imagesInRange } = this.paintEventData;\n const operations = [];\n const { configuration, setters } = segmentationModule;\n\n for (let i = 0; i < imagesInRange.length; i++) {\n const { imageIdIndex } = imagesInRange[i];\n const labelmap2D = labelmap3D.labelmaps2D[imageIdIndex];\n\n // Grab the labels on the slice.\n const segmentSet = new Set(labelmap2D.pixelData);\n const iterator = segmentSet.values();\n\n const segmentsOnLabelmap = [];\n let done = false;\n\n while (!done) {\n const next = iterator.next();\n\n done = next.done;\n\n if (!done) {\n segmentsOnLabelmap.push(next.value);\n }\n }\n\n labelmap2D.segmentsOnLabelmap = segmentsOnLabelmap;\n\n if (configuration.storeHistory) {\n const { previousPixeldataForImagesInRange } = this.paintEventData;\n\n const previousPixeldata = previousPixeldataForImagesInRange[i];\n const labelmap2D = labelmap3D.labelmaps2D[imageIdIndex];\n const newPixelData = labelmap2D.pixelData;\n\n operations.push({\n imageIdIndex,\n diff: getDiffBetweenPixelData(previousPixeldata, newPixelData),\n });\n }\n }\n\n if (configuration.storeHistory) {\n setters.pushState(this.element, operations);\n }\n\n triggerLabelmapModifiedEvent(this.element);\n }\n}\n","import { fillInsideFreehand, eraseInsideFreehand } from './index.js';\nimport {\n getPixelPathBetweenPixels,\n floodFill,\n} from '../../../util/segmentation';\nimport clip from '../../../util/clip';\nimport isPointInImage from '../../../util/isPointInImage';\n\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger('util:segmentation:operations:correction');\n\n/**\n * Using the stroke given, determine which action(s) to perfom:\n * - Stroke starts and ends inside a segmentation: Behaves as an subtractive freehand scissors.\n * - Stroke starts and ends outside a segmentation: Behaves as an additive freehand scissors.\n * - Stroke out-in-out: Section is subtracted.\n * - Stroke in-out-in: Section is added.\n *\n * @param {Object} evt The cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n *\n * @returns {null}\n */\nexport default function correction(evt, operationData) {\n const { pixelData, segmentIndex, segmentationMixinType } = operationData;\n\n if (segmentationMixinType !== `freehandSegmentationMixin`) {\n logger.error(\n `correction operation requires freehandSegmentationMixin operationData, recieved ${segmentationMixinType}`\n );\n\n return;\n }\n\n const nodes = snapPointsToGrid(evt, operationData);\n\n const scissorOperation = checkIfSimpleScissorOperation(nodes, segmentIndex);\n\n if (scissorOperation.isScissorOperation) {\n if (scissorOperation.operation === 'fillInsideFreehand') {\n logger.warn('The line never intersects a segment.');\n fillInsideFreehand(evt, operationData);\n } else if (scissorOperation.operation === 'eraseInsideFreehand') {\n logger.warn('The line is only ever inside the segment.');\n eraseInsideFreehand(evt, operationData);\n }\n\n return;\n }\n\n // Create binary labelmap with only this segment for calculations of each operation.\n const workingLabelMap = new Uint8Array(pixelData.length);\n const operations = splitLineIntoSeperateOperations(nodes, segmentIndex);\n\n operations.forEach(operation => {\n performOperation(operation, pixelData, workingLabelMap, segmentIndex, evt);\n });\n}\n\n/**\n * Snap the freehand points to the labelmap grid and attach a label for each node.\n *\n * @param {Object[]} points An array of points drawn by the user.\n * @param {UInt16Array} pixelData The 2D labelmap.\n * @param {Object} evt The cornerstone event.\n * @returns {Object[]}\n */\nfunction snapPointsToGrid(evt, operationData) {\n const { pixelData, points } = operationData;\n\n const { image } = evt.detail;\n const cols = image.width;\n const rows = image.height;\n\n const nodes = [];\n\n for (let i = 0; i < points.length; i++) {\n const point = points[i];\n\n let x = Math.floor(point.x);\n let y = Math.floor(point.y);\n\n // Clamp within the confines of the image.\n x = clip(x, 0, cols - 1);\n y = clip(y, 0, rows - 1);\n\n const lastNode = nodes[nodes.length - 1];\n\n // Skip double counting of closely drawn freehand points.\n if (lastNode && x === lastNode.x && y === lastNode.y) {\n continue;\n }\n\n nodes.push({\n x,\n y,\n segment: pixelData[y * cols + x],\n });\n }\n\n return nodes;\n}\n/**\n * Check if the operation is a simple scissors add/remove.\n * @param {Object[]} nodes - The nodes snapped to the grid.\n * @param {number} segmentIndex\n * @returns {Object} Information about the operation.\n * `isScissorOperation` is true if the operation is a simple scissor.\n * If `isScissorOperation` is true, `operation` says which operation.\n */\nfunction checkIfSimpleScissorOperation(nodes, segmentIndex) {\n let allInside = true;\n let allOutside = true;\n\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n\n if (node.segment === segmentIndex) {\n allOutside = false;\n } else {\n allInside = false;\n }\n\n if (!allInside && !allOutside) {\n break;\n }\n }\n\n if (allOutside) {\n return { isScissorOperation: true, operation: 'fillInsideFreehand' };\n } else if (allInside) {\n return { isScissorOperation: true, operation: 'eraseInsideFreehand' };\n }\n\n return { isScissorOperation: false };\n}\n\n/**\n * Performs the given add/subtract operation using a modification of the Tobias Heimann Correction Algorithm:\n * The algorithm is described in full length in Tobias Heimann's diploma thesis (MBI Technical Report 145, p. 37 - 40).\n *\n * @param {Object} operation The operation.\n * @param {UInt16Array} pixelData The 2D labelmap.\n * @param {UInt16Array} workingLabelMap A copy of the labelmap for processing purposes.\n * @param {number} segmentIndex The label of the tool being used.\n * @param {Object} evt The cornerstone event.\n */\nfunction performOperation(\n operation,\n pixelData,\n workingLabelMap,\n segmentIndex,\n evt\n) {\n const { width: cols, height: rows } = evt.detail.image;\n\n const { nodes, additive } = operation;\n const shouldFillOver = additive ? 0 : 1;\n\n // Local getters to swap from cornerstone vector notation and flattened array indicies.\n const getPixelIndex = pixelCoord => pixelCoord.y * cols + pixelCoord.x;\n const getPixelCoordinateFromPixelIndex = pixelIndex => ({\n x: pixelIndex % cols,\n y: Math.floor(pixelIndex / cols),\n });\n\n if (additive) {\n logger.warn('additive operation...');\n } else {\n logger.warn('subtractive operation...');\n }\n\n const { pixelPath, leftPath, rightPath } = getPixelPaths(nodes);\n\n // Find extent of region for floodfill (This segment + the drawn loop).\n // This is to reduce the extent of the outwards floodfill, which constitutes 99% of the computation.\n const firstPixelOnPath = pixelPath[0];\n\n const boundingBox = {\n xMin: firstPixelOnPath.x,\n xMax: firstPixelOnPath.x,\n yMin: firstPixelOnPath.y,\n yMax: firstPixelOnPath.y,\n };\n\n // ...whilst also initializing the workingLabelmap\n for (let i = 0; i < workingLabelMap.length; i++) {\n if (pixelData[i] === segmentIndex) {\n const pixel = getPixelCoordinateFromPixelIndex(i);\n\n expandBoundingBox(boundingBox, pixel);\n workingLabelMap[i] = 1;\n } else {\n workingLabelMap[i] = 0;\n }\n }\n\n // Set workingLabelmap pixelPath to 2 to form a\n // Boundary in the working labelmap to contain the flood fills.\n for (let i = 0; i < pixelPath.length; i++) {\n const pixel = pixelPath[i];\n\n workingLabelMap[getPixelIndex(pixel)] = 2;\n expandBoundingBox(boundingBox, pixel);\n }\n\n clipBoundingBox(boundingBox, rows, cols);\n\n const { xMin, xMax, yMin, yMax } = boundingBox;\n\n // Define a getter for the fill routine to access the working label map.\n function getter(x, y) {\n // Check if out of bounds, as the flood filler doesn't know about the dimensions of\n // The data structure. E.g. if cols is 10, (0,1) and (10, 0) would point to the same\n // position in this getter.\n\n if (x >= xMax || x < xMin || y >= yMax || y < yMin) {\n return;\n }\n\n return workingLabelMap[y * cols + x];\n }\n\n let leftArea = 0;\n let rightArea = 0;\n\n // Traverse the path whilst pouring paint off the left and right sides.\n for (let i = 0; i < leftPath.length; i++) {\n // Left fill\n const leftPixel = leftPath[i];\n const leftValue = workingLabelMap[getPixelIndex(leftPixel)];\n\n if (leftValue === shouldFillOver && isPointInImage(leftPixel, rows, cols)) {\n leftArea += fillFromPixel(leftPixel, 3, workingLabelMap, getter, cols);\n }\n\n // Right fill\n const rightPixel = rightPath[i];\n const rightValue = workingLabelMap[getPixelIndex(rightPixel)];\n\n if (\n rightValue === shouldFillOver &&\n isPointInImage(rightPixel, rows, cols)\n ) {\n rightArea += fillFromPixel(rightPixel, 4, workingLabelMap, getter, cols);\n }\n }\n\n if (leftArea === 0 || rightArea === 0) {\n // The areas are connected, therefore the start and end\n // Of the path go through unconnected regions, exit.\n return;\n }\n\n const replaceValue = additive ? segmentIndex : 0;\n\n // Fill in smallest area.\n const fillValue = leftArea < rightArea ? 3 : 4;\n\n for (let i = 0; i < workingLabelMap.length; i++) {\n if (workingLabelMap[i] === fillValue) {\n pixelData[i] = replaceValue;\n }\n }\n\n if (replaceValue === segmentIndex) {\n // Fill in the path.\n for (let i = 0; i < pixelPath.length; i++) {\n pixelData[getPixelIndex(pixelPath[i])] = segmentIndex;\n }\n } else {\n // Only erase this segment.\n for (let i = 0; i < pixelPath.length; i++) {\n const pixelIndex = getPixelIndex(pixelPath[i]);\n\n if (pixelData[pixelIndex] === segmentIndex) {\n pixelData[pixelIndex] = 0;\n }\n }\n }\n}\n\n/**\n * Expands the bounding box if the pixel falls outside it.\n *\n * @param {Object} boundingBox The bounding box.\n * @param {Object} pixel The pixel.\n * @returns {null}\n */\nfunction expandBoundingBox(boundingBox, pixel) {\n const { x, y } = pixel;\n\n if (x < boundingBox.xMin) {\n boundingBox.xMin = x;\n }\n if (x > boundingBox.xMax) {\n boundingBox.xMax = x;\n }\n if (y < boundingBox.yMin) {\n boundingBox.yMin = y;\n }\n if (y > boundingBox.yMax) {\n boundingBox.yMax = y;\n }\n}\n\n/**\n * Expands the bounding box by 2 px and then clips it to the image size.\n * @param {Object} boundingBox The bounding box.\n * @param {number} rows The number of rows.\n * @param {number} cols The number of columns.\n * @returns {null}\n */\nfunction clipBoundingBox(boundingBox, rows, cols) {\n // Add a 2px border to stop the floodfill starting out of bounds and exploading.\n const border = 2;\n\n boundingBox.xMax = Math.min(boundingBox.xMax + border, cols);\n boundingBox.xMin = Math.max(boundingBox.xMin - border, 0);\n boundingBox.yMax = Math.min(boundingBox.yMax + border, rows);\n boundingBox.yMin = Math.max(boundingBox.yMin - border, 0);\n}\n\n/**\n * Performs a floodfill from the given pixel to the workingLabelMap.\n * @param {Object} pixel The pixel.\n * @param {number} fillValue The fill value.\n * @param {UInt8Array} workingLabelMap The working labelmap.\n * @param {function} getter The getter function for pixels in the labelmap.\n * @param {number} cols The number of columns.\n * @returns {number} The number of pixels flooded.\n */\nfunction fillFromPixel(pixel, fillValue, workingLabelMap, getter, cols) {\n const result = floodFill(getter, [pixel.x, pixel.y]);\n\n const flooded = result.flooded;\n\n for (let p = 0; p < flooded.length; p++) {\n const floodedI = flooded[p];\n\n workingLabelMap[floodedI[1] * cols + floodedI[0]] = fillValue;\n }\n\n return flooded.length;\n}\n\n/**\n * Interpolates the pixelPath using an obstacleless path finding algorithm.\n * @param {Object[]} nodes The nodes to interpolate between.\n * @returns {Object} The pixelPath, and the path to the left and right of it.\n */\nfunction getPixelPaths(nodes) {\n const pixelPath = [];\n\n for (let i = 0; i < nodes.length - 1; i++) {\n // Push the node.\n pixelPath.push(nodes[i]);\n // Path towards next node.\n pixelPath.push(...getPixelPathBetweenPixels(nodes[i], nodes[i + 1]));\n }\n\n // Push final node.\n pixelPath.push[nodes[nodes.length - 1]];\n\n // Get paths on either side.\n\n const leftPath = [];\n const rightPath = [];\n\n for (let i = 0; i < pixelPath.length - 1; i++) {\n const { left, right } = getNodesPerpendicularToPathPixel(\n pixelPath[i],\n pixelPath[i + 1]\n );\n\n leftPath.push(left);\n rightPath.push(right);\n }\n\n return { pixelPath, leftPath, rightPath };\n}\n\n/**\n * Using the current and next pixel on the path, determine the adjacent pixels\n * which are perpendicular to the path direction. (i.e. to the left and to the right).\n *\n * @param {Object} pathPixel The pixel being queried.\n * @param {Object} nextPathPixel the pathPixel's successor.\n *\n * @returns {Object} The coordinates of the left and right perpendicular pixels.\n */\nfunction getNodesPerpendicularToPathPixel(pathPixel, nextPathPixel) {\n const direction = {\n x: nextPathPixel.x - pathPixel.x,\n y: nextPathPixel.y - pathPixel.y,\n };\n\n // P = pathPixel, n = nextPathPixel, L = left, R = right\n //\n // |n| |R| | |n| | |L| |n|\n // | |p| | |L|p|R| | |p| |\n // |L| | | | | | | | | |R|\n //\n // | |R| | | |L| |\n // |n|p| | | |p|n|\n // | |L| | | |R| |\n //\n // |R| | | | | | | | | |L|\n // | |p| | |R|p|L| | |p| |\n // |n| |L| | |n| | |R| |n|\n\n if (direction.x === -1 && direction.y === 1) {\n return {\n left: { x: pathPixel.x - 1, y: pathPixel.y - 1 },\n right: { x: pathPixel.x + 1, y: pathPixel.y + 1 },\n };\n } else if (direction.x === 0 && direction.y === 1) {\n return {\n left: { x: pathPixel.x - 1, y: pathPixel.y },\n right: { x: pathPixel.x + 1, y: pathPixel.y },\n };\n } else if (direction.x === 1 && direction.y === 1) {\n return {\n left: { x: pathPixel.x - 1, y: pathPixel.y + 1 },\n right: { x: pathPixel.x + 1, y: pathPixel.y - 1 },\n };\n } else if (direction.x === 1 && direction.y === 0) {\n return {\n left: { x: pathPixel.x, y: pathPixel.y + 1 },\n right: { x: pathPixel.x, y: pathPixel.y - 1 },\n };\n } else if (direction.x === 1 && direction.y === -1) {\n return {\n left: { x: pathPixel.x + 1, y: pathPixel.y + 1 },\n right: { x: pathPixel.x - 1, y: pathPixel.y - 1 },\n };\n } else if (direction.x === 0 && direction.y === -1) {\n return {\n left: { x: pathPixel.x + 1, y: pathPixel.y },\n right: { x: pathPixel.x - 1, y: pathPixel.y },\n };\n } else if (direction.x === -1 && direction.y === -1) {\n return {\n left: { x: pathPixel.x + 1, y: pathPixel.y - 1 },\n right: { x: pathPixel.x - 1, y: pathPixel.y + 1 },\n };\n } else if (direction.x === -1 && direction.y === 0) {\n return {\n left: { x: pathPixel.x, y: pathPixel.y - 1 },\n right: { x: pathPixel.x, y: pathPixel.y + 1 },\n };\n }\n\n logger.error(\n `Unable to find left and right paths for flood fill `,\n pathPixel,\n nextPathPixel,\n direction\n );\n}\n\n/**\n * Splits the path of nodes into seperate add/remove operations.\n *\n * @param {Object[]} nodes The array of nodes.\n * @param {number} segmentIndex The label value to replace.\n * @returns {{additive: boolean, nodes: []}[]} An array of operations to perform,\n * whether they are `additive` and the\n * corresponding `nodes` of the operation.\n */\nfunction splitLineIntoSeperateOperations(nodes, segmentIndex) {\n // Check whether the first node is inside a segment of the appropriate label or not.\n let isLabel = nodes[0].segment === segmentIndex;\n\n const operations = [];\n\n operations.push({\n additive: !isLabel,\n nodes: [],\n });\n\n let operationIndex = 0;\n\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n\n if (isLabel) {\n operations[operationIndex].nodes.push(node);\n\n if (node.segment !== segmentIndex) {\n // Start a new operation and include the last two nodes.\n\n operationIndex++;\n isLabel = !isLabel;\n operations.push({\n additive: true,\n nodes: [],\n });\n operations[operationIndex].nodes.push(nodes[i - 1]);\n operations[operationIndex].nodes.push(node);\n }\n } else {\n operations[operationIndex].nodes.push(node);\n\n if (node.segment === segmentIndex) {\n // Start a new operation and add include the last two nodes.\n operationIndex++;\n isLabel = !isLabel;\n operations.push({\n additive: false,\n nodes: [],\n });\n operations[operationIndex].nodes.push(nodes[i - 1]);\n operations[operationIndex].nodes.push(node);\n }\n }\n }\n\n // Trim the first and last entries, as they don't form full operations.\n\n operations.pop();\n operations.shift();\n\n return operations;\n}\n","/**\n * Checks whether a point is inside a polygon\n *\n * {@link https://github.com/substack/point-in-polygon/blob/master/index.js}\n * ray-casting algorithm based on\n * {@link http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html}\n *\n * @param {Array} point The point [x1, y1]\n * @param {Array} vs The vertices [[x1, y1], [x2, y2], ...] of the Polygon\n * @returns {boolean}\n */\nexport default function isPointInPolygon(point, vs) {\n const x = point[0];\n const y = point[1];\n let inside = false;\n\n for (let i = 0, j = vs.length - 1; i < vs.length; j = i++) {\n const xi = vs[i][0];\n const yi = vs[i][1];\n\n const xj = vs[j][0];\n const yj = vs[j][1];\n\n const intersect =\n yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;\n\n if (intersect) {\n inside = !inside;\n }\n }\n\n return inside;\n}\n","import {\n getBoundingBoxAroundPolygon,\n eraseInsideShape,\n eraseOutsideShape,\n} from '../../../util/segmentation';\nimport isPointInPolygon from '../../../util/isPointInPolygon';\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger('util:segmentation:operations:eraseInsideFreehand');\n\n/**\n * Erase all pixels labeled with the activeSegmentIndex,\n * in the region defined by evt.operationData.points.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nfunction eraseFreehand(evt, operationData, inside = true) {\n const { points, segmentationMixinType } = operationData;\n\n if (segmentationMixinType !== `freehandSegmentationMixin`) {\n logger.error(\n `eraseInsideFreehand operation requires freehandSegmentationMixin operationData, recieved ${segmentationMixinType}`\n );\n\n return;\n }\n\n const { image } = evt.detail;\n const vertices = points.map(a => [a.x, a.y]);\n const [topLeft, bottomRight] = getBoundingBoxAroundPolygon(vertices, image);\n\n inside\n ? eraseInsideShape(\n evt,\n operationData,\n point => isPointInPolygon([point.x, point.y], vertices),\n topLeft,\n bottomRight\n )\n : eraseOutsideShape(\n evt,\n operationData,\n point => isPointInPolygon([point.x, point.y], vertices),\n topLeft,\n bottomRight\n );\n}\n\n/**\n * Erase all pixels inside/outside the region defined by `operationData.points`.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function eraseInsideFreehand(evt, operationData) {\n eraseFreehand(evt, operationData, true);\n}\n\n/**\n * Erase all pixels outside the region defined by `operationData.points`.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function eraseOutsideFreehand(evt, operationData) {\n eraseFreehand(evt, operationData, false);\n}\n","import { getLogger } from '../../../util/logger';\nimport {\n getBoundingBoxAroundPolygon,\n eraseInsideShape,\n eraseOutsideBoundingBox,\n} from '../../../util/segmentation';\n\nconst logger = getLogger('util:segmentation:operations:eraseInsideRectangle');\n\n/**\n * Erase all pixels inside the region defined by the rectangle.\n * @param {Object} evt The Cornerstone event.\n * @param {Object} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nfunction eraseRectangle(evt, operationData, inside = true) {\n const { points, segmentationMixinType } = operationData;\n\n if (segmentationMixinType !== `rectangleSegmentationMixin`) {\n logger.error(\n `eraseInsideRectangle operation requires rectangleSegmentationMixin operationData, recieved ${segmentationMixinType}`\n );\n\n return;\n }\n\n const eventData = evt.detail;\n\n // Loop through all pixels in the segmentation data mask\n\n // Obtain the bounding box of the entire drawing so that\n // we can subset our search.\n const { image } = eventData;\n const vertices = points.map(a => [a.x, a.y]);\n const [topLeft, bottomRight] = getBoundingBoxAroundPolygon(vertices, image);\n\n inside\n ? eraseInsideShape(evt, operationData, () => true, topLeft, bottomRight)\n : eraseOutsideBoundingBox(evt, operationData, topLeft, bottomRight);\n}\n\n/**\n * Erase all pixels inside/outside the region defined by the rectangle.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function eraseInsideRectangle(evt, operationData) {\n eraseRectangle(evt, operationData, true);\n}\n\n/**\n * Erase all pixels outside the region defined by the rectangle.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function eraseOutsideRectangle(evt, operationData) {\n eraseRectangle(evt, operationData, false);\n}\n","import {\n getBoundingBoxAroundPolygon,\n fillInsideShape,\n fillOutsideShape,\n} from '../../../util/segmentation';\nimport isPointInPolygon from '../../../util/isPointInPolygon';\n\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger('util:segmentation:operations:fillInsideFreehand');\n\n/**\n * Fill all pixels inside/outside the region defined by\n * `operationData.points` with the `activeSegmentIndex` value.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nfunction fillFreehand(evt, operationData, inside = true) {\n const { points, segmentationMixinType } = operationData;\n\n if (segmentationMixinType !== `freehandSegmentationMixin`) {\n logger.error(\n `eraseInsideFreehand operation requires freehandSegmentationMixin operationData, recieved ${segmentationMixinType}`\n );\n\n return;\n }\n\n // Obtain the bounding box of the entire drawing so that\n // we can subset our search. Outside of the bounding box,\n // everything is outside of the polygon.\n const { image } = evt.detail;\n const vertices = points.map(a => [a.x, a.y]);\n const [topLeft, bottomRight] = getBoundingBoxAroundPolygon(vertices, image);\n\n inside\n ? fillInsideShape(\n evt,\n operationData,\n point => isPointInPolygon([point.x, point.y], vertices),\n topLeft,\n bottomRight\n )\n : fillOutsideShape(\n evt,\n operationData,\n point => isPointInPolygon([point.x, point.y], vertices),\n topLeft,\n bottomRight\n );\n}\n\n/**\n * Fill all pixels inside/outside the region defined by `operationData.points`.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function fillInsideFreehand(evt, operationData) {\n fillFreehand(evt, operationData, true);\n}\n\n/**\n * Fill all pixels outside the region defined by `operationData.points`.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function fillOutsideFreehand(evt, operationData) {\n fillFreehand(evt, operationData, false);\n}\n","import {\n fillInsideShape,\n getBoundingBoxAroundPolygon,\n fillOutsideBoundingBox,\n} from '../../../util/segmentation';\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger('util:segmentation:operations:fillInsideRectangle');\n\n/**\n * FillInsideRectangle - Fill all pixels inside/outside the region defined\n * by the rectangle.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nfunction fillRectangle(evt, operationData, inside = true) {\n const { points, segmentationMixinType } = operationData;\n\n if (segmentationMixinType !== `rectangleSegmentationMixin`) {\n logger.error(\n `eraseInsideRectangle operation requires rectangleSegmentationMixin operationData, recieved ${segmentationMixinType}`\n );\n\n return;\n }\n\n const { image } = evt.detail;\n const vertices = points.map(a => [a.x, a.y]);\n const [topLeft, bottomRight] = getBoundingBoxAroundPolygon(vertices, image);\n\n inside\n ? fillInsideShape(evt, operationData, () => true, topLeft, bottomRight)\n : fillOutsideBoundingBox(evt, operationData, topLeft, bottomRight);\n}\n\n/**\n * Fill all pixels inside/outside the region defined by the rectangle.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function fillInsideRectangle(evt, operationData) {\n fillRectangle(evt, operationData, true);\n}\n\n/**\n * Fill all pixels outside the region defined by the rectangle.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function fillOutsideRectangle(evt, operationData) {\n fillRectangle(evt, operationData, false);\n}\n","import {\n getBoundingBoxAroundCircle,\n fillInsideShape,\n fillOutsideShape,\n} from '../../../util/segmentation';\nimport { pointInEllipse } from '../../../util/ellipse';\nimport getCircleCoords from '../../../util/getCircleCoords';\n\nimport { getLogger } from '../../../util/logger';\n\nconst logger = getLogger('util:segmentation:operations:fillCircle');\n\n/**\n * Fill all pixels inside/outside the region defined by the circle.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nfunction fillCircle(evt, operationData, inside = true) {\n const { segmentationMixinType } = operationData;\n\n if (segmentationMixinType !== `circleSegmentationMixin`) {\n logger.error(\n `fillInsideCircle operation requires circleSegmentationMixin operationData, recieved ${segmentationMixinType}`\n );\n\n return;\n }\n\n const eventData = evt.detail;\n const [topLeft, bottomRight] = getBoundingBoxAroundCircle(evt);\n const ellipse = getCircleCoords(\n eventData.handles.start,\n eventData.handles.end\n );\n\n inside\n ? fillInsideShape(\n evt,\n operationData,\n point => pointInEllipse(ellipse, point),\n topLeft,\n bottomRight\n )\n : fillOutsideShape(\n evt,\n operationData,\n point => pointInEllipse(ellipse, point),\n topLeft,\n bottomRight\n );\n}\n\n/**\n * Fill all pixels inside/outside the region defined by the circle.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function fillInsideCircle(evt, operationData) {\n fillCircle(evt, operationData, true);\n}\n\n/**\n * Fill all pixels outside the region defined by the circle.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function fillOutsideCircle(evt, operationData) {\n fillCircle(evt, operationData, false);\n}\n","import { pointInEllipse } from '../../../util/ellipse';\nimport { getLogger } from '../../../util/logger';\nimport {\n eraseInsideShape,\n eraseOutsideShape,\n getBoundingBoxAroundCircle,\n} from '../../../util/segmentation';\nimport getCircleCoords from '../../../util/getCircleCoords.js';\n\nconst logger = getLogger('util:segmentation:operations:eraseInsideCircle');\n\n/**\n * EraseInsideCircle - Erase all pixels labeled with the activeSegmentIndex,\n * in the region defined by the circle.\n * @param {Object} evt The Cornerstone event.\n * @param {Object} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nfunction eraseCircle(evt, operationData, inside = true) {\n const { segmentationMixinType } = operationData;\n\n if (segmentationMixinType !== `circleSegmentationMixin`) {\n logger.error(\n `eraseInsideCircle operation requires circleSegmentationMixin operationData, recieved ${segmentationMixinType}`\n );\n\n return;\n }\n\n const eventData = evt.detail;\n const [topLeft, bottomRight] = getBoundingBoxAroundCircle(evt);\n const ellipse = getCircleCoords(\n eventData.handles.start,\n eventData.handles.end\n );\n\n inside\n ? eraseInsideShape(\n evt,\n operationData,\n point => pointInEllipse(ellipse, point),\n topLeft,\n bottomRight\n )\n : eraseOutsideShape(\n evt,\n operationData,\n point => pointInEllipse(ellipse, point),\n topLeft,\n bottomRight\n );\n}\n\n/**\n * Erase all pixels inside/outside the region defined by the circle.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function eraseInsideCircle(evt, operationData) {\n eraseCircle(evt, operationData, true);\n}\n\n/**\n * Erase all pixels outside the region defined by the circle.\n * @param {} evt The Cornerstone event.\n * @param {} operationData An object containing the `pixelData` to\n * modify, the `segmentIndex` and the `points` array.\n * @returns {null}\n */\nexport function eraseOutsideCircle(evt, operationData) {\n eraseCircle(evt, operationData, false);\n}\n","import {\n freehandFillInsideCursor,\n freehandFillOutsideCursor,\n freehandEraseOutsideCursor,\n freehandEraseInsideCursor,\n} from '../cursors';\nimport {\n fillInsideFreehand,\n fillOutsideFreehand,\n eraseOutsideFreehand,\n eraseInsideFreehand,\n} from './strategies';\nimport { BaseTool } from '../base';\n\n/**\n * @public\n * @class FreehandScissorsTool\n * @memberof Tools\n * @classdesc Tool for manipulating labelmap data by drawing a freehand polygon.\n * @extends Tools.Base.BaseTool\n */\nexport default class FreehandScissorsTool extends BaseTool {\n /** @inheritdoc */\n constructor(props = {}) {\n const defaultProps = {\n name: 'FreehandScissors',\n strategies: {\n FILL_INSIDE: fillInsideFreehand,\n FILL_OUTSIDE: fillOutsideFreehand,\n ERASE_OUTSIDE: eraseOutsideFreehand,\n ERASE_INSIDE: eraseInsideFreehand,\n },\n cursors: {\n FILL_INSIDE: freehandFillInsideCursor,\n FILL_OUTSIDE: freehandFillOutsideCursor,\n ERASE_OUTSIDE: freehandEraseOutsideCursor,\n ERASE_INSIDE: freehandEraseInsideCursor,\n },\n defaultStrategy: 'FILL_INSIDE',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: freehandFillInsideCursor,\n mixins: ['freehandSegmentationMixin'],\n };\n\n super(props, defaultProps);\n }\n}\n","import { BaseTool } from '../base';\nimport {\n fillInsideRectangle,\n fillOutsideRectangle,\n eraseOutsideRectangle,\n eraseInsideRectangle,\n} from './strategies';\nimport {\n segRectangleFillInsideCursor,\n segRectangleFillOutsideCursor,\n segRectangleEraseInsideCursor,\n segRectangleEraseOutsideCursor,\n} from '../cursors';\n\n/**\n * @public\n * @class RectangleScissorsTool\n * @memberof Tools\n * @classdesc Tool for manipulating labelmap data by drawing a rectangle.\n * @extends Tools.Base.BaseTool\n */\nexport default class RectangleScissorsTool extends BaseTool {\n /** @inheritdoc */\n constructor(props = {}) {\n const defaultProps = {\n name: 'RectangleScissors',\n strategies: {\n FILL_INSIDE: fillInsideRectangle,\n FILL_OUTSIDE: fillOutsideRectangle,\n ERASE_OUTSIDE: eraseOutsideRectangle,\n ERASE_INSIDE: eraseInsideRectangle,\n },\n cursors: {\n FILL_INSIDE: segRectangleFillInsideCursor,\n FILL_OUTSIDE: segRectangleFillOutsideCursor,\n ERASE_OUTSIDE: segRectangleEraseOutsideCursor,\n ERASE_INSIDE: segRectangleEraseInsideCursor,\n },\n defaultStrategy: 'FILL_INSIDE',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n mixins: ['rectangleSegmentationMixin'],\n };\n\n super(props, defaultProps);\n }\n}\n","import { BaseTool } from '../base';\nimport {\n fillInsideCircle,\n fillOutsideCircle,\n eraseOutsideCircle,\n eraseInsideCircle,\n} from './strategies';\nimport {\n segCircleFillInsideCursor,\n segCircleFillOutsideCursor,\n segCircleEraseOutsideCursor,\n segCircleEraseInsideCursor,\n} from '../cursors';\n\n/**\n * @public\n * @class CircleScissorsTool\n * @memberof Tools\n * @classdesc Tool for manipulating labelmap data by drawing a circle.\n * @extends Tools.Base.BaseTool\n */\nexport default class CircleScissorsTool extends BaseTool {\n /** @inheritdoc */\n constructor(props = {}) {\n const defaultProps = {\n name: 'CircleScissors',\n strategies: {\n FILL_INSIDE: fillInsideCircle,\n FILL_OUTSIDE: fillOutsideCircle,\n ERASE_OUTSIDE: eraseOutsideCircle,\n ERASE_INSIDE: eraseInsideCircle,\n },\n cursors: {\n FILL_INSIDE: segCircleFillInsideCursor,\n FILL_OUTSIDE: segCircleFillOutsideCursor,\n ERASE_OUTSIDE: segCircleEraseOutsideCursor,\n ERASE_INSIDE: segCircleEraseInsideCursor,\n },\n defaultStrategy: 'FILL_INSIDE',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: segCircleFillInsideCursor,\n mixins: ['circleSegmentationMixin'],\n };\n\n super(props, defaultProps);\n }\n}\n","import { BaseTool } from '../base';\nimport { freehandFillInsideCursor } from '../cursors';\nimport { correction } from './strategies';\n\n/**\n * @public\n * @class CorrectionScissorsTool\n * @memberof Tools\n * @classdesc Tool for correcting segments on a labelmap.\n * @extends Tools.Base.BaseTool\n */\nexport default class CorrectionScissorsTool extends BaseTool {\n /** @inheritdoc */\n constructor(props = {}) {\n const defaultProps = {\n name: 'CorrectionScissors',\n strategies: {\n CORRECTION: correction,\n },\n cursors: {\n CORRECTION: freehandFillInsideCursor,\n },\n defaultStrategy: 'CORRECTION',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: freehandFillInsideCursor,\n mixins: ['polylineSegmentationMixin'],\n };\n\n super(props, defaultProps);\n }\n}\n","import external from '../externalModules.js';\n\nconst _DEFAULT_LOAD_HANDLER = 'DEFAULT';\n\nconst defaultStartLoadHandler = {};\nconst defaultEndLoadHandler = {};\nconst defaultErrorLoadingHandler = {};\n\nfunction _getUUIDFromElement(element) {\n if (!element) {\n return _DEFAULT_LOAD_HANDLER;\n }\n const uuid = external.cornerstone.getEnabledElement(element).uuid;\n\n if (!uuid) {\n throw new Error('Something went wrong when getting uuid from element');\n }\n\n return uuid;\n}\n\nfunction setStartLoadHandler(handler, element = undefined) {\n if (!handler) {\n throw new Error('The Handler function must be defined');\n }\n const uuid = _getUUIDFromElement(element);\n\n defaultStartLoadHandler[uuid] = handler;\n}\n\nfunction getStartLoadHandler(element) {\n const uuid = _getUUIDFromElement(element);\n\n return (\n defaultStartLoadHandler[uuid] ||\n defaultStartLoadHandler[_DEFAULT_LOAD_HANDLER]\n );\n}\n\nfunction setEndLoadHandler(handler, element = undefined) {\n if (!handler) {\n throw new Error('The Handler function must be defined');\n }\n const uuid = _getUUIDFromElement(element);\n\n defaultEndLoadHandler[uuid] = handler;\n}\n\nfunction getEndLoadHandler(element) {\n const uuid = _getUUIDFromElement(element);\n\n return (\n defaultEndLoadHandler[uuid] || defaultEndLoadHandler[_DEFAULT_LOAD_HANDLER]\n );\n}\n\nfunction setErrorLoadingHandler(handler, element = undefined) {\n if (!handler) {\n throw new Error('The Handler function must be defined');\n }\n const uuid = _getUUIDFromElement(element);\n\n defaultErrorLoadingHandler[uuid] = handler;\n}\n\nfunction getErrorLoadingHandler(element) {\n const uuid = _getUUIDFromElement(element);\n\n return (\n defaultErrorLoadingHandler[uuid] ||\n defaultErrorLoadingHandler[_DEFAULT_LOAD_HANDLER]\n );\n}\n\nfunction removeHandlers(element) {\n const uuid = _getUUIDFromElement(element);\n\n delete defaultStartLoadHandler[uuid];\n delete defaultEndLoadHandler[uuid];\n delete defaultErrorLoadingHandler[uuid];\n}\n\nconst loadHandlerManager = {\n setStartLoadHandler,\n getStartLoadHandler,\n setEndLoadHandler,\n getEndLoadHandler,\n setErrorLoadingHandler,\n getErrorLoadingHandler,\n removeHandlers,\n};\n\nexport default loadHandlerManager;\n","const elementToolOptions = {};\n\n/**\n * Retrieve the options object associated with a particular toolType and element\n * @export\n * @public\n * @method\n * @name getToolOptions\n *\n * @param {string} toolType Tool type identifier of the target options object\n * @param {HTMLElement} element Element of the target options object\n *\n * @returns {Object} Target options object (empty if not yet set)\n */\nfunction getToolOptions(toolType, element) {\n if (!elementToolOptions[toolType]) {\n return {};\n }\n\n const toolOptions = elementToolOptions[toolType];\n const optionsObject = toolOptions.find(\n toolOptionObject => toolOptionObject.element === element\n );\n\n if (!optionsObject) {\n return {};\n }\n\n return optionsObject.options;\n}\n\n/**\n * Set the options object associated with a particular toolType and element.\n * @export\n * @public\n * @method\n * @name setToolOptions\n *\n * @param {string} toolType Tool type identifier of the target options object.\n * @param {HTMLElement} element Element of the target options object.\n * @param {Object} options Options object to store at target.\n * @returns {void}\n */\nfunction setToolOptions(toolType, element, options) {\n if (!elementToolOptions[toolType]) {\n elementToolOptions[toolType] = [\n {\n element,\n options,\n },\n ];\n\n return;\n }\n\n const toolOptions = elementToolOptions[toolType];\n const index = toolOptions.findIndex(\n toolOptionObject => toolOptionObject.element === element\n );\n\n if (index === -1) {\n elementToolOptions[toolType].push({\n element,\n options,\n });\n } else {\n const elementOptions = elementToolOptions[toolType][index].options || {};\n\n elementToolOptions[toolType][index].options = Object.assign(\n elementOptions,\n options\n );\n }\n}\n\n/**\n * Clear the options object associated with a particular toolType and element.\n * @export\n * @public\n * @method\n * @name clearToolOptions\n *\n * @param {string} toolType Tool type identifier of the target options object.\n * @param {HTMLElement} element Element of the target options object.\n * @returns {void}\n */\nfunction clearToolOptions(toolType, element) {\n const toolOptions = elementToolOptions[toolType];\n\n if (toolOptions) {\n elementToolOptions[toolType] = toolOptions.filter(\n toolOptionObject => toolOptionObject.element !== element\n );\n }\n}\n\n/**\n * Clear the options objects associated with a particular toolType.\n * @export\n * @public\n * @method\n * @name clearToolOptionsByToolType\n *\n * @param {string} toolType Tool type identifier of the target options objects.\n * @returns {void}\n */\nfunction clearToolOptionsByToolType(toolType) {\n delete elementToolOptions[toolType];\n}\n\n/**\n * Clear the options objects associated with a particular element.\n * @export\n * @public\n * @method\n * @name clearToolOptionsByElement\n *\n * @param {HTMLElement} element Element of the target options objects.\n * @returns {void}\n */\nfunction clearToolOptionsByElement(element) {\n for (const toolType in elementToolOptions) {\n elementToolOptions[toolType] = elementToolOptions[toolType].filter(\n toolOptionObject => toolOptionObject.element !== element\n );\n }\n}\n\nexport {\n getToolOptions,\n setToolOptions,\n clearToolOptions,\n clearToolOptionsByToolType,\n clearToolOptionsByElement,\n};\n","import BaseTool from './base/BaseTool.js';\nimport external from './../externalModules.js';\n\nimport loadHandlerManager from '../stateManagement/loadHandlerManager.js';\nimport {\n addToolState,\n getToolState,\n clearToolState,\n} from '../stateManagement/toolState.js';\nimport { imagePointToPatientPoint } from '../util/pointProjector.js';\nimport convertToVector3 from '../util/convertToVector3.js';\nimport { setToolOptions } from '../toolOptions.js';\nimport { crosshairsCursor } from './cursors/index.js';\n\n/**\n * @public\n * @class CrosshairsTool\n * @memberof Tools\n *\n * @classdesc Tool for finding the slice in another element corresponding to the\n * image position in a synchronized image series.\n * @extends Tools.Base.BaseTool\n */\nexport default class CrosshairsTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Crosshairs',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: crosshairsCursor,\n };\n\n super(props, defaultProps);\n\n this.mouseDownCallback = this._chooseLocation.bind(this);\n this.mouseDragCallback = this._chooseLocation.bind(this);\n this.touchDragCallback = this._chooseLocation.bind(this);\n }\n\n _chooseLocation(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n\n // Prevent CornerstoneToolsTouchStartActive from killing any press events\n evt.stopImmediatePropagation();\n\n // If we have no toolData for this element, return immediately as there is nothing to do\n const toolData = getToolState(element, this.name);\n\n if (!toolData) {\n return;\n }\n\n // Get current element target information\n const sourceElement = element;\n const sourceEnabledElement = external.cornerstone.getEnabledElement(\n sourceElement\n );\n const sourceImageId = sourceEnabledElement.image.imageId;\n const sourceImagePlane = external.cornerstone.metaData.get(\n 'imagePlaneModule',\n sourceImageId\n );\n\n if (!sourceImagePlane) {\n return;\n }\n\n // Get currentPoints from mouse cursor on selected element\n const sourceImagePoint = eventData.currentPoints.image;\n\n // Transfer this to a patientPoint given imagePlane metadata\n const patientPoint = imagePointToPatientPoint(\n sourceImagePoint,\n sourceImagePlane\n );\n\n // Get the enabled elements associated with this synchronization context\n const syncContext = toolData.data[0].synchronizationContext;\n const enabledElements = syncContext.getSourceElements();\n\n // Iterate over each synchronized element\n enabledElements.forEach(function(targetElement) {\n // Don't do anything if the target is the same as the source\n if (targetElement === sourceElement) {\n return;\n }\n\n let minDistance = Number.MAX_VALUE;\n let newImageIdIndex = -1;\n\n const stackToolDataSource = getToolState(targetElement, 'stack');\n\n if (stackToolDataSource === undefined) {\n return;\n }\n\n const stackData = stackToolDataSource.data[0];\n\n // Find within the element's stack the closest image plane to selected location\n stackData.imageIds.forEach(function(imageId, index) {\n const imagePlane = external.cornerstone.metaData.get(\n 'imagePlaneModule',\n imageId\n );\n\n // Skip if the image plane is not ready\n if (\n !imagePlane ||\n !imagePlane.imagePositionPatient ||\n !imagePlane.rowCosines ||\n !imagePlane.columnCosines\n ) {\n return;\n }\n\n const imagePosition = convertToVector3(imagePlane.imagePositionPatient);\n const row = convertToVector3(imagePlane.rowCosines);\n const column = convertToVector3(imagePlane.columnCosines);\n const normal = column.clone().cross(row.clone());\n const distance = Math.abs(\n normal.clone().dot(imagePosition) - normal.clone().dot(patientPoint)\n );\n\n if (distance < minDistance) {\n minDistance = distance;\n newImageIdIndex = index;\n }\n });\n\n if (newImageIdIndex === stackData.currentImageIdIndex) {\n return;\n }\n\n // Switch the loaded image to the required image\n if (\n newImageIdIndex !== -1 &&\n stackData.imageIds[newImageIdIndex] !== undefined\n ) {\n const startLoadingHandler = loadHandlerManager.getStartLoadHandler(\n targetElement\n );\n const endLoadingHandler = loadHandlerManager.getEndLoadHandler(\n targetElement\n );\n const errorLoadingHandler = loadHandlerManager.getErrorLoadingHandler(\n targetElement\n );\n\n if (startLoadingHandler) {\n startLoadingHandler(targetElement);\n }\n\n let loader;\n\n if (stackData.preventCache === true) {\n loader = external.cornerstone.loadImage(\n stackData.imageIds[newImageIdIndex]\n );\n } else {\n loader = external.cornerstone.loadAndCacheImage(\n stackData.imageIds[newImageIdIndex]\n );\n }\n\n loader.then(\n function(image) {\n const viewport = external.cornerstone.getViewport(targetElement);\n\n stackData.currentImageIdIndex = newImageIdIndex;\n external.cornerstone.displayImage(targetElement, image, viewport);\n if (endLoadingHandler) {\n endLoadingHandler(targetElement, image);\n }\n },\n function(error) {\n const imageId = stackData.imageIds[newImageIdIndex];\n\n if (errorLoadingHandler) {\n errorLoadingHandler(targetElement, imageId, error);\n }\n }\n );\n }\n });\n }\n\n activeCallback(element, { mouseButtonMask, synchronizationContext }) {\n setToolOptions(this.name, element, { mouseButtonMask });\n\n // Clear any currently existing toolData\n clearToolState(element, this.name);\n\n addToolState(element, this.name, {\n synchronizationContext,\n });\n }\n}\n","import external from '../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\n\n/**\n * @public\n * @class DoubleTapFitToWindowTool\n * @memberof Tools\n *\n * @classdesc Tool which calls the external cornerstone.fitToWindow() function\n * on double tap.\n * @extends Tools.Base.BaseTool\n */\nexport default class DoubleTapFitToWindowTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'DoubleTapFitToWindow',\n supportedInteractionTypes: ['DoubleTap'],\n };\n\n super(props, defaultProps);\n }\n\n doubleTapCallback(evt) {\n const eventData = evt.detail;\n\n external.cornerstone.fitToWindow(eventData.element);\n }\n}\n","import external from '../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\n\nimport textStyle from '../stateManagement/textStyle.js';\nimport toolColors from '../stateManagement/toolColors.js';\nimport getRGBPixels from '../util/getRGBPixels.js';\nimport calculateSUV from '../util/calculateSUV.js';\nimport {\n getNewContext,\n draw,\n setShadow,\n drawCircle,\n} from '../drawing/index.js';\nimport drawTextBox, { textBoxWidth } from '../drawing/drawTextBox.js';\nimport { probeCursor } from './cursors/index.js';\n\n/**\n * @public\n * @class DragProbeTool\n * @memberof Tools\n *\n * @classdesc Tool which provides a probe of the image data at the\n * input position on drag.\n * @extends Tools.Base.BaseTool\n */\nexport default class DragProbeTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'DragProbe',\n strategies: {\n default: defaultStrategy,\n minimal: minimalStrategy,\n },\n defaultStrategy: 'default',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: probeCursor,\n };\n\n super(props, defaultProps);\n\n this.touchDragCallback = this._movingEventCallback.bind(this);\n this.touchEndCallback = this._endMovingEventCallback.bind(this);\n\n this.mouseDragCallback = this._movingEventCallback.bind(this);\n this.mouseUpCallback = this._endMovingEventCallback.bind(this);\n\n this.dragEventData = {};\n }\n\n _movingEventCallback(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n\n this.dragEventData = eventData;\n external.cornerstone.updateImage(element);\n }\n\n _endMovingEventCallback(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n\n this.dragEventData = {};\n external.cornerstone.updateImage(element);\n }\n\n renderToolData(evt) {\n if (!this.dragEventData.currentPoints) {\n return;\n }\n\n if (\n evt &&\n evt.detail &&\n Boolean(Object.keys(this.dragEventData.currentPoints).length)\n ) {\n evt.detail.currentPoints = this.dragEventData.currentPoints;\n this.applyActiveStrategy(evt);\n }\n }\n}\n\n/**\n * Default strategy will pick the exactly point of mouse/touch interact and display the probe data.\n *\n * @param {Object} evt Image rendered event\n * @returns {void}\n */\nfunction defaultStrategy(evt) {\n const config = this.configuration;\n const cornerstone = external.cornerstone;\n const eventData = evt.detail;\n const { element, image, currentPoints, canvasContext } = eventData;\n\n const context = getNewContext(canvasContext.canvas);\n\n const color = toolColors.getActiveColor();\n const fontHeight = textStyle.getFontSize();\n\n const x = Math.round(currentPoints.image.x);\n const y = Math.round(currentPoints.image.y);\n\n if (x < 0 || y < 0 || x >= image.columns || y >= image.rows) {\n return;\n }\n\n draw(context, context => {\n setShadow(context, config);\n\n const text = `${x}, ${y}`;\n let storedPixels;\n let str;\n\n if (image.color) {\n storedPixels = getRGBPixels(element, x, y, 1, 1);\n str = `R: ${storedPixels[0]} G: ${storedPixels[1]} B: ${\n storedPixels[2]\n } A: ${storedPixels[3]}`;\n } else {\n storedPixels = cornerstone.getStoredPixels(element, x, y, 1, 1);\n const sp = storedPixels[0];\n const mo = sp * image.slope + image.intercept;\n const suv = calculateSUV(image, sp);\n\n // Draw text\n str = `SP: ${sp} MO: ${parseFloat(mo.toFixed(3))}`;\n if (suv) {\n str += ` SUV: ${parseFloat(suv.toFixed(3))}`;\n }\n }\n\n // Draw text 5px away from cursor\n const textCoords = {\n x: currentPoints.canvas.x + 5,\n y: currentPoints.canvas.y - 5,\n };\n\n drawTextBox(\n context,\n str,\n textCoords.x,\n textCoords.y + fontHeight + 5,\n color\n );\n drawTextBox(context, text, textCoords.x, textCoords.y, color);\n });\n}\n\n/**\n * Minimal strategy will position a circle and use the center of the circle to calculate and display probe data.\n *\n * @param {Object} evt Image rendered event\n * @returns {void}\n */\nfunction minimalStrategy(evt) {\n const config = this.configuration;\n const cornerstone = external.cornerstone;\n const eventData = evt.detail;\n const {\n element,\n image,\n currentPoints,\n canvasContext,\n isTouchEvent,\n } = eventData;\n\n const context = getNewContext(canvasContext.canvas);\n const color = toolColors.getActiveColor();\n\n let pageCoordY = currentPoints.page.y - textStyle.getFontSize() / 2;\n\n if (isTouchEvent) {\n pageCoordY = currentPoints.page.y - textStyle.getFontSize() * 4;\n }\n const toolCoords = cornerstone.pageToPixel(\n element,\n currentPoints.page.x,\n pageCoordY\n );\n\n if (\n toolCoords.x < 0 ||\n toolCoords.y < 0 ||\n toolCoords.x >= image.columns ||\n toolCoords.y >= image.rows\n ) {\n return;\n }\n\n draw(context, context => {\n setShadow(context, config);\n\n const seriesModule = cornerstone.metaData.get(\n 'generalSeriesModule',\n image.imageId\n );\n const modality = seriesModule && seriesModule.modality;\n\n let storedPixels;\n let text = '';\n\n if (image.color) {\n storedPixels = getRGBPixels(element, toolCoords.x, toolCoords.y, 1, 1);\n text = `R: ${storedPixels[0]} G: ${storedPixels[1]} B: ${\n storedPixels[2]\n }`;\n } else {\n storedPixels = cornerstone.getStoredPixels(\n element,\n toolCoords.x,\n toolCoords.y,\n 1,\n 1\n );\n const sp = storedPixels[0];\n const mo = sp * image.slope + image.intercept;\n\n const modalityPixelValueText = parseFloat(mo.toFixed(2));\n\n if (modality === 'CT') {\n text += `HU: ${modalityPixelValueText}`;\n } else if (modality === 'PT') {\n text += modalityPixelValueText;\n const suv = calculateSUV(image, sp);\n\n if (suv) {\n text += ` SUV: ${parseFloat(suv.toFixed(2))}`;\n }\n } else {\n text += modalityPixelValueText;\n }\n }\n\n // Prepare text\n const textCoords = cornerstone.pixelToCanvas(element, toolCoords);\n\n // Translate the x/y away from the cursor\n let translation = {\n x: 12,\n y: -(textStyle.getFontSize() + 10) / 2,\n };\n\n const handleRadius = 6;\n const padding = 5;\n const width = textBoxWidth(context, text, padding);\n\n if (isTouchEvent) {\n translation = {\n x: -width / 2,\n y: -textStyle.getFontSize() - 10 - 2 * handleRadius,\n };\n }\n\n drawCircle(context, element, textCoords, handleRadius, { color }, 'canvas');\n drawTextBox(\n context,\n text,\n textCoords.x + translation.x,\n textCoords.y + translation.y,\n color\n );\n });\n}\n","import external from '../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\nimport { getToolState, removeToolState } from '../stateManagement/toolState.js';\nimport { state } from '../store/index.js';\nimport { eraserCursor } from './cursors/index.js';\n\n/**\n * @public\n * @class EraserTool\n * @memberof Tools\n *\n * @classdesc Tool for deleting the data of other Annotation Tools.\n * @extends Tools.Base.BaseTool\n */\nexport default class EraserTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Eraser',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: eraserCursor,\n };\n\n super(props, defaultProps);\n\n this.preMouseDownCallback = this._deleteAllNearbyTools.bind(this);\n this.preTouchStartCallback = this._deleteAllNearbyTools.bind(this);\n }\n\n _deleteAllNearbyTools(evt) {\n const coords = evt.detail.currentPoints.canvas;\n const element = evt.detail.element;\n\n state.tools.forEach(function(tool) {\n const toolState = getToolState(element, tool.name);\n\n if (toolState) {\n // Modifying in a foreach? Probably not ideal\n toolState.data.forEach(function(data) {\n if (\n typeof tool.pointNearTool === 'function' &&\n tool.pointNearTool(element, data, coords)\n ) {\n removeToolState(element, tool.name, data);\n external.cornerstone.updateImage(element);\n }\n });\n }\n });\n\n const consumeEvent = true;\n\n return consumeEvent;\n }\n}\n","import EVENTS from '../events.js';\nimport external from '../externalModules.js';\nimport toolColors from '../stateManagement/toolColors.js';\nimport drawHandles from '../drawing/drawHandles.js';\nimport { state } from '../store/index.js';\nimport { getToolState } from '../stateManagement/toolState.js';\nimport { clipToBox } from '../util/clip.js';\nimport getToolForElement from '../store/getToolForElement.js';\nimport BaseTool from './base/BaseTool.js';\nimport { hideToolCursor, setToolCursor } from '../store/setToolCursor.js';\nimport { freehandRoiSculptorCursor } from './cursors/index.js';\n\nimport freehandUtils from '../util/freehand/index.js';\n\nconst { FreehandHandleData } = freehandUtils;\n\n/**\n * @public\n * @class FreehandRoiSculptorTool\n * @memberof Tools\n *\n * @classdesc Tool for easily sculpting annotations drawn with\n * the FreehandRoiTool.\n * @extends Tools.Base.BaseTool\n */\nexport default class FreehandRoiSculptorTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'FreehandRoiSculptor',\n referencedToolName: 'FreehandRoi',\n supportedInteractionTypes: ['Mouse', 'Touch', 'DoubleTap'],\n mixins: ['activeOrDisabledBinaryTool'],\n configuration: getDefaultFreehandRoiSculptorToolConfiguration(),\n svgCursor: freehandRoiSculptorCursor,\n };\n\n super(props, defaultProps);\n\n this.updateOnMouseMove = true;\n this.isMultiPartTool = true;\n this.referencedToolName = this.initialConfiguration.referencedToolName;\n\n this._active = false;\n\n // Create bound functions for private event loop.\n this.activeMouseUpCallback = this.activeMouseUpCallback.bind(this);\n this.activeTouchEndCallback = this.activeTouchEndCallback.bind(this);\n this.activeMouseDragCallback = this.activeMouseDragCallback.bind(this);\n }\n\n renderToolData(evt) {\n const eventData = evt.detail;\n\n if (this.configuration.currentTool === null) {\n return false;\n }\n\n const element = eventData.element;\n const config = this.configuration;\n\n const toolState = getToolState(element, this.referencedToolName);\n const data = toolState.data[config.currentTool];\n\n if (!data) {\n return false;\n }\n\n if (this._active) {\n const context = eventData.canvasContext.canvas.getContext('2d');\n const options = {\n color: this.configuration.dragColor,\n fill: null,\n handleRadius: this._toolSizeCanvas,\n };\n\n drawHandles(\n context,\n eventData,\n this.configuration.mouseLocation.handles,\n options\n );\n } else if (this.configuration.showCursorOnHover && !this._recentTouchEnd) {\n this._renderHoverCursor(evt);\n }\n }\n\n doubleClickCallback(evt) {\n const eventData = evt.detail;\n\n this._selectFreehandTool(eventData);\n external.cornerstone.updateImage(eventData.element);\n }\n\n doubleTapCallback(evt) {\n const eventData = evt.detail;\n\n this._selectFreehandTool(eventData);\n external.cornerstone.updateImage(eventData.element);\n }\n\n preTouchStartCallback(evt) {\n this._initialiseSculpting(evt);\n\n return true;\n }\n\n /**\n * Event handler for MOUSE_DOWN.\n *\n * @param {Object} evt - The event.\n * @returns {boolean}\n */\n preMouseDownCallback(evt) {\n if (!this.options.mouseButtonMask.includes(evt.detail.buttons)) {\n return;\n }\n\n this._initialiseSculpting(evt);\n\n return true;\n }\n\n /**\n * Event handler for MOUSE_DRAG during the active loop.\n *\n * @event\n * @param {Object} evt - The event.\n * @returns {void}\n */\n activeMouseDragCallback(evt) {\n const config = this.configuration;\n\n if (!this._active) {\n return;\n }\n\n const eventData = evt.detail;\n const toolState = getToolState(eventData.element, this.referencedToolName);\n\n if (!toolState) {\n return;\n }\n\n const points = toolState.data[config.currentTool].handles.points;\n\n // Set the mouseLocation handle\n this._getMouseLocation(eventData);\n this._sculpt(eventData, points);\n\n // Update the image\n external.cornerstone.updateImage(eventData.element);\n }\n\n /**\n * Event handler for MOUSE_UP during the active loop.\n *\n * @param {Object} evt - The event.\n * @returns {void}\n */\n activeMouseUpCallback(evt) {\n this._activeEnd(evt);\n }\n\n /**\n * Event handler for TOUCH_END during the active loop.\n *\n * @param {Object} evt - The event.\n * @returns {void}\n */\n activeTouchEndCallback(evt) {\n this._activeEnd(evt);\n\n this._deselectAllTools(evt);\n this._recentTouchEnd = true;\n }\n\n _activeEnd(evt) {\n const eventData = evt.detail;\n const element = eventData.element;\n const config = this.configuration;\n\n this._active = false;\n\n state.isMultiPartToolActive = false;\n\n this._getMouseLocation(eventData);\n this._invalidateToolData(eventData);\n\n config.mouseUpRender = true;\n\n this._deactivateSculpt(element);\n\n // Update the image\n external.cornerstone.updateImage(eventData.element);\n\n preventPropagation(evt);\n }\n\n /**\n * Renders the cursor\n *\n * @private\n * @param {type} evt description\n * @returns {void}\n */\n _renderHoverCursor(evt) {\n const eventData = evt.detail;\n const element = eventData.element;\n const context = eventData.canvasContext.canvas.getContext('2d');\n\n const toolState = getToolState(element, this.referencedToolName);\n const data = toolState.data[this.configuration.currentTool];\n\n this._recentTouchEnd = false;\n\n let coords;\n\n if (this.configuration.mouseUpRender) {\n coords = this.configuration.mouseLocation.handles.start;\n this.configuration.mouseUpRender = false;\n } else {\n coords = state.mousePositionImage;\n }\n\n const freehandRoiTool = getToolForElement(element, this.referencedToolName);\n let radiusCanvas = freehandRoiTool.distanceFromPointCanvas(\n element,\n data,\n coords\n );\n\n this.configuration.mouseLocation.handles.start.x = coords.x;\n this.configuration.mouseLocation.handles.start.y = coords.y;\n\n if (this.configuration.limitRadiusOutsideRegion) {\n const unlimitedRadius = radiusCanvas;\n\n radiusCanvas = this._limitCursorRadiusCanvas(eventData, radiusCanvas);\n\n // Fade if distant\n if (\n unlimitedRadius >\n this.configuration.hoverCursorFadeDistance * radiusCanvas\n ) {\n context.globalAlpha = this.configuration.hoverCursorFadeAlpha;\n }\n }\n\n const options = {\n fill: null,\n color: this.configuration.hoverColor,\n handleRadius: radiusCanvas,\n };\n\n drawHandles(\n context,\n eventData,\n this.configuration.mouseLocation.handles,\n options\n );\n\n if (this.configuration.limitRadiusOutsideRegion) {\n context.globalAlpha = 1.0; // Reset drawing alpha for other draw calls.\n }\n }\n\n /**\n * Event handler for NEW_IMAGE event.\n *\n * @public\n * @param {Object} evt - The event.\n * @returns {void}\n */\n newImageCallback(evt) {\n this._deselectAllTools(evt);\n }\n\n /**\n * Event handler for switching mode to enabled.\n *\n * @public\n * @param {Object} evt - The event.\n * @returns {void}\n */\n enabledCallback(evt) {\n this._deselectAllTools(evt);\n }\n\n /**\n * Event handler for switching mode to passive.\n *\n * @public\n * @param {Object} evt - The event.\n * @returns {void}\n */\n passiveCallback(evt) {\n this._deselectAllTools(evt);\n }\n\n /**\n * Event handler for switching mode to disabled.\n *\n * @public\n * @param {Object} evt - The event.\n * @returns {void}\n */\n disabledCallback(evt) {\n this._deselectAllTools(evt);\n }\n\n /**\n * Select the freehand tool to be edited.\n *\n * @private\n * @param {Object} eventData - Data object associated with the event.\n * @returns {void}\n */\n _selectFreehandTool(eventData) {\n const config = this.configuration;\n const element = eventData.element;\n const closestToolIndex = this._getClosestFreehandToolOnElement(\n element,\n eventData\n );\n\n if (closestToolIndex === undefined) {\n return;\n }\n\n config.currentTool = closestToolIndex;\n hideToolCursor(element);\n }\n\n /**\n * Activate the selected freehand tool and deactivate others.\n *\n * @private\n * @param {Object} element - The parent element of the freehand tool.\n * @param {Number} toolIndex - The ID of the freehand tool.\n * @returns {void}\n */\n _activateFreehandTool(element, toolIndex) {\n const toolState = getToolState(element, this.referencedToolName);\n const data = toolState.data;\n const config = this.configuration;\n\n config.currentTool = toolIndex;\n\n for (let i = 0; i < data.length; i++) {\n if (i === toolIndex) {\n data[i].active = true;\n } else {\n data[i].active = false;\n }\n }\n }\n\n /**\n * Choose the tool radius from the mouse position relative to the active freehand\n * tool, and begin sculpting.\n *\n * @private\n * @param {Object} evt - The event.\n * @returns {void}\n */\n _initialiseSculpting(evt) {\n const eventData = evt.detail;\n const config = this.configuration;\n const element = eventData.element;\n\n if (config.currentTool === null) {\n this._selectFreehandTool(eventData);\n\n if (config.currentTool === null) {\n return;\n }\n }\n\n this._active = true;\n\n // Interupt event dispatcher\n state.isMultiPartToolActive = true;\n\n this._configureToolSize(eventData);\n this._getMouseLocation(eventData);\n\n this._activateFreehandTool(element, config.currentTool);\n this._activateSculpt(element);\n\n external.cornerstone.updateImage(eventData.element);\n }\n\n /**\n * Sculpts the freehand ROI with the circular freehandSculpter tool, moving,\n * adding and removing handles as necessary.\n *\n * @private\n * @param {Object} eventData - Data object associated with the event.\n * @param {Object} points - Array of points.\n * @returns {void}\n */\n _sculpt(eventData, points) {\n const config = this.configuration;\n\n this._sculptData = {\n element: eventData.element,\n image: eventData.image,\n mousePoint: eventData.currentPoints.image,\n points,\n toolSize: this._toolSizeImage,\n minSpacing: config.minSpacing,\n maxSpacing: Math.max(this._toolSizeImage, config.minSpacing * 2),\n };\n\n // Push existing handles radially away from tool.\n const pushedHandles = this._pushHandles();\n // Insert new handles in sparsely populated areas of the\n // Pushed part of the contour.\n\n if (pushedHandles.first !== undefined) {\n this._insertNewHandles(pushedHandles);\n // If any handles have been pushed very close together or even overlap,\n // Combine these into a single handle.\n this._consolidateHandles();\n }\n }\n\n /**\n * _pushHandles -Pushes the points radially away from the mouse if they are\n * contained within the circle defined by the freehandSculpter's toolSize and\n * the mouse position.\n *\n * @returns {Object} The first and last pushedHandles.\n */\n _pushHandles() {\n const { points, mousePoint, toolSize } = this._sculptData;\n const pushedHandles = {};\n\n for (let i = 0; i < points.length; i++) {\n const distanceToHandle = external.cornerstoneMath.point.distance(\n points[i],\n mousePoint\n );\n\n if (distanceToHandle > toolSize) {\n continue;\n }\n\n // Push point if inside circle, to edge of circle.\n this._pushOneHandle(i, distanceToHandle);\n if (pushedHandles.first === undefined) {\n pushedHandles.first = i;\n pushedHandles.last = i;\n } else {\n pushedHandles.last = i;\n }\n }\n\n return pushedHandles;\n }\n\n /**\n * Pushes one handle.\n *\n * @private\n * @param {number} i - The index of the handle to push.\n * @param {number} distanceToHandle - The distance between the mouse cursor and the handle.\n * @returns {void}\n */\n _pushOneHandle(i, distanceToHandle) {\n const { points, mousePoint, toolSize, image } = this._sculptData;\n const handle = points[i];\n\n const directionUnitVector = {\n x: (handle.x - mousePoint.x) / distanceToHandle,\n y: (handle.y - mousePoint.y) / distanceToHandle,\n };\n\n const position = {\n x: mousePoint.x + toolSize * directionUnitVector.x,\n y: mousePoint.y + toolSize * directionUnitVector.y,\n };\n\n clipToBox(position, image);\n\n handle.x = position.x;\n handle.y = position.y;\n\n // Push lines\n const lastHandleIndex = this.constructor._getPreviousHandleIndex(\n i,\n points.length\n );\n\n points[lastHandleIndex].lines.pop();\n points[lastHandleIndex].lines.push(handle);\n }\n\n /**\n * Inserts additional handles in sparsely sampled regions of the contour. The\n * new handles are placed on the circle defined by the the freehandSculpter's\n * toolSize and the mouse position.\n * @private\n * @param {Array} pushedHandles\n * @returns {void}\n */\n _insertNewHandles(pushedHandles) {\n const indiciesToInsertAfter = this._findNewHandleIndicies(pushedHandles);\n let newIndexModifier = 0;\n\n for (let i = 0; i < indiciesToInsertAfter.length; i++) {\n const insertIndex = indiciesToInsertAfter[i] + 1 + newIndexModifier;\n\n this._insertHandleRadially(insertIndex);\n newIndexModifier++;\n }\n }\n\n /**\n * Returns an array of indicies that describe where new handles should be\n * inserted (where the distance between subsequent handles is >\n * config.maxSpacing).\n *\n * @private\n * @param {Object} pushedHandles - The first and last handles that were pushed.\n * @returns {Object} An array of indicies that describe where new handles should be inserted.\n */\n _findNewHandleIndicies(pushedHandles) {\n const { points, maxSpacing } = this._sculptData;\n const indiciesToInsertAfter = [];\n\n for (let i = pushedHandles.first; i <= pushedHandles.last; i++) {\n this._checkSpacing(i, points, indiciesToInsertAfter, maxSpacing);\n }\n\n const pointAfterLast = this.constructor._getNextHandleIndex(\n pushedHandles.last,\n points.length\n );\n\n // Check points before and after those pushed.\n if (pointAfterLast !== pushedHandles.first) {\n this._checkSpacing(\n pointAfterLast,\n points,\n indiciesToInsertAfter,\n maxSpacing\n );\n\n const pointBeforeFirst = this.constructor._getPreviousHandleIndex(\n pushedHandles.first,\n points.length\n );\n\n if (pointBeforeFirst !== pointAfterLast) {\n this._checkSpacing(\n pointBeforeFirst,\n points,\n indiciesToInsertAfter,\n maxSpacing\n );\n }\n }\n\n return indiciesToInsertAfter;\n }\n\n /**\n * _checkSpacing - description\n *@modifies indiciesToInsertAfter\n *\n * @param {number} i - The index to check.\n * @param {Object} points - The points.\n * @param {Array} indiciesToInsertAfter - The working list of indicies to insert new points after.\n * @param {number} maxSpacing\n * @returns {void}\n */\n _checkSpacing(i, points, indiciesToInsertAfter, maxSpacing) {\n const nextHandleIndex = this.constructor._getNextHandleIndex(\n i,\n points.length\n );\n\n const distanceToNextHandle = external.cornerstoneMath.point.distance(\n points[i],\n points[nextHandleIndex]\n );\n\n if (distanceToNextHandle > maxSpacing) {\n indiciesToInsertAfter.push(i);\n }\n }\n\n /**\n * Inserts a handle on the surface of the circle defined by toolSize and the\n * mousePoint.\n *\n * @private\n * @param {number} insertIndex - The index to insert the new handle.\n * @returns {void}\n */\n _insertHandleRadially(insertIndex) {\n const { points } = this._sculptData;\n\n const previousIndex = insertIndex - 1;\n const nextIndex = this.constructor._getNextHandleIndexBeforeInsert(\n insertIndex,\n points.length\n );\n const insertPosition = this._getInsertPosition(\n insertIndex,\n previousIndex,\n nextIndex\n );\n const handleData = new FreehandHandleData(insertPosition);\n\n points.splice(insertIndex, 0, handleData);\n\n // Add the line from the previous handle to the inserted handle (note the tool is now one increment longer)\n points[previousIndex].lines.pop();\n points[previousIndex].lines.push(points[insertIndex]);\n\n freehandUtils.addLine(points, insertIndex);\n }\n\n /**\n * Checks for any close points and consolidates these to a\n * single point.\n *\n * @private\n * @returns {void}\n */\n _consolidateHandles() {\n const { points } = this._sculptData;\n\n // Don't merge handles if it would destroy the polygon.\n if (points.length <= 3) {\n return;\n }\n\n const closePairs = this._findCloseHandlePairs();\n\n this._mergeCloseHandles(closePairs);\n }\n\n /**\n * Finds pairs of close handles with seperations < config.minSpacing. No handle\n * is included in more than one pair, to avoid spurious deletion of densely\n * populated regions of the contour (see mergeCloseHandles).\n *\n * @private\n * @returns {Array} An array of close pairs in points.\n */\n _findCloseHandlePairs() {\n const { points, minSpacing } = this._sculptData;\n const closePairs = [];\n let length = points.length;\n\n for (let i = 0; i < length; i++) {\n const nextHandleIndex = this.constructor._getNextHandleIndex(\n i,\n points.length\n );\n\n const distanceToNextHandle = external.cornerstoneMath.point.distance(\n points[i],\n points[nextHandleIndex]\n );\n\n if (distanceToNextHandle < minSpacing) {\n const pair = [i, nextHandleIndex];\n\n closePairs.push(pair);\n\n // Don't check last node if first in pair to avoid double counting.\n if (i === 0) {\n length -= 1;\n }\n\n // Don't double count pairs in order to prevent your polygon collapsing to a singularity.\n i++;\n }\n }\n\n return closePairs;\n }\n\n /**\n * Merges points given a list of close pairs. The points are merged in an\n * iterative fashion to prevent generating a singularity in some edge cases.\n *\n * @private\n * @param {Array} closePairs - An array of pairs of handle indicies.\n * @returns {void}\n */\n _mergeCloseHandles(closePairs) {\n let removedIndexModifier = 0;\n\n for (let i = 0; i < closePairs.length; i++) {\n const pair = this.constructor._getCorrectedPair(\n closePairs[i],\n removedIndexModifier\n );\n\n this._combineHandles(pair);\n removedIndexModifier++;\n }\n\n // Recursively remove problem childs\n const newClosePairs = this._findCloseHandlePairs();\n\n if (newClosePairs.length) {\n this._mergeCloseHandles(newClosePairs);\n }\n }\n\n /**\n * Combines two handles defined by the indicies in handlePairs.\n *\n * @private\n * @param {Object} handlePair - A pair of handle indicies.\n * @returns {void}\n */\n _combineHandles(handlePair) {\n const { points, image } = this._sculptData;\n\n // Calculate combine position: half way between the handles.\n const midPoint = {\n x: (points[handlePair[0]].x + points[handlePair[1]].x) / 2.0,\n y: (points[handlePair[0]].y + points[handlePair[1]].y) / 2.0,\n };\n\n clipToBox(midPoint, image);\n\n // Move first point to midpoint\n points[handlePair[0]].x = midPoint.x;\n points[handlePair[0]].y = midPoint.y;\n\n // Link first point to handle that second point links to.\n const handleAfterPairIndex = this.constructor._getNextHandleIndex(\n handlePair[1],\n points.length\n );\n\n points[handlePair[0]].lines.pop();\n points[handlePair[0]].lines.push(points[handleAfterPairIndex]);\n\n // Remove the latter handle\n points.splice(handlePair[1], 1);\n }\n\n /**\n * Calculates the distance to the closest handle in the tool, and stores the\n * result in this._toolSizeImage and this._toolSizeCanvas.\n *\n * @private\n * @param {Object} eventData - Data object associated with the event.\n * @returns {void}\n */\n _configureToolSize(eventData) {\n const element = eventData.element;\n const config = this.configuration;\n const toolIndex = config.currentTool;\n const coords = eventData.currentPoints.image;\n\n const toolState = getToolState(element, this.referencedToolName);\n const data = toolState.data[toolIndex];\n\n const freehandRoiTool = getToolForElement(element, this.referencedToolName);\n\n let radiusImage = freehandRoiTool.distanceFromPoint(element, data, coords);\n let radiusCanvas = freehandRoiTool.distanceFromPointCanvas(\n element,\n data,\n coords\n );\n\n // Check if should limit maximum size.\n if (config.limitRadiusOutsideRegion) {\n radiusImage = this._limitCursorRadiusImage(eventData, radiusImage);\n radiusCanvas = this._limitCursorRadiusCanvas(eventData, radiusCanvas);\n }\n\n this._toolSizeImage = radiusImage;\n this._toolSizeCanvas = radiusCanvas;\n }\n\n /**\n * Gets the current mouse location and stores it in the configuration object.\n *\n * @private\n * @param {Object} eventData - The data assoicated with the event.\n * @returns {void}\n */\n _getMouseLocation(eventData) {\n const config = this.configuration;\n\n config.mouseLocation.handles.start.x = eventData.currentPoints.image.x;\n config.mouseLocation.handles.start.y = eventData.currentPoints.image.y;\n clipToBox(config.mouseLocation.handles.start, eventData.image);\n }\n\n /**\n * Attaches event listeners to the element such that is is visible, modifiable, and new data can be created.\n *\n * @private\n * @param {Object} element - The viewport element to attach event listeners to.\n * @modifies {element}\n * @returns {void}\n */\n _activateSculpt(element) {\n this._deactivateSculpt(element);\n\n // Begin activeMouseDragCallback loop - call activeMouseUpCallback at end of drag or straight away if just a click.\n element.addEventListener(EVENTS.MOUSE_UP, this.activeMouseUpCallback);\n element.addEventListener(EVENTS.MOUSE_CLICK, this.activeMouseUpCallback);\n element.addEventListener(EVENTS.MOUSE_DRAG, this.activeMouseDragCallback);\n\n element.addEventListener(EVENTS.TOUCH_END, this.activeTouchEndCallback);\n element.addEventListener(EVENTS.TOUCH_TAP, this.activeTouchEndCallback);\n element.addEventListener(EVENTS.TOUCH_DRAG, this.activeMouseDragCallback);\n\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Removes event listeners from the element.\n *\n * @private\n * @param {Object} element - The viewport element to remove event listeners from.\n * @modifies {element}\n * @returns {void}\n */\n _deactivateSculpt(element) {\n element.removeEventListener(EVENTS.MOUSE_UP, this.activeMouseUpCallback);\n element.removeEventListener(EVENTS.MOUSE_CLICK, this.activeMouseUpCallback);\n element.removeEventListener(\n EVENTS.MOUSE_DRAG,\n this.activeMouseDragCallback\n );\n\n element.removeEventListener(EVENTS.TOUCH_END, this.activeTouchEndCallback);\n element.removeEventListener(EVENTS.TOUCH_TAP, this.activeTouchEndCallback);\n element.removeEventListener(\n EVENTS.TOUCH_DRAG,\n this.activeMouseDragCallback\n );\n\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Invalidate the freehand tool data, tirggering re-calculation of statistics.\n *\n * @private\n * @param {Object} eventData - Data object associated with the event.\n * @returns {void}\n */\n _invalidateToolData(eventData) {\n const config = this.configuration;\n const element = eventData.element;\n const toolData = getToolState(element, this.referencedToolName);\n const data = toolData.data[config.currentTool];\n\n data.invalidated = true;\n }\n\n /**\n * Deactivates all freehand ROIs and change currentTool to null\n *\n * @private\n * @param {Object} evt - The event.\n * @returns {void}\n */\n // eslint-disable-next-line no-unused-vars\n _deselectAllTools(evt) {\n const config = this.configuration;\n const toolData = getToolState(this.element, this.referencedToolName);\n\n config.currentTool = null;\n\n if (toolData) {\n for (let i = 0; i < toolData.data.length; i++) {\n toolData.data[i].active = false;\n }\n }\n\n setToolCursor(this.element, this.svgCursor);\n\n external.cornerstone.updateImage(this.element);\n }\n\n /**\n * Given a pair of indicies, and the number of points already removed,\n * convert to the correct live indicies.\n *\n * @private\n * @static\n * @param {Object} pair A pairs of handle indicies.\n * @param {Number} removedIndexModifier The number of handles already removed.\n * @returns {Object} The corrected pair of handle indicies.\n */\n static _getCorrectedPair(pair, removedIndexModifier) {\n const correctedPair = [\n pair[0] - removedIndexModifier,\n pair[1] - removedIndexModifier,\n ];\n\n // Deal with edge case of last node + first node.\n if (correctedPair[1] < 0) {\n correctedPair[1] = 0;\n }\n\n return correctedPair;\n }\n\n /**\n * Limits the cursor radius so that it its maximum area is the same as the\n * ROI being sculpted (in canvas coordinates).\n *\n * @private\n * @param {Object} eventData Data object associated with the event.\n * @param {Number} radiusCanvas The distance from the mouse to the ROI\n * in canvas coordinates.\n * @returns {Number} The limited radius in canvas coordinates.\n */\n _limitCursorRadiusCanvas(eventData, radiusCanvas) {\n return this._limitCursorRadius(eventData, radiusCanvas, true);\n }\n\n /**\n * Limits the cursor radius so that it its maximum area is the same as the\n * ROI being sculpted (in image coordinates).\n *\n * @private\n * @param {Object} eventData Data object associated with the event.\n * @param {Number} radiusImage The distance from the mouse to the ROI\n * in image coordinates.\n * @returns {Number} The limited radius in image coordinates.\n */\n _limitCursorRadiusImage(eventData, radiusImage) {\n return this._limitCursorRadius(eventData, radiusImage, false);\n }\n\n /**\n * Limits the cursor radius so that it its maximum area is the same as the\n * ROI being sculpted.\n *\n * @private\n * @param {Object} eventData Data object associated with the event.\n * @param {Number} radius The distance from the mouse to the ROI.\n * @param {Boolean} canvasCoords Whether the calculation should be performed\n * In canvas coordinates.\n * @returns {Number} The limited radius.\n */\n _limitCursorRadius(eventData, radius, canvasCoords = false) {\n const element = eventData.element;\n const image = eventData.image;\n const config = this.configuration;\n\n const toolState = getToolState(element, this.referencedToolName);\n const data = toolState.data[config.currentTool];\n\n let areaModifier = 1.0;\n\n if (canvasCoords) {\n const topLeft = external.cornerstone.pixelToCanvas(element, {\n x: 0,\n y: 0,\n });\n const bottomRight = external.cornerstone.pixelToCanvas(element, {\n x: image.width,\n y: image.height,\n });\n const canvasArea =\n (bottomRight.x - topLeft.x) * (bottomRight.y - topLeft.y);\n\n areaModifier = canvasArea / (image.width * image.height);\n }\n\n const area = data.area * areaModifier;\n const maxRadius = Math.pow(area / Math.PI, 0.5);\n\n return Math.min(radius, maxRadius);\n }\n\n /**\n * Finds the nearest handle to the mouse cursor for all freehand\n * data on the element.\n *\n * @private\n * @param {Object} element - The element.\n * @param {Object} eventData - Data object associated with the event.\n * @returns {Number} The tool index of the closest freehand tool.\n */\n _getClosestFreehandToolOnElement(element, eventData) {\n const freehand = getToolForElement(element, this.referencedToolName);\n const toolState = getToolState(element, this.referencedToolName);\n\n if (!toolState) {\n return;\n }\n\n const data = toolState.data;\n const pixelCoords = eventData.currentPoints.image;\n\n const closest = {\n distance: Infinity,\n toolIndex: null,\n };\n\n for (let i = 0; i < data.length; i++) {\n const distanceFromToolI = freehand.distanceFromPoint(\n element,\n data[i],\n pixelCoords\n );\n\n if (distanceFromToolI === -1) {\n continue;\n }\n\n if (distanceFromToolI < closest.distance) {\n closest.distance = distanceFromToolI;\n closest.toolIndex = i;\n }\n }\n\n return closest.toolIndex;\n }\n\n /**\n * Returns the next handle index.\n *\n * @private\n * @static\n * @param {Number} i - The handle index.\n * @param {Number} length - The length of the polygon.\n * @returns {Number} The next handle index.\n */\n static _getNextHandleIndex(i, length) {\n if (i === length - 1) {\n return 0;\n }\n\n return i + 1;\n }\n\n /**\n * Returns the previous handle index.\n *\n * @private\n * @static\n * @param {Number} i - The handle index.\n * @param {Number} length - The length of the polygon.\n * @returns {Number} The previous handle index.\n */\n static _getPreviousHandleIndex(i, length) {\n if (i === 0) {\n return length - 1;\n }\n\n return i - 1;\n }\n\n /**\n * Returns the next handle index, with a correction considering a handle is\n * about to be inserted.\n *\n * @private\n * @static\n * @param {Number} insertIndex - The index in which the handle is being inserted.\n * @param {Number} length - The length of the polygon.\n * @returns {Number} The next handle index.\n */\n static _getNextHandleIndexBeforeInsert(insertIndex, length) {\n if (insertIndex === length) {\n return 0;\n }\n // Index correction here: The line bellow is correct, as we haven't inserted our handle yet!\n\n return insertIndex;\n }\n\n /**\n * Calculates the position that a new handle should be inserted.\n *\n * @private\n * @static\n * @param {Number} insertIndex - The index to insert the new handle.\n * @param {Number} previousIndex - The previous index.\n * @param {Number} nextIndex - The next index.\n * @returns {Object} The position the handle should be inserted.\n */\n _getInsertPosition(insertIndex, previousIndex, nextIndex) {\n const { points, toolSize, mousePoint, image } = this._sculptData;\n\n // Calculate insert position: half way between the handles, then pushed out\n // Radially to the edge of the freehandSculpter.\n const midPoint = {\n x: (points[previousIndex].x + points[nextIndex].x) / 2.0,\n y: (points[previousIndex].y + points[nextIndex].y) / 2.0,\n };\n\n const distanceToMidPoint = external.cornerstoneMath.point.distance(\n mousePoint,\n midPoint\n );\n\n let insertPosition;\n\n if (distanceToMidPoint < toolSize) {\n const directionUnitVector = {\n x: (midPoint.x - mousePoint.x) / distanceToMidPoint,\n y: (midPoint.y - mousePoint.y) / distanceToMidPoint,\n };\n\n insertPosition = {\n x: mousePoint.x + toolSize * directionUnitVector.x,\n y: mousePoint.y + toolSize * directionUnitVector.y,\n };\n } else {\n insertPosition = midPoint;\n }\n\n clipToBox(insertPosition, image);\n\n return insertPosition;\n }\n\n // ===================================================================\n // Public Configuration API. .\n // ===================================================================\n\n get minSpacing() {\n return this.configuration.minSpacing;\n }\n\n set minSpacing(value) {\n if (typeof value !== 'number') {\n throw new Error(\n 'Attempting to set freehandSculpter minSpacing to a value other than a number.'\n );\n }\n\n this.configuration.minSpacing = value;\n }\n\n get maxSpacing() {\n return this.configuration.maxSpacing;\n }\n\n set maxSpacing(value) {\n if (typeof value !== 'number') {\n throw new Error(\n 'Attempting to set freehandSculpter maxSpacing to a value other than a number.'\n );\n }\n\n this.configuration.maxSpacing = value;\n }\n\n get showCursorOnHover() {\n return this.configuration.showCursorOnHover;\n }\n\n set showCursorOnHover(value) {\n if (typeof value !== 'boolean') {\n throw new Error(\n 'Attempting to set freehandSculpter showCursorOnHover to a value other than a boolean.'\n );\n }\n\n this.configuration.showCursorOnHover = value;\n external.cornerstone.updateImage(this.element);\n }\n\n get limitRadiusOutsideRegion() {\n return this.configuration.limitRadiusOutsideRegion;\n }\n\n set limitRadiusOutsideRegion(value) {\n if (typeof value !== 'boolean') {\n throw new Error(\n 'Attempting to set freehandSculpter limitRadiusOutsideRegion to a value other than a boolean.'\n );\n }\n\n this.configuration.limitRadiusOutsideRegion = value;\n external.cornerstone.updateImage(this.element);\n }\n\n get hoverCursorFadeAlpha() {\n return this.configuration.hoverCursorFadeAlpha;\n }\n\n set hoverCursorFadeAlpha(value) {\n if (typeof value !== 'number') {\n throw new Error(\n 'Attempting to set freehandSculpter hoverCursorFadeAlpha to a value other than a number.'\n );\n }\n\n // Clamp the value from 0 to 1.\n value = Math.max(Math.min(value, 1.0), 0.0);\n\n this.configuration.hoverCursorFadeAlpha = value;\n external.cornerstone.updateImage(this.element);\n }\n\n get hoverCursorFadeDistance() {\n return this.configuration.hoverCursorFadeDistance;\n }\n\n set hoverCursorFadeDistance(value) {\n if (typeof value !== 'number') {\n throw new Error(\n 'Attempting to set freehandSculpter hoverCursorFadeDistance to a value other than a number.'\n );\n }\n\n // Don't allow to fade a distances smaller than the tool's radius.\n value = Math.max(value, 1.0);\n\n this.configuration.hoverCursorFadeDistance = value;\n external.cornerstone.updateImage(this.element);\n }\n}\n\n/**\n * Returns the default freehandRoiSculptorTool configuration.\n *\n * @returns {Object} The default configuration object.\n */\nfunction getDefaultFreehandRoiSculptorToolConfiguration() {\n return {\n mouseLocation: {\n handles: {\n start: {\n highlight: true,\n active: true,\n },\n },\n },\n minSpacing: 1,\n currentTool: null,\n dragColor: toolColors.getActiveColor(),\n hoverColor: toolColors.getToolColor(),\n\n /* --- Hover options ---\n showCursorOnHover: Shows a preview of the sculpting radius on hover.\n limitRadiusOutsideRegion: Limit max toolsize outside the subject ROI based\n on subject ROI area.\n hoverCursorFadeAlpha: Alpha to fade to when tool very distant from\n subject ROI.\n hoverCursorFadeDistance: Distance from ROI in which to fade the hoverCursor\n (in units of radii).\n */\n showCursorOnHover: true,\n limitRadiusOutsideRegion: true,\n hoverCursorFadeAlpha: 0.5,\n hoverCursorFadeDistance: 1.2,\n };\n}\n\nfunction preventPropagation(evt) {\n evt.stopImmediatePropagation();\n evt.stopPropagation();\n evt.preventDefault();\n}\n","import external from '../externalModules.js';\nimport { getNewContext } from '../drawing/index.js';\nimport BaseTool from './base/BaseTool.js';\nimport { hideToolCursor, setToolCursor } from '../store/setToolCursor.js';\nimport { magnifyCursor } from './cursors/index.js';\n\n/**\n * @public\n * @class MagnifyTool\n * @memberof Tools\n *\n * @classdesc Tool for inspecting a region at increased magnification.\n * @extends Tools.Base.BaseTool\n */\nexport default class MagnifyTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Magnify',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {\n magnifySize: 300,\n magnificationLevel: 2,\n },\n svgCursor: magnifyCursor,\n };\n\n super(props, defaultProps);\n\n this.zoomCanvas = undefined;\n this.zoomElement = undefined;\n\n // Mode Callbacks: (element, options)\n this.activeCallback = this._createMagnificationCanvas.bind(this);\n this.enabledCallback = this._createMagnificationCanvas.bind(this);\n this.disabledCallback = this._destroyMagnificationCanvas.bind(this);\n\n // Touch\n this.postTouchStartCallback = this._addMagnifyingGlass.bind(this);\n this.touchDragCallback = this._updateMagnifyingGlass.bind(this);\n this.touchEndCallback = this._removeMagnifyingGlass.bind(this);\n this.touchDragEndCallback = this._removeMagnifyingGlass.bind(this);\n // Mouse\n this.postMouseDownCallback = this._addMagnifyingGlass.bind(this);\n this.mouseDragCallback = this._updateMagnifyingGlass.bind(this);\n this.mouseUpCallback = this._removeMagnifyingGlass.bind(this);\n // On quick clicks, mouseUp does not fire, but this does\n this.mouseClickCallback = this._removeMagnifyingGlass.bind(this);\n // Misc\n this.newImageCallback = this._drawMagnificationTool.bind(this);\n }\n\n _addMagnifyingGlass(evt) {\n // Ignore until next event\n this._removeZoomElement();\n this._drawZoomedElement(evt);\n // On next frame\n window.requestAnimationFrame(() => this._drawMagnificationTool(evt));\n\n hideToolCursor(evt.detail.element);\n\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n _updateMagnifyingGlass(evt) {\n this._drawMagnificationTool(evt);\n\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n _removeMagnifyingGlass(evt) {\n const element = evt.detail.element;\n\n // Re-enable the mouse cursor\n setToolCursor(this.element, this.svgCursor);\n\n element.querySelector('.magnifyTool').style.display = 'none';\n this._removeZoomElement();\n }\n\n _drawMagnificationTool(evt) {\n const element = evt.detail.element;\n const magnifyCanvas = element.querySelector('.magnifyTool');\n\n if (!magnifyCanvas) {\n this._createMagnificationCanvas(element);\n }\n\n if (this.zoomCanvas === undefined) {\n return;\n }\n\n // The 'not' magnifyTool class here is necessary because cornerstone places\n // No classes of it's own on the canvas we want to select\n const canvas = element.querySelector('canvas:not(.magnifyTool)');\n const context = getNewContext(magnifyCanvas);\n\n // Calculate the on-canvas location of the mouse pointer / touch\n const canvasLocation = external.cornerstone.pixelToCanvas(\n evt.detail.element,\n evt.detail.currentPoints.image\n );\n\n // Shrink magnifier to smallest canvas dimension if smaller than desired magnifier size\n const magnifySize = Math.min(\n this.configuration.magnifySize,\n canvas.width,\n canvas.height\n );\n const magnificationLevel = this.configuration.magnificationLevel;\n\n magnifyCanvas.width = magnifySize;\n magnifyCanvas.height = magnifySize;\n\n // Constrain drag movement to zoomed image boundaries\n canvasLocation.x = Math.max(\n canvasLocation.x,\n (0.5 * magnifySize) / magnificationLevel\n );\n canvasLocation.x = Math.min(\n canvasLocation.x,\n canvas.width - (0.5 * magnifySize) / magnificationLevel\n );\n canvasLocation.y = Math.max(\n canvasLocation.y,\n (0.5 * magnifySize) / magnificationLevel\n );\n canvasLocation.y = Math.min(\n canvasLocation.y,\n canvas.height - (0.5 * magnifySize) / magnificationLevel\n );\n\n const copyFrom = {\n x: canvasLocation.x * magnificationLevel - 0.5 * magnifySize,\n y: canvasLocation.y * magnificationLevel - 0.5 * magnifySize,\n };\n\n copyFrom.x = Math.max(copyFrom.x, 0);\n copyFrom.y = Math.max(copyFrom.y, 0);\n\n context.drawImage(\n this.zoomCanvas,\n copyFrom.x,\n copyFrom.y,\n magnifySize,\n magnifySize,\n 0,\n 0,\n magnifySize,\n magnifySize\n );\n\n // Place the magnification tool at the same location as the pointer\n const touchOffset = evt.detail.isTouchEvent ? 120 : 0;\n const magnifyPosition = {\n top: Math.max(canvasLocation.y - 0.5 * magnifySize - touchOffset, 0),\n left: Math.max(canvasLocation.x - 0.5 * magnifySize, 0),\n };\n\n // Get full magnifier dimensions with borders\n const magnifierBox = magnifyCanvas.getBoundingClientRect();\n\n // Constrain magnifier to canvas boundaries\n magnifyPosition.top = Math.min(\n magnifyPosition.top,\n canvas.height - magnifierBox.height\n );\n magnifyPosition.left = Math.min(\n magnifyPosition.left,\n canvas.width - magnifierBox.width\n );\n magnifyCanvas.style.top = `${magnifyPosition.top}px`;\n magnifyCanvas.style.left = `${magnifyPosition.left}px`;\n magnifyCanvas.style.display = 'block';\n }\n\n /**\n * Creates a cornerstone enabled element, and renders the target image at the\n * desired magnification level using it.\n *\n * @private\n * @param {*} evt\n * @returns {void}\n */\n _drawZoomedElement(evt) {\n const element = evt.detail.element;\n let enabledElement = evt.detail.enabledElement;\n\n if (enabledElement === undefined) {\n enabledElement = external.cornerstone.getEnabledElement(element);\n }\n\n const magnificationLevel = this.configuration.magnificationLevel;\n const origCanvas = enabledElement.canvas;\n const image = enabledElement.image;\n\n // Create a new cornerstone enabledElement\n if (!this.zoomElement) {\n this.zoomElement = document.createElement('div');\n this.zoomElement.width = origCanvas.width * magnificationLevel;\n this.zoomElement.height = origCanvas.height * magnificationLevel;\n external.cornerstone.enable(this.zoomElement, enabledElement.options);\n }\n\n const zoomEnabledElement = external.cornerstone.getEnabledElement(\n this.zoomElement\n );\n const viewport = external.cornerstone.getViewport(enabledElement.element);\n\n this.zoomCanvas = zoomEnabledElement.canvas;\n this.zoomCanvas.width = origCanvas.width * magnificationLevel;\n this.zoomCanvas.height = origCanvas.height * magnificationLevel;\n\n zoomEnabledElement.viewport = Object.assign({}, viewport);\n\n // Update it's viewport to render at desired magnification level\n viewport.scale *= magnificationLevel;\n external.cornerstone.displayImage(this.zoomElement, image);\n external.cornerstone.setViewport(this.zoomElement, viewport);\n // To do enable annotation tools for zoomElement\n }\n\n /**\n * Removes the canvas and associated enabled element that's\n * used to render the zoomed image.\n * @returns {void}\n */\n _removeZoomElement() {\n if (this.zoomElement !== undefined) {\n external.cornerstone.disable(this.zoomCanvas);\n this.zoomElement = undefined;\n this.zoomCanvas = undefined;\n }\n }\n\n /**\n * The canvas used to render the zoomed image.\n * It will be displayed and clipped inside the magnifying glass frame/element.\n *\n * @private\n *\n * @param {*} element\n * @returns {void}\n */\n _createMagnificationCanvas(element) {\n // If the magnifying glass canvas doesn't already exist\n if (element.querySelector('.magnifyTool') === null) {\n // Create a canvas and append it as a child to the element\n const magnifyCanvas = document.createElement('canvas');\n\n // The magnifyTool class is used to find the canvas later on\n // Make sure position is absolute so the canvas can follow the mouse / touch\n magnifyCanvas.classList.add('magnifyTool');\n magnifyCanvas.width = this.configuration.magnifySize;\n magnifyCanvas.height = this.configuration.magnifySize;\n magnifyCanvas.style.position = 'absolute';\n magnifyCanvas.style.display = 'none';\n element.appendChild(magnifyCanvas);\n }\n }\n\n /**\n *\n *\n * @param {*} element\n * @returns {void}\n */\n _destroyMagnificationCanvas(element) {\n const magnifyCanvas = element.querySelector('.magnifyTool');\n\n if (magnifyCanvas) {\n element.removeChild(magnifyCanvas);\n }\n }\n}\n","import getOrientationString from './getOrientationString.js';\nimport invertOrientationString from './invertOrientationString.js';\n\nconst orientation = {\n getOrientationString,\n invertOrientationString,\n};\n\nexport default orientation;\n","import external from '../externalModules.js';\nimport convertToVector3 from '../util/convertToVector3.js';\n\n/**\n * Returns the orientation of the vector in the patient coordinate system.\n * @public\n * @function getOrientationString\n *\n * @param {Array|cornerstoneMath.Vector3} vector Input array or Vector3\n * @returns {string} The orientation in the patient coordinate system.\n */\nexport default function(vector) {\n const vec3 = convertToVector3(vector);\n\n // Thanks to David Clunie\n // https://sites.google.com/site/dicomnotes/\n\n let orientation = '';\n const orientationX = vec3.x < 0 ? 'R' : 'L';\n const orientationY = vec3.y < 0 ? 'A' : 'P';\n const orientationZ = vec3.z < 0 ? 'F' : 'H';\n\n // Should probably make this a function vector3.abs\n const abs = new external.cornerstoneMath.Vector3(\n Math.abs(vec3.x),\n Math.abs(vec3.y),\n Math.abs(vec3.z)\n );\n\n for (let i = 0; i < 3; i++) {\n if (abs.x > 0.0001 && abs.x > abs.y && abs.x > abs.z) {\n orientation += orientationX;\n abs.x = 0;\n } else if (abs.y > 0.0001 && abs.y > abs.x && abs.y > abs.z) {\n orientation += orientationY;\n abs.y = 0;\n } else if (abs.z > 0.0001 && abs.z > abs.x && abs.z > abs.y) {\n orientation += orientationZ;\n abs.z = 0;\n } else {\n break;\n }\n }\n\n return orientation;\n}\n","/**\n * Inverts an orientation string.\n * @public\n * @function invertOrientationString\n *\n * @param {string} orientationString The orientation.\n * @returns {string} The inverted orientationString.\n */\nexport default function(orientationString) {\n let inverted = orientationString.replace('H', 'f');\n\n inverted = inverted.replace('F', 'h');\n inverted = inverted.replace('R', 'l');\n inverted = inverted.replace('L', 'r');\n inverted = inverted.replace('A', 'p');\n inverted = inverted.replace('P', 'a');\n inverted = inverted.toUpperCase();\n\n return inverted;\n}\n","import external from '../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\nimport orientation from '../orientation/index.js';\n\n// Drawing\nimport { getNewContext } from '../drawing/index.js';\nimport toolColors from '../stateManagement/toolColors.js';\nimport drawTextBox, { textBoxWidth } from '../drawing/drawTextBox.js';\n\n/**\n * @public\n * @class OrientationMarkersTool\n * @memberof Tools\n *\n * @classdesc Tool for displaying orientation markers on the image.\n * @extends Tools.Base.BaseTool\n */\nexport default class OrientationMarkersTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'OrientationMarkers',\n configuration: {\n drawAllMarkers: true,\n },\n mixins: ['enabledOrDisabledBinaryTool'],\n };\n\n super(props, defaultProps);\n }\n\n enabledCallback(element) {\n this.forceImageUpdate(element);\n }\n\n disabledCallback(element) {\n this.forceImageUpdate(element);\n }\n\n forceImageUpdate(element) {\n const cornerstone = external.cornerstone;\n const enabledElement = cornerstone.getEnabledElement(element);\n\n if (enabledElement.image) {\n cornerstone.updateImage(element);\n }\n }\n\n renderToolData(evt) {\n const eventData = evt.detail;\n const context = getNewContext(eventData.canvasContext.canvas);\n const element = eventData.element;\n const markers = getOrientationMarkers(element);\n\n if (!markers) {\n return;\n }\n const coords = getOrientationMarkerPositions(element, markers);\n const color = toolColors.getToolColor();\n\n const textWidths = {\n top: textBoxWidth(context, markers.top, 0),\n left: textBoxWidth(context, markers.left, 0),\n right: textBoxWidth(context, markers.right, 0),\n bottom: textBoxWidth(context, markers.bottom, 0),\n height: textBoxWidth(context, 'M', 0), // Trick to get an approximation of the height of the text\n };\n\n drawTopLeftText(context, markers, coords, textWidths, color);\n if (this.configuration.drawAllMarkers) {\n drawBottomRightText(context, markers, coords, textWidths, color);\n }\n }\n}\n\nconst drawTopLeftText = (context, markers, coords, textWidths, color) => {\n drawTextBox(\n context,\n markers.top,\n coords.top.x - textWidths.top / 2,\n coords.top.y,\n color\n );\n drawTextBox(\n context,\n markers.left,\n coords.left.x - textWidths.left / 2,\n coords.left.y,\n color\n );\n};\n\nconst drawBottomRightText = (context, markers, coords, textWidths, color) => {\n drawTextBox(\n context,\n markers.right,\n coords.right.x - textWidths.right,\n coords.right.y,\n color\n );\n drawTextBox(\n context,\n markers.bottom,\n coords.bottom.x - textWidths.bottom / 2,\n coords.bottom.y - textWidths.height,\n color\n );\n};\n\nconst getOrientationMarkers = element => {\n const cornerstone = external.cornerstone;\n const enabledElement = cornerstone.getEnabledElement(element);\n const imagePlane = cornerstone.metaData.get(\n 'imagePlaneModule',\n enabledElement.image.imageId\n );\n\n if (!imagePlane || !imagePlane.rowCosines || !imagePlane.columnCosines) {\n return;\n }\n\n const row = orientation.getOrientationString(imagePlane.rowCosines);\n const column = orientation.getOrientationString(imagePlane.columnCosines);\n const oppositeRow = orientation.invertOrientationString(row);\n const oppositeColumn = orientation.invertOrientationString(column);\n\n return {\n top: oppositeColumn,\n bottom: column,\n left: oppositeRow,\n right: row,\n };\n};\n\nconst getOrientationMarkerPositions = element => {\n const enabledElement = external.cornerstone.getEnabledElement(element);\n const top = external.cornerstone.pixelToCanvas(element, {\n x: enabledElement.image.width / 2,\n y: 5,\n });\n const bottom = external.cornerstone.pixelToCanvas(element, {\n x: enabledElement.image.width / 2,\n y: enabledElement.image.height - 15,\n });\n const left = external.cornerstone.pixelToCanvas(element, {\n x: 5,\n y: enabledElement.image.height / 2,\n });\n const right = external.cornerstone.pixelToCanvas(element, {\n x: enabledElement.image.width - 10,\n y: enabledElement.image.height / 2,\n });\n\n return {\n top,\n bottom,\n left,\n right,\n };\n};\n","import external from '../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\n\n/**\n * @public\n * @class PanMultiTouchTool\n * @memberof Tools\n *\n * @classdesc Tool for panning the image using multi-touch.\n * @extends Tools.Base.BaseTool\n */\nexport default class PanMultiTouchTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'PanMultiTouch',\n supportedInteractionTypes: ['MultiTouch'],\n configuration: {\n touchPointers: 2,\n },\n };\n\n super(props, defaultProps);\n\n // Touch\n this.multiTouchDragCallback = this._dragCallback.bind(this);\n }\n\n _dragCallback(evt) {\n const eventData = evt.detail;\n const { element, viewport } = eventData;\n\n if (eventData.numPointers === this.configuration.touchPointers) {\n const translation = this._getTranslation(eventData);\n\n this._applyTranslation(viewport, translation);\n external.cornerstone.setViewport(element, viewport);\n }\n }\n\n _getTranslation(eventData) {\n const { viewport, image, deltaPoints } = eventData;\n\n let widthScale = viewport.scale;\n let heightScale = viewport.scale;\n\n if (image.rowPixelSpacing < image.columnPixelSpacing) {\n widthScale *= image.columnPixelSpacing / image.rowPixelSpacing;\n } else if (image.columnPixelSpacing < image.rowPixelSpacing) {\n heightScale *= image.rowPixelSpacing / image.columnPixelSpacing;\n }\n\n return {\n x: deltaPoints.page.x / widthScale,\n y: deltaPoints.page.y / heightScale,\n };\n }\n\n _applyTranslation(viewport, translation) {\n viewport.translation.x += translation.x;\n viewport.translation.y += translation.y;\n }\n}\n","import external from './../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\nimport { panCursor } from './cursors/index.js';\n\n/**\n * @public\n * @class PanTool\n * @memberof Tools\n *\n * @classdesc Tool for panning the image.\n * @extends Tools.Base.BaseTool\n */\nexport default class PanTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Pan',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: panCursor,\n };\n\n super(props, defaultProps);\n\n // Touch\n this.touchDragCallback = this._dragCallback.bind(this);\n // Mouse\n this.mouseDragCallback = this._dragCallback.bind(this);\n }\n\n _dragCallback(evt) {\n const eventData = evt.detail;\n const { element, viewport } = eventData;\n\n const translation = this._getTranslation(eventData);\n\n this._applyTranslation(viewport, translation);\n external.cornerstone.setViewport(element, viewport);\n }\n\n _getTranslation(eventData) {\n const { viewport, image, deltaPoints } = eventData;\n\n let widthScale = viewport.scale;\n let heightScale = viewport.scale;\n\n if (image.rowPixelSpacing < image.columnPixelSpacing) {\n widthScale *= image.columnPixelSpacing / image.rowPixelSpacing;\n } else if (image.columnPixelSpacing < image.rowPixelSpacing) {\n heightScale *= image.rowPixelSpacing / image.columnPixelSpacing;\n }\n\n return {\n x: deltaPoints.page.x / widthScale,\n y: deltaPoints.page.y / heightScale,\n };\n }\n\n _applyTranslation(viewport, translation) {\n viewport.translation.x += translation.x;\n viewport.translation.y += translation.y;\n }\n}\n","import external from './../../externalModules.js';\nimport calculateReferenceLine from './calculateReferenceLine.js';\nimport toolColors from './../../stateManagement/toolColors.js';\nimport convertToVector3 from './../../util/convertToVector3.js';\nimport { draw, drawLine } from './../../drawing/index.js';\n\n/**\n * Renders the active reference line.\n *\n * @export @public @method\n * @name renderActiveReferenceLine\n * @param {Object} context The canvas context.\n * @param {Object} eventData The data associated with the event.\n * @param {HTMLElement} targetElement The element on which to render the reference line.\n * @param {HTMLElement} referenceElement The element referenced by the line.\n * @returns {void}\n */\nexport default function(context, eventData, targetElement, referenceElement) {\n const cornerstone = external.cornerstone;\n const targetImage = cornerstone.getEnabledElement(targetElement).image;\n const referenceImage = cornerstone.getEnabledElement(referenceElement).image;\n\n // Make sure the images are actually loaded for the target and reference\n if (!targetImage || !referenceImage) {\n return;\n }\n\n const targetImagePlane = cornerstone.metaData.get(\n 'imagePlaneModule',\n targetImage.imageId\n );\n const referenceImagePlane = cornerstone.metaData.get(\n 'imagePlaneModule',\n referenceImage.imageId\n );\n\n // Make sure the target and reference actually have image plane metadata\n if (\n !targetImagePlane ||\n !referenceImagePlane ||\n !targetImagePlane.rowCosines ||\n !targetImagePlane.columnCosines ||\n !targetImagePlane.imagePositionPatient ||\n !referenceImagePlane.rowCosines ||\n !referenceImagePlane.columnCosines ||\n !referenceImagePlane.imagePositionPatient\n ) {\n return;\n }\n\n // The image planes must be in the same frame of reference\n if (\n targetImagePlane.frameOfReferenceUID !==\n referenceImagePlane.frameOfReferenceUID\n ) {\n return;\n }\n\n targetImagePlane.rowCosines = convertToVector3(targetImagePlane.rowCosines);\n targetImagePlane.columnCosines = convertToVector3(\n targetImagePlane.columnCosines\n );\n targetImagePlane.imagePositionPatient = convertToVector3(\n targetImagePlane.imagePositionPatient\n );\n referenceImagePlane.rowCosines = convertToVector3(\n referenceImagePlane.rowCosines\n );\n referenceImagePlane.columnCosines = convertToVector3(\n referenceImagePlane.columnCosines\n );\n referenceImagePlane.imagePositionPatient = convertToVector3(\n referenceImagePlane.imagePositionPatient\n );\n\n // The image plane normals must be > 30 degrees apart\n const targetNormal = targetImagePlane.rowCosines\n .clone()\n .cross(targetImagePlane.columnCosines);\n const referenceNormal = referenceImagePlane.rowCosines\n .clone()\n .cross(referenceImagePlane.columnCosines);\n let angleInRadians = targetNormal.angleTo(referenceNormal);\n\n angleInRadians = Math.abs(angleInRadians);\n if (angleInRadians < 0.5) {\n // 0.5 radians = ~30 degrees\n return;\n }\n\n const referenceLine = calculateReferenceLine(\n targetImagePlane,\n referenceImagePlane\n );\n\n if (!referenceLine) {\n return;\n }\n\n const color = toolColors.getActiveColor();\n\n // Draw the referenceLines\n context.setTransform(1, 0, 0, 1, 0, 0);\n\n draw(context, context => {\n drawLine(\n context,\n eventData.element,\n referenceLine.start,\n referenceLine.end,\n { color }\n );\n });\n}\n","import {\n planePlaneIntersection,\n projectPatientPointToImagePlane,\n} from './../../util/pointProjector.js';\n\n/**\n * Calculates a reference line between two planes by projecting the top left hand corner and bottom right hand corner\n * Of the reference image onto the target image. Ideally we would calculate the intersection between the planes but\n * That requires a bit more math and this works fine for most cases.\n *\n * @export\n * @public\n * @method\n * @name calculateReferenceLine\n * @param {Object} targetImagePlane The imagePlane on which the reference line will be drawn.\n * @param {Object} referenceImagePlane The imagePlane being referenced.\n * @returns {Object} The start and end points of the line to be drawn.\n */\nexport default function(targetImagePlane, referenceImagePlane) {\n const points = planePlaneIntersection(targetImagePlane, referenceImagePlane);\n\n if (!points) {\n return;\n }\n\n return {\n start: projectPatientPointToImagePlane(points.start, targetImagePlane),\n end: projectPatientPointToImagePlane(points.end, targetImagePlane),\n };\n}\n","import external from './../externalModules.js';\n\n/**\n * Waits a set amount of time, then resolves. Can be chained off of to delay\n * next call in promise chain.\n * @public\n * @function wait\n * @param {number} ms - number in ms to wait\n * @returns {Promise} - A promise that resolves when setTimeout elapses\n */\nexport const wait = ms => new Promise(resolve => setTimeout(resolve, ms));\n\n/**\n * A promise that returns an EnabledElement who's image has loaded, or\n * null if the provided element ceases being an enabledElement before an\n * image has been loaded.\n * @public\n * @function waitForEnabledElementImageToLoad\n *\n * @param {HTMLElement} element - An element that is an EnabledElement\n * @returns {EnabledElement} - The enabled element that has loaded an image\n */\nexport function waitForEnabledElementImageToLoad(element) {\n try {\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n if (!enabledElement.image) {\n return wait(250).then(() => waitForEnabledElementImageToLoad(element));\n }\n\n // EnabledElement's image is loaded.\n return enabledElement;\n } catch (ex) {\n // Is no longer, or never was an enabled element, stop polling\n return null;\n }\n}\n\nexport default wait;\n","import external from './../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\n\nimport { getNewContext } from '../drawing/index.js';\nimport renderActiveReferenceLine from './referenceLines/renderActiveReferenceLine.js';\nimport { waitForEnabledElementImageToLoad } from '../util/wait.js';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('tools:ReferenceLinesTool');\n\n/**\n * When enabled, this tool will display references lines for each source\n * enabledElement in the provided synchronizer. This tool can also be configured\n * to use a custom renderer for alternative reference line rendering behavior\n *\n * TODO: Need to watch for configuration changes to update ToolState\n * TODO:\n *\n * @export @public @class\n * @name ReferenceLinesTool\n * @classdesc Tool for displaying reference lines of other enabledElements\n * @extends Tools.Base.BaseTool\n */\nexport default class ReferenceLinesTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'ReferenceLines',\n mixins: ['enabledOrDisabledBinaryTool'],\n configuration: {\n renderer: renderActiveReferenceLine,\n },\n };\n\n super(props, defaultProps);\n\n this.renderer = null;\n this.synchronizationContext = null;\n }\n\n async enabledCallback(element, { synchronizationContext } = {}) {\n const renderer = this.configuration.renderer;\n const enabledElement = await waitForEnabledElementImageToLoad(element);\n\n if (!enabledElement || !renderer || !synchronizationContext) {\n // TODO: Unable to add tool state, image never loaded.\n // Should we `setToolDisabledForElement` here?\n logger.warn(\n `Unable to enable ${this.name}. Exiting enable callback. Tool will be enabled, but will not render.`\n );\n\n return;\n }\n this.renderer = renderer;\n this.synchronizationContext = synchronizationContext;\n\n this.forceImageUpdate(element);\n }\n\n disabledCallback(element) {\n this.forceImageUpdate(element);\n }\n\n forceImageUpdate(element) {\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n if (enabledElement.image) {\n external.cornerstone.updateImage(element);\n }\n }\n\n renderToolData(evt) {\n const eventData = evt.detail;\n\n // No renderer or synch context? Adios\n if (!this.renderer || !this.synchronizationContext) {\n return;\n }\n\n // Get the enabled elements associated with this synchronization context and draw them\n const enabledElements = this.synchronizationContext.getSourceElements();\n const context = getNewContext(eventData.canvasContext.canvas);\n\n external.cornerstone.setToPixelCoordinateSystem(\n eventData.enabledElement,\n context\n );\n enabledElements.forEach(referenceEnabledElement => {\n // Don't draw ourselves\n if (referenceEnabledElement === evt.currentTarget) {\n return;\n }\n\n // Render it\n this.renderer(\n context,\n eventData,\n evt.currentTarget,\n referenceEnabledElement\n );\n });\n }\n}\n","/**\n * Calculates the (interior) angle in degrees from the initial mouse location\n * to the current mouse location in relation to the center point.\n * @public\n * @function angleBetweenPoints\n *\n * @param {Object} p0 The center point.\n * @param {Object} p1 The initial point.\n * @param {Object} p2 The final point.\n * @returns {Object} { angle, direction }\n */\nexport default (p0, p1, p2) => {\n const p12 = Math.sqrt(Math.pow(p0.x - p1.x, 2) + Math.pow(p0.y - p1.y, 2));\n const p13 = Math.sqrt(Math.pow(p0.x - p2.x, 2) + Math.pow(p0.y - p2.y, 2));\n const p23 = Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\n\n const angle =\n (Math.acos(\n (Math.pow(p12, 2) + Math.pow(p13, 2) - Math.pow(p23, 2)) / (2 * p12 * p13)\n ) *\n 180) /\n Math.PI;\n\n // The direction of the angle (> 0 clockwise, < 0 anti-clockwise)\n const direction =\n (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);\n\n return {\n angle,\n direction,\n };\n};\n","import external from './../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\nimport angleBetweenPoints from '../util/angleBetweenPoints.js';\nimport { rotateCursor } from './cursors/index.js';\n\n/**\n * @public\n * @class RotateTool\n * @memberof Tools\n *\n * @classdesc Tool for rotating the image.\n * @extends Tools.Base.BaseTool\n */\nexport default class RotateTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Rotate',\n strategies: {\n default: defaultStrategy,\n horizontal: horizontalStrategy,\n vertical: verticalStrategy,\n },\n defaultStrategy: 'default',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n svgCursor: rotateCursor,\n };\n\n super(props, defaultProps);\n }\n\n touchDragCallback(evt) {\n this.dragCallback(evt);\n }\n\n mouseDragCallback(evt) {\n this.dragCallback(evt);\n }\n\n postMouseDownCallback(evt) {\n this.initialRotation = evt.detail.viewport.rotation;\n }\n\n dragCallback(evt) {\n evt.detail.viewport.initialRotation = this.initialRotation;\n this.applyActiveStrategy(evt);\n external.cornerstone.setViewport(evt.detail.element, evt.detail.viewport);\n }\n}\n\nfunction defaultStrategy(evt) {\n const eventData = evt.detail;\n const { element, viewport } = eventData;\n const initialRotation = viewport.initialRotation;\n\n // Calculate the center of the image\n const rect = element.getBoundingClientRect(element);\n const { clientWidth: width, clientHeight: height } = element;\n\n const initialPoints = {\n x: eventData.startPoints.client.x,\n y: eventData.startPoints.client.y,\n };\n const { scale, translation } = viewport;\n const centerPoints = {\n x: rect.left + width / 2 + translation.x * scale,\n y: rect.top + height / 2 + translation.y * scale,\n };\n\n const currentPoints = {\n x: eventData.currentPoints.client.x,\n y: eventData.currentPoints.client.y,\n };\n\n const angleInfo = angleBetweenPoints(\n centerPoints,\n initialPoints,\n currentPoints\n );\n\n if (angleInfo.direction < 0) {\n angleInfo.angle = -angleInfo.angle;\n }\n\n viewport.rotation = initialRotation + angleInfo.angle;\n}\n\nconst horizontalStrategy = evt => {\n const eventData = evt.detail;\n const { viewport, deltaPoints } = eventData;\n\n viewport.rotation += deltaPoints.page.x / viewport.scale;\n};\n\nconst verticalStrategy = evt => {\n const eventData = evt.detail;\n const { viewport, deltaPoints } = eventData;\n\n viewport.rotation += deltaPoints.page.y / viewport.scale;\n};\n","let configMaxSimultaneousRequests;\n\n// Maximum concurrent connections to the same server\n// Information from http://sgdev-blog.blogspot.fr/2014/01/maximum-concurrent-connection-to-same.html\nconst maxSimultaneousRequests = {\n default: 6,\n IE: {\n 9: 6,\n 10: 8,\n default: 8,\n },\n Firefox: {\n default: 6,\n },\n Opera: {\n 10: 8,\n 11: 6,\n 12: 6,\n default: 6,\n },\n Chrome: {\n default: 6,\n },\n Safari: {\n default: 6,\n },\n};\n\n// Browser name / version detection\n//\n//\n\n/**\n * Browser name / version detection\n * http://stackoverflow.com/questions/2400935/browser-detection-in-javascript\n * @export @public @method\n * @name getBrowserInfo\n *\n * @returns {string} The name and version of the browser.\n */\nfunction getBrowserInfo() {\n const ua = navigator.userAgent;\n let M =\n ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i) ||\n [];\n let tem;\n\n if (/trident/i.test(M[1])) {\n tem = /\\brv[ :]+(\\d+)/g.exec(ua) || [];\n\n return `IE ${tem[1] || ''}`;\n }\n\n if (M[1] === 'Chrome') {\n tem = ua.match(/\\b(OPR|Edge)\\/(\\d+)/);\n if (tem !== null) {\n return tem\n .slice(1)\n .join(' ')\n .replace('OPR', 'Opera');\n }\n }\n\n M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];\n if ((tem = ua.match(/version\\/(\\d+)/i)) !== null) {\n M.splice(1, 1, tem[1]);\n }\n\n return M.join(' ');\n}\n\n/**\n * Sets the maximum number of simultaneous requests.\n * @export @public @method\n * @name setMaxSimultaneousRequests\n *\n * @param {number} newMaxSimultaneousRequests The value.\n * @returns {void}\n */\nfunction setMaxSimultaneousRequests(newMaxSimultaneousRequests) {\n configMaxSimultaneousRequests = newMaxSimultaneousRequests;\n}\n\n/**\n * Returns the maximum number of simultaneous requests.\n * @export @public @method\n * @name getMaxSimultaneousRequests\n *\n * @returns {number} The maximum number of simultaneous requests\n */\nfunction getMaxSimultaneousRequests() {\n if (configMaxSimultaneousRequests) {\n return configMaxSimultaneousRequests;\n }\n\n return getDefaultSimultaneousRequests();\n}\n\n/**\n * Returns the default number of simultaneous requests.\n * @export @public @method\n * @name getDefaultSimultaneousRequests\n *\n * @returns {number} The default number of simultaneous requests.\n */\nfunction getDefaultSimultaneousRequests() {\n const infoString = getBrowserInfo();\n const info = infoString.split(' ');\n const browserName = info[0];\n const browserVersion = info[1];\n const browserData = maxSimultaneousRequests[browserName];\n\n if (!browserData) {\n return maxSimultaneousRequests.default;\n }\n\n if (!browserData[browserVersion]) {\n return browserData.default;\n }\n\n return browserData[browserVersion];\n}\n\n/**\n * Checks if cornerstoneTools is operating on a mobile device.\n * @export @public @method\n * @name isMobileDevice\n *\n * @returns {boolean} True if running on a mobile device.\n */\nfunction isMobileDevice() {\n const pattern = new RegExp(\n 'Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini'\n );\n\n return pattern.test(navigator.userAgent);\n}\n\nexport {\n getDefaultSimultaneousRequests,\n getMaxSimultaneousRequests,\n setMaxSimultaneousRequests,\n getBrowserInfo,\n isMobileDevice,\n};\n","import external from './../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\n\n/**\n * @public\n * @class RotateTouchTool\n * @memberof Tools\n *\n * @classdesc Tool for rotating the image using touch.\n * @extends Tools.Base.BaseTool\n */\nexport default class RotateTouchTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'RotateTouch',\n supportedInteractionTypes: ['TouchRotate'],\n };\n\n super(props, defaultProps);\n }\n\n touchRotateCallback(evt) {\n const eventData = evt.detail;\n const { element, viewport, rotation } = eventData;\n\n viewport.rotation += rotation;\n external.cornerstone.setViewport(element, viewport);\n }\n}\n","import external from '../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\n// Drawing\nimport { getNewContext, draw, setShadow, drawLine } from '../drawing/index.js';\nimport toolStyle from '../stateManagement/toolStyle.js';\nimport toolColors from '../stateManagement/toolColors.js';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('tools:ScaleOverlayTool');\n\n/**\n * @public\n * @class ScaleOverlayTool\n * @memberof Tools\n *\n * @classdesc Tool for displaying a scale overlay on the image.\n * @extends Tools.Base.BaseTool\n */\nexport default class ScaleOverlayTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'ScaleOverlay',\n configuration: {\n minorTickLength: 12.5,\n majorTickLength: 25,\n },\n mixins: ['enabledOrDisabledBinaryTool'],\n };\n\n super(props, defaultProps);\n }\n\n enabledCallback(element) {\n this.forceImageUpdate(element);\n }\n\n disabledCallback(element) {\n this.forceImageUpdate(element);\n }\n\n forceImageUpdate(element) {\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n if (enabledElement.image) {\n external.cornerstone.updateImage(element);\n }\n }\n\n renderToolData(evt) {\n const eventData = evt.detail;\n\n const context = getNewContext(eventData.canvasContext.canvas);\n const { image, viewport, element } = eventData;\n\n let rowPixelSpacing = image.rowPixelSpacing;\n let colPixelSpacing = image.columnPixelSpacing;\n const imagePlane = external.cornerstone.metaData.get(\n 'imagePlaneModule',\n image.imageId\n );\n\n if (imagePlane) {\n rowPixelSpacing =\n imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing;\n colPixelSpacing =\n imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing;\n }\n\n // Check whether pixel spacing is defined\n if (!rowPixelSpacing || !colPixelSpacing) {\n logger.warn(\n `unable to define rowPixelSpacing or colPixelSpacing from data on ${this.name}'s renderToolData`\n );\n\n return;\n }\n\n const canvasSize = {\n width: context.canvas.width,\n height: context.canvas.height,\n };\n\n // Distance between intervals is 10mm\n const verticalIntervalScale = (10.0 / rowPixelSpacing) * viewport.scale;\n const horizontalIntervalScale = (10.0 / colPixelSpacing) * viewport.scale;\n\n // 0.1 and 0.05 gives margin to horizontal and vertical lines\n const hscaleBounds = computeScaleBounds(canvasSize, 0.25, 0.05);\n const vscaleBounds = computeScaleBounds(canvasSize, 0.05, 0.15);\n\n if (\n !canvasSize.width ||\n !canvasSize.height ||\n !hscaleBounds ||\n !vscaleBounds\n ) {\n return;\n }\n\n const color = toolColors.getToolColor();\n const lineWidth = toolStyle.getToolWidth();\n\n const imageAttributes = Object.assign(\n {},\n {\n hscaleBounds,\n vscaleBounds,\n verticalMinorTick: verticalIntervalScale,\n horizontalMinorTick: horizontalIntervalScale,\n verticalLine: {\n start: {\n x: vscaleBounds.bottomRight.x,\n y: vscaleBounds.topLeft.y,\n },\n end: {\n x: vscaleBounds.bottomRight.x,\n y: vscaleBounds.bottomRight.y,\n },\n },\n horizontalLine: {\n start: {\n x: hscaleBounds.topLeft.x,\n y: hscaleBounds.bottomRight.y,\n },\n end: {\n x: hscaleBounds.bottomRight.x,\n y: hscaleBounds.bottomRight.y,\n },\n },\n color,\n lineWidth,\n },\n this.configuration\n );\n\n draw(context, context => {\n setShadow(context, imageAttributes);\n\n // Draw vertical line\n drawLine(\n context,\n element,\n imageAttributes.verticalLine.start,\n imageAttributes.verticalLine.end,\n {\n color: imageAttributes.color,\n lineWidth: imageAttributes.lineWidth,\n },\n 'canvas'\n );\n drawVerticalScalebarIntervals(context, element, imageAttributes);\n\n // Draw horizontal line\n drawLine(\n context,\n element,\n imageAttributes.horizontalLine.start,\n imageAttributes.horizontalLine.end,\n {\n color: imageAttributes.color,\n lineWidth: imageAttributes.lineWidth,\n },\n 'canvas'\n );\n drawHorizontalScalebarIntervals(context, element, imageAttributes);\n });\n }\n}\n\n/**\n * Computes the max bound for scales on the image\n * @param {{width: number, height: number}} canvasSize\n * @param {number} horizontalReduction\n * @param {number} verticalReduction\n * @returns {Object.<string, { x:number, y:number }>}\n */\nconst computeScaleBounds = (\n canvasSize,\n horizontalReduction,\n verticalReduction\n) => {\n const hReduction = horizontalReduction * Math.min(1000, canvasSize.width);\n const vReduction = verticalReduction * Math.min(1000, canvasSize.height);\n const canvasBounds = {\n left: hReduction,\n top: vReduction,\n width: canvasSize.width - 2 * hReduction,\n height: canvasSize.height - 2 * vReduction,\n };\n\n return {\n topLeft: {\n x: canvasBounds.left,\n y: canvasBounds.top,\n },\n bottomRight: {\n x: canvasBounds.left + canvasBounds.width,\n y: canvasBounds.top + canvasBounds.height,\n },\n };\n};\n\n/**\n * @param {CanvasRenderingContext2D} context\n * @param {HTMLElement} element\n * @param {Object} imageAttributes\n * @returns {void}\n */\nconst drawVerticalScalebarIntervals = (context, element, imageAttributes) => {\n let i = 0;\n\n while (\n imageAttributes.verticalLine.start.y +\n i * imageAttributes.verticalMinorTick <=\n imageAttributes.vscaleBounds.bottomRight.y\n ) {\n const { color, lineWidth } = imageAttributes;\n const startPoint = {\n x: imageAttributes.verticalLine.start.x,\n y:\n imageAttributes.verticalLine.start.y +\n i * imageAttributes.verticalMinorTick,\n };\n\n const endPoint = {\n x: 0,\n y:\n imageAttributes.verticalLine.start.y +\n i * imageAttributes.verticalMinorTick,\n };\n\n if (i % 5 === 0) {\n endPoint.x =\n imageAttributes.verticalLine.start.x - imageAttributes.majorTickLength;\n } else {\n endPoint.x =\n imageAttributes.verticalLine.start.x - imageAttributes.minorTickLength;\n }\n\n drawLine(\n context,\n element,\n startPoint,\n endPoint,\n {\n color,\n lineWidth,\n },\n 'canvas'\n );\n\n i++;\n }\n};\n\n/**\n * @param {CanvasRenderingContext2D} context\n * @param {HTMLElement} element\n * @param {Object} imageAttributes\n * @returns {void}\n */\nconst drawHorizontalScalebarIntervals = (context, element, imageAttributes) => {\n let i = 0;\n\n while (\n imageAttributes.horizontalLine.start.x +\n i * imageAttributes.horizontalMinorTick <=\n imageAttributes.hscaleBounds.bottomRight.x\n ) {\n const { color, lineWidth } = imageAttributes;\n const startPoint = {\n x:\n imageAttributes.horizontalLine.start.x +\n i * imageAttributes.horizontalMinorTick,\n y: imageAttributes.horizontalLine.start.y,\n };\n\n const endPoint = {\n x:\n imageAttributes.horizontalLine.start.x +\n i * imageAttributes.horizontalMinorTick,\n y: 0,\n };\n\n if (i % 5 === 0) {\n endPoint.y =\n imageAttributes.horizontalLine.start.y -\n imageAttributes.majorTickLength;\n } else {\n endPoint.y =\n imageAttributes.horizontalLine.start.y -\n imageAttributes.minorTickLength;\n }\n\n drawLine(\n context,\n element,\n startPoint,\n endPoint,\n {\n color,\n lineWidth,\n },\n 'canvas'\n );\n\n i++;\n }\n};\n","import external from '../externalModules.js';\nimport { getMaxSimultaneousRequests } from '../util/getMaxSimultaneousRequests.js';\n\nconst requestPool = {\n interaction: [],\n thumbnail: [],\n prefetch: [],\n};\n\nconst numRequests = {\n interaction: 0,\n thumbnail: 0,\n prefetch: 0,\n};\n\nlet maxNumRequests = {\n interaction: 6,\n thumbnail: 6,\n prefetch: 5,\n};\n\nlet awake = false;\nconst grabDelay = 20;\n\nfunction addRequest(\n element,\n imageId,\n type,\n preventCache,\n doneCallback,\n failCallback,\n addToBeginning\n) {\n if (!requestPool.hasOwnProperty(type)) {\n throw new Error(\n 'Request type must be one of interaction, thumbnail, or prefetch'\n );\n }\n\n if (!element || !imageId) {\n return;\n }\n\n // Describe the request\n const requestDetails = {\n type,\n imageId,\n preventCache,\n doneCallback,\n failCallback,\n };\n\n // If this imageId is in the cache, resolve it immediately\n const imageLoadObject = external.cornerstone.imageCache.getImageLoadObject(\n imageId\n );\n\n if (imageLoadObject) {\n imageLoadObject.promise.then(\n function(image) {\n doneCallback(image);\n },\n function(error) {\n failCallback(error);\n }\n );\n\n return;\n }\n\n if (addToBeginning) {\n // Add it to the beginning of the stack\n requestPool[type].unshift(requestDetails);\n } else {\n // Add it to the end of the stack\n requestPool[type].push(requestDetails);\n }\n\n // Wake up\n awake = true;\n}\n\nfunction clearRequestStack(type) {\n // Console.log('clearRequestStack');\n if (!requestPool.hasOwnProperty(type)) {\n throw new Error(\n 'Request type must be one of interaction, thumbnail, or prefetch'\n );\n }\n\n requestPool[type] = [];\n}\n\nfunction startAgain() {\n if (!awake) {\n return;\n }\n\n setTimeout(function() {\n startGrabbing();\n }, grabDelay);\n}\n\nfunction sendRequest(requestDetails) {\n const cornerstone = external.cornerstone;\n // Increment the number of current requests of this type\n const type = requestDetails.type;\n\n numRequests[type]++;\n\n awake = true;\n const imageId = requestDetails.imageId;\n const doneCallback = requestDetails.doneCallback;\n const failCallback = requestDetails.failCallback;\n\n // Check if we already have this image promise in the cache\n const imageLoadObject = cornerstone.imageCache.getImageLoadObject(imageId);\n\n if (imageLoadObject) {\n // If we do, remove from list (when resolved, as we could have\n // Pending prefetch requests) and stop processing this iteration\n imageLoadObject.promise.then(\n function(image) {\n numRequests[type]--;\n // Console.log(numRequests);\n\n doneCallback(image);\n startAgain();\n },\n function(error) {\n numRequests[type]--;\n // Console.log(numRequests);\n failCallback(error);\n startAgain();\n }\n );\n\n return;\n }\n\n function requestTypeToLoadPriority(requestDetails) {\n if (requestDetails.type === 'prefetch') {\n return -5;\n } else if (requestDetails.type === 'interactive') {\n return 0;\n } else if (requestDetails.type === 'thumbnail') {\n return 5;\n }\n }\n\n const priority = requestTypeToLoadPriority(requestDetails);\n\n let loader;\n\n if (requestDetails.preventCache === true) {\n loader = cornerstone.loadImage(imageId, {\n priority,\n type: requestDetails.type,\n });\n } else {\n loader = cornerstone.loadAndCacheImage(imageId, {\n priority,\n type: requestDetails.type,\n });\n }\n\n // Load and cache the image\n loader.then(\n function(image) {\n numRequests[type]--;\n // Console.log(numRequests);\n doneCallback(image);\n startAgain();\n },\n function(error) {\n numRequests[type]--;\n // Console.log(numRequests);\n failCallback(error);\n startAgain();\n }\n );\n}\n\nfunction startGrabbing() {\n // Begin by grabbing X images\n const maxSimultaneousRequests = getMaxSimultaneousRequests();\n\n maxNumRequests = {\n interaction: Math.max(maxSimultaneousRequests, 1),\n thumbnail: Math.max(maxSimultaneousRequests - 2, 1),\n prefetch: Math.max(maxSimultaneousRequests - 1, 1),\n };\n\n const currentRequests =\n numRequests.interaction + numRequests.thumbnail + numRequests.prefetch;\n const requestsToSend = maxSimultaneousRequests - currentRequests;\n\n for (let i = 0; i < requestsToSend; i++) {\n const requestDetails = getNextRequest();\n\n if (requestDetails) {\n sendRequest(requestDetails);\n }\n }\n}\n\nfunction getNextRequest() {\n if (\n requestPool.interaction.length &&\n numRequests.interaction < maxNumRequests.interaction\n ) {\n return requestPool.interaction.shift();\n }\n\n if (\n requestPool.thumbnail.length &&\n numRequests.thumbnail < maxNumRequests.thumbnail\n ) {\n return requestPool.thumbnail.shift();\n }\n\n if (\n requestPool.prefetch.length &&\n numRequests.prefetch < maxNumRequests.prefetch\n ) {\n return requestPool.prefetch.shift();\n }\n\n if (\n !requestPool.interaction.length &&\n !requestPool.thumbnail.length &&\n !requestPool.prefetch.length\n ) {\n awake = false;\n }\n\n return false;\n}\n\nfunction getRequestPool() {\n return requestPool;\n}\n\nexport default {\n addRequest,\n clearRequestStack,\n startGrabbing,\n getRequestPool,\n};\n","import EVENTS from '../events.js';\nimport external from '../externalModules.js';\nimport { getToolState } from '../stateManagement/toolState.js';\nimport requestPoolManager from '../requestPool/requestPoolManager.js';\nimport loadHandlerManager from '../stateManagement/loadHandlerManager.js';\nimport triggerEvent from '../util/triggerEvent.js';\n\n/**\n * Scrolls through the stack to the image index requested.\n * @export @public @method\n * @name scrollToIndex\n *\n * @param {type} element The element to scroll through.\n * @param {type} newImageIdIndex The target image index.\n * @returns {void}\n */\nexport default function(element, newImageIdIndex) {\n const toolData = getToolState(element, 'stack');\n\n if (!toolData || !toolData.data || !toolData.data.length) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n // If we have more than one stack, check if we have a stack renderer defined\n let stackRenderer;\n\n if (toolData.data.length > 1) {\n const stackRendererData = getToolState(element, 'stackRenderer');\n\n if (\n stackRendererData &&\n stackRendererData.data &&\n stackRendererData.data.length\n ) {\n stackRenderer = stackRendererData.data[0];\n }\n }\n\n const stackData = toolData.data[0];\n\n // Allow for negative indexing\n if (newImageIdIndex < 0) {\n newImageIdIndex += stackData.imageIds.length;\n }\n\n const startLoadingHandler = loadHandlerManager.getStartLoadHandler(element);\n const endLoadingHandler = loadHandlerManager.getEndLoadHandler(element);\n const errorLoadingHandler = loadHandlerManager.getErrorLoadingHandler(\n element\n );\n\n function doneCallback(image) {\n if (stackData.currentImageIdIndex !== newImageIdIndex) {\n return;\n }\n\n // Check if the element is still enabled in Cornerstone,\n // If an error is thrown, stop here.\n try {\n // TODO: Add 'isElementEnabled' to Cornerstone?\n cornerstone.getEnabledElement(element);\n } catch (error) {\n return;\n }\n\n if (stackRenderer) {\n stackRenderer.currentImageIdIndex = newImageIdIndex;\n stackRenderer.render(element, toolData.data);\n } else {\n cornerstone.displayImage(element, image);\n }\n\n if (endLoadingHandler) {\n endLoadingHandler(element, image);\n }\n }\n\n function failCallback(error) {\n const imageId = stackData.imageIds[newImageIdIndex];\n\n if (errorLoadingHandler) {\n errorLoadingHandler(element, imageId, error);\n }\n }\n\n if (newImageIdIndex === stackData.currentImageIdIndex) {\n return;\n }\n\n if (startLoadingHandler) {\n startLoadingHandler(element);\n }\n\n const eventData = {\n newImageIdIndex,\n direction: newImageIdIndex - stackData.currentImageIdIndex,\n };\n\n stackData.currentImageIdIndex = newImageIdIndex;\n const newImageId = stackData.imageIds[newImageIdIndex];\n\n // Retry image loading in cases where previous image promise\n // Was rejected, if the option is set\n /*\n\n Const config = stackScroll.getConfiguration();\n\n TODO: Revisit this. It appears that Core's imageCache is not\n keeping rejected promises anywhere, so we have no way to know\n if something was previously rejected.\n\n if (config && config.retryLoadOnScroll === true) {\n }\n */\n\n // Convert the preventCache value in stack data to a boolean\n const preventCache = Boolean(stackData.preventCache);\n\n let imagePromise;\n\n if (preventCache) {\n imagePromise = cornerstone.loadImage(newImageId);\n } else {\n imagePromise = cornerstone.loadAndCacheImage(newImageId);\n }\n\n imagePromise.then(doneCallback, failCallback);\n // Make sure we kick off any changed download request pools\n requestPoolManager.startGrabbing();\n\n triggerEvent(element, EVENTS.STACK_SCROLL, eventData);\n}\n","import scrollToIndex from './scrollToIndex.js';\nimport { getToolState } from '../stateManagement/toolState.js';\nimport clip from './clip.js';\nimport external from './../externalModules.js';\n\n/**\n * Scrolls through the stack.\n * @export @public @method\n * @name scroll\n *\n * @param {HTMLElement} element The element to scroll.\n * @param {number} images The number of images to scroll through.\n * @param {type} [loop = false] Whether to loop the scrolling.\n * @param {type} [allowSkipping = true] Whether frames can be skipped.\n * @returns {void}\n */\nexport default function(element, images, loop = false, allowSkipping = true) {\n const toolData = getToolState(element, 'stack');\n\n if (!toolData || !toolData.data || !toolData.data.length) {\n return;\n }\n\n const stackData = toolData.data[0];\n\n if (!stackData.pending) {\n stackData.pending = [];\n }\n\n let newImageIdIndex = stackData.currentImageIdIndex + images;\n\n if (loop) {\n const nbImages = stackData.imageIds.length;\n\n newImageIdIndex %= nbImages;\n } else {\n newImageIdIndex = clip(newImageIdIndex, 0, stackData.imageIds.length - 1);\n }\n\n if (allowSkipping) {\n scrollToIndex(element, newImageIdIndex);\n } else {\n const pendingEvent = {\n index: newImageIdIndex,\n };\n\n stackData.pending.push(pendingEvent);\n scrollWithoutSkipping(stackData, pendingEvent, element);\n }\n}\n\n/**\n * Recursively scrolls the stack until the desired image is reached.\n * @private\n * @method\n * @name scrollWithoutSkipping\n *\n * @param {type} stackData Data object containing information about the stack.\n * @param {Object} pendingEvent The event to process next.\n * @param {HTMLElement} element The element being scrolled through.\n * @returns {void}\n */\nfunction scrollWithoutSkipping(stackData, pendingEvent, element) {\n if (stackData.pending[0] === pendingEvent) {\n if (stackData.currentImageIdIndex === pendingEvent.index) {\n stackData.pending.splice(stackData.pending.indexOf(pendingEvent), 1);\n\n if (stackData.pending.length > 0) {\n scrollWithoutSkipping(stackData, stackData.pending[0], element);\n }\n\n return;\n }\n\n const newImageHandler = function(event) {\n const index = stackData.imageIds.indexOf(event.detail.image.imageId);\n\n if (index === pendingEvent.index) {\n stackData.pending.splice(stackData.pending.indexOf(pendingEvent), 1);\n element.removeEventListener(\n external.cornerstone.EVENTS.NEW_IMAGE,\n newImageHandler\n );\n\n if (stackData.pending.length > 0) {\n scrollWithoutSkipping(stackData, stackData.pending[0], element);\n }\n }\n };\n\n element.addEventListener(\n external.cornerstone.EVENTS.NEW_IMAGE,\n newImageHandler\n );\n\n scrollToIndex(element, pendingEvent.index);\n }\n}\n","import BaseTool from './base/BaseTool.js';\nimport scroll from '../util/scroll.js';\n\n/**\n * @public\n * @class StackScrollMouseWheelTool\n * @memberof Tools\n *\n * @classdesc Tool for scrolling through a series using the mouse wheel.\n * @extends Tools.Base.BaseTool\n */\nexport default class StackScrollMouseWheelTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'StackScrollMouseWheel',\n supportedInteractionTypes: ['MouseWheel'],\n configuration: {\n loop: false,\n allowSkipping: true,\n invert: false,\n },\n };\n\n super(props, defaultProps);\n }\n\n mouseWheelCallback(evt) {\n const { direction: images, element } = evt.detail;\n const { loop, allowSkipping, invert } = this.configuration;\n const direction = invert ? -images : images;\n\n scroll(element, direction, loop, allowSkipping);\n }\n}\n","import BaseTool from './base/BaseTool.js';\nimport scroll from '../util/scroll.js';\nimport { getToolState } from '../stateManagement/toolState.js';\nimport { setToolOptions, getToolOptions } from '../toolOptions.js';\n\n/**\n * @public\n * @class StackScrollMultiTouchTool\n * @memberof Tools\n *\n * @classdesc Tool for scrolling through a series using multi-touch.\n * @extends Tools.Base.BaseTool\n */\nexport default class StackScrollMultiTouchTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'StackScrollMultiTouch',\n supportedInteractionTypes: ['MultiTouch'],\n configuration: {\n loop: false,\n allowSkipping: true,\n touchPointers: 3,\n },\n };\n\n super(props, defaultProps);\n this.multiTouchDragCallback = this._dragCallback.bind(this);\n }\n\n _dragCallback(evt) {\n const eventData = evt.detail;\n\n if (eventData.numPointers === this.configuration.touchPointers) {\n const { element, deltaPoints } = eventData;\n const { loop, allowSkipping } = this.configuration;\n const options = getToolOptions(this.name, element);\n\n const pixelsPerImage = this._getPixelPerImage(element);\n const deltaY = this._getDeltaY(element, deltaPoints.page.y);\n\n if (!pixelsPerImage) {\n return;\n }\n\n if (Math.abs(deltaY) >= pixelsPerImage) {\n const imageIdIndexOffset = Math.round(deltaY / pixelsPerImage);\n\n scroll(element, imageIdIndexOffset, loop, allowSkipping);\n\n options.deltaY = deltaY % pixelsPerImage;\n } else {\n options.deltaY = deltaY;\n }\n\n setToolOptions(this.name, element, options);\n }\n }\n\n _getDeltaY(element, deltaPointsY) {\n const options = getToolOptions(this.name, element);\n const deltaY = options.deltaY || 0;\n\n return deltaY + deltaPointsY;\n }\n\n _getPixelPerImage(element) {\n const toolData = getToolState(element, 'stack');\n\n if (!toolData || !toolData.data || !toolData.data.length) {\n return;\n }\n\n const stackData = toolData.data[0];\n const { stackScrollSpeed } = this.configuration;\n\n // The Math.max here makes it easier to mouseDrag-scroll small or really large image stacks\n return (\n stackScrollSpeed ||\n Math.max(2, element.offsetHeight / Math.max(stackData.imageIds.length, 8))\n );\n }\n}\n","import BaseTool from './base/BaseTool.js';\nimport scroll from '../util/scroll.js';\nimport { getToolState } from '../stateManagement/toolState.js';\nimport { setToolOptions, getToolOptions } from '../toolOptions.js';\nimport { stackScrollCursor } from './cursors/index.js';\n\n/**\n * @public\n * @class StackScrollTool\n * @memberof Tools\n *\n * @classdesc Tool for scrolling through a series.\n * @extends Tools.Base.BaseTool\n */\nexport default class StackScrollTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'StackScroll',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {\n loop: false,\n allowSkipping: true,\n },\n svgCursor: stackScrollCursor,\n };\n\n super(props, defaultProps);\n\n this.mouseDragCallback = this._dragCallback.bind(this);\n this.touchDragCallback = this._dragCallback.bind(this);\n }\n\n _dragCallback(evt) {\n const eventData = evt.detail;\n const { element, deltaPoints } = eventData;\n const { loop, allowSkipping } = this.configuration;\n const options = getToolOptions(this.name, element);\n\n const pixelsPerImage = this._getPixelPerImage(element);\n const deltaY = this._getDeltaY(element, deltaPoints.page.y);\n\n if (!pixelsPerImage) {\n return;\n }\n\n if (Math.abs(deltaY) >= pixelsPerImage) {\n const imageIdIndexOffset = Math.round(deltaY / pixelsPerImage);\n\n scroll(element, imageIdIndexOffset, loop, allowSkipping);\n\n options.deltaY = deltaY % pixelsPerImage;\n } else {\n options.deltaY = deltaY;\n }\n\n setToolOptions(this.name, element, options);\n }\n\n _getDeltaY(element, deltaPointsY) {\n const options = getToolOptions(this.name, element);\n const deltaY = options.deltaY || 0;\n\n return deltaY + deltaPointsY;\n }\n\n _getPixelPerImage(element) {\n const toolData = getToolState(element, 'stack');\n\n if (!toolData || !toolData.data || !toolData.data.length) {\n return;\n }\n\n const stackData = toolData.data[0];\n const { stackScrollSpeed } = this.configuration;\n\n // The Math.max here makes it easier to mouseDrag-scroll small or really large image stacks\n return (\n stackScrollSpeed ||\n Math.max(2, element.offsetHeight / Math.max(stackData.imageIds.length, 8))\n );\n }\n}\n","import external from '../externalModules.js';\n\n/**\n * Returns the luminance of a region.\n * @public\n * @function getLuminance\n *\n * @param {HTMLElement} element The element.\n * @param {number} x The x position of the top-left corner of the region.\n * @param {number} y The y position of the top-left corner of the region.\n * @param {number} width The width of the region.\n * @param {number} height The height of the region\n * @returns {number[]} The luminance.\n */\nexport default function(element, x, y, width, height) {\n if (!element) {\n throw new Error('getLuminance: parameter element must not be undefined');\n }\n\n x = Math.round(x);\n y = Math.round(y);\n const enabledElement = external.cornerstone.getEnabledElement(element);\n const image = enabledElement.image;\n const luminance = [];\n let index = 0;\n const pixelData = image.getPixelData();\n let spIndex, row, column;\n\n if (image.color) {\n for (row = 0; row < height; row++) {\n for (column = 0; column < width; column++) {\n spIndex = ((row + y) * image.columns + (column + x)) * 4;\n const red = pixelData[spIndex];\n const green = pixelData[spIndex + 1];\n const blue = pixelData[spIndex + 2];\n\n luminance[index++] = 0.2126 * red + 0.7152 * green + 0.0722 * blue;\n }\n }\n } else {\n for (row = 0; row < height; row++) {\n for (column = 0; column < width; column++) {\n spIndex = (row + y) * image.columns + (column + x);\n luminance[index++] = pixelData[spIndex] * image.slope + image.intercept;\n }\n }\n }\n\n return luminance;\n}\n","import external from '../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\n// Drawing\nimport { draw, drawRect, getNewContext } from '../drawing/index.js';\nimport clip from '../util/clip.js';\nimport getLuminance from '../util/getLuminance.js';\nimport toolColors from '../stateManagement/toolColors.js';\nimport { wwwcRegionCursor } from './cursors/index.js';\n\n/**\n * @public\n * @class WwwcRegionTool\n * @memberof Tools\n *\n * @classdesc Tool for setting wwwc based on a rectangular region.\n * @extends Tools.Base.BaseTool\n */\nexport default class WwwcRegionTool extends BaseTool {\n /** @inheritdoc */\n constructor(props = {}) {\n const defaultProps = {\n name: 'WwwcRegion',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {\n minWindowWidth: 10,\n },\n svgCursor: wwwcRegionCursor,\n };\n\n super(props, defaultProps);\n this._resetHandles();\n\n //\n // Touch\n //\n\n /** @inheritdoc */\n this.postTouchStartCallback = this._startOutliningRegion.bind(this);\n\n /** @inheritdoc */\n this.touchDragCallback = this._setHandlesAndUpdate.bind(this);\n\n /** @inheritdoc */\n this.touchEndCallback = this._applyStrategy.bind(this);\n\n //\n // MOUSE\n //\n\n /** @inheritdoc */\n this.postMouseDownCallback = this._startOutliningRegion.bind(this);\n\n /** @inheritdoc */\n this.mouseClickCallback = this._startOutliningRegion.bind(this);\n\n /** @inheritdoc */\n this.mouseDragCallback = this._setHandlesAndUpdate.bind(this);\n\n /** @inheritdoc */\n this.mouseMoveCallback = this._setHandlesAndUpdate.bind(this);\n\n /** @inheritdoc */\n this.mouseUpCallback = this._applyStrategy.bind(this);\n }\n\n /**\n * Render hook: draws the WWWCRegion's \"box\" when selecting\n *\n * @param {Cornerstone.event#cornerstoneimagerendered} evt cornerstoneimagerendered event\n * @memberof Tools.WwwcRegionTool\n * @returns {void}\n */\n renderToolData(evt) {\n const eventData = evt.detail;\n const { element } = eventData;\n const color = toolColors.getColorIfActive({ active: true });\n const context = getNewContext(eventData.canvasContext.canvas);\n\n draw(context, context => {\n drawRect(context, element, this.handles.start, this.handles.end, {\n color,\n });\n });\n }\n\n /**\n * Sets the start handle point and claims the eventDispatcher event\n *\n * @private\n * @param {*} evt // mousedown, touchstart, click\n * @returns {Boolean} True\n */\n _startOutliningRegion(evt) {\n const consumeEvent = true;\n const element = evt.detail.element;\n const image = evt.detail.currentPoints.image;\n\n if (_isEmptyObject(this.handles.start)) {\n this.handles.start = image;\n } else {\n this.handles.end = image;\n this._applyStrategy(evt);\n }\n\n external.cornerstone.updateImage(element);\n\n return consumeEvent;\n }\n\n /**\n * This function will update the handles and updateImage to force re-draw\n *\n * @private\n * @method _setHandlesAndUpdate\n * @param {(CornerstoneTools.event#TOUCH_DRAG|CornerstoneTools.event#MOUSE_DRAG|CornerstoneTools.event#MOUSE_MOVE)} evt Interaction event emitted by an enabledElement\n * @returns {void}\n */\n _setHandlesAndUpdate(evt) {\n const element = evt.detail.element;\n const image = evt.detail.currentPoints.image;\n\n this.handles.end = image;\n external.cornerstone.updateImage(element);\n }\n\n /**\n * Event handler for MOUSE_UP/TOUCH_END during handle drag event loop.\n *\n * @private\n * @method _applyStrategy\n * @param {(CornerstoneTools.event#MOUSE_UP|CornerstoneTools.event#TOUCH_END)} evt Interaction event emitted by an enabledElement\n * @returns {void}\n */\n _applyStrategy(evt) {\n if (\n _isEmptyObject(this.handles.start) ||\n _isEmptyObject(this.handles.end)\n ) {\n return;\n }\n\n evt.detail.handles = this.handles;\n _applyWWWCRegion(evt, this.configuration);\n this._resetHandles();\n }\n\n /**\n * Sets the start and end handle points to empty objects\n *\n * @private\n * @method _resetHandles\n * @returns {undefined}\n */\n _resetHandles() {\n this.handles = {\n start: {},\n end: {},\n };\n }\n}\n\n/**\n * Helper to determine if an object has no keys and is the correct type (is empty)\n *\n * @private\n * @function _isEmptyObject\n * @param {Object} obj The object to check\n * @returns {Boolean} true if the object is empty\n */\nconst _isEmptyObject = obj =>\n Object.keys(obj).length === 0 && obj.constructor === Object;\n\n/**\n * Calculates the minimum and maximum value in the given pixel array\n * and updates the viewport of the element in the event.\n *\n * @private\n * @method _applyWWWCRegion\n * @param {(CornerstoneTools.event#MOUSE_UP|CornerstoneTools.event#TOUCH_END)} evt Interaction event emitted by an enabledElement\n * @param {Object} config The tool's configuration object\n * @returns {void}\n */\nconst _applyWWWCRegion = function(evt, config) {\n const eventData = evt.detail;\n const { image, element } = eventData;\n const { start: startPoint, end: endPoint } = evt.detail.handles;\n\n // Get the rectangular region defined by the handles\n let left = Math.min(startPoint.x, endPoint.x);\n let top = Math.min(startPoint.y, endPoint.y);\n let width = Math.abs(startPoint.x - endPoint.x);\n let height = Math.abs(startPoint.y - endPoint.y);\n\n // Bound the rectangle so we don't get undefined pixels\n left = clip(left, 0, image.width);\n top = clip(top, 0, image.height);\n width = Math.floor(Math.min(width, Math.abs(image.width - left)));\n height = Math.floor(Math.min(height, Math.abs(image.height - top)));\n\n // Get the pixel data in the rectangular region\n const pixelLuminanceData = getLuminance(element, left, top, width, height);\n\n // Calculate the minimum and maximum pixel values\n const minMaxMean = _calculateMinMaxMean(\n pixelLuminanceData,\n image.minPixelValue,\n image.maxPixelValue\n );\n\n // Adjust the viewport window width and center based on the calculated values\n const viewport = eventData.viewport;\n\n if (config.minWindowWidth === undefined) {\n config.minWindowWidth = 10;\n }\n\n viewport.voi.windowWidth = Math.max(\n Math.abs(minMaxMean.max - minMaxMean.min),\n config.minWindowWidth\n );\n viewport.voi.windowCenter = minMaxMean.mean;\n\n external.cornerstone.setViewport(element, viewport);\n external.cornerstone.updateImage(element);\n};\n\n/**\n * Calculates the minimum, maximum, and mean value in the given pixel array\n *\n * @private\n * @method _calculateMinMaxMean\n * @param {number[]} pixelLuminance array of pixel luminance values\n * @param {number} globalMin starting \"min\" valie\n * @param {bumber} globalMax starting \"max\" value\n * @returns {Object} {min: number, max: number, mean: number }\n */\nconst _calculateMinMaxMean = function(pixelLuminance, globalMin, globalMax) {\n const numPixels = pixelLuminance.length;\n let min = globalMax;\n let max = globalMin;\n let sum = 0;\n\n if (numPixels < 2) {\n return {\n min,\n max,\n mean: (globalMin + globalMax) / 2,\n };\n }\n\n for (let index = 0; index < numPixels; index++) {\n const spv = pixelLuminance[index];\n\n min = Math.min(min, spv);\n max = Math.max(max, spv);\n sum += spv;\n }\n\n return {\n min,\n max,\n mean: sum / numPixels,\n };\n};\n","import external from '../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\nimport { wwwcCursor } from './cursors/index.js';\n\n/**\n * @public\n * @class WwwcTool\n * @memberof Tools\n *\n * @classdesc Tool for setting wwwc by dragging with mouse/touch.\n * @extends Tools.Base.BaseTool\n */\nexport default class WwwcTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Wwwc',\n strategies: { basicLevelingStrategy },\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {\n orientation: 0,\n },\n svgCursor: wwwcCursor,\n };\n\n super(props, defaultProps);\n }\n\n mouseDragCallback(evt) {\n this.applyActiveStrategy(evt);\n external.cornerstone.setViewport(evt.detail.element, evt.detail.viewport);\n }\n\n touchDragCallback(evt) {\n // Prevent CornerstoneToolsTouchStartActive from killing any press events\n evt.stopImmediatePropagation();\n this.applyActiveStrategy(evt);\n external.cornerstone.setViewport(evt.detail.element, evt.detail.viewport);\n }\n}\n\n/**\n * Here we normalize the ww/wc adjustments so the same number of on screen pixels\n * adjusts the same percentage of the dynamic range of the image. This is needed to\n * provide consistency for the ww/wc tool regardless of the dynamic range (e.g. an 8 bit\n * image will feel the same as a 16 bit image would)\n *\n * @param {Object} evt\n * @param {Object} { orienttion }\n * @returns {void}\n */\nfunction basicLevelingStrategy(evt) {\n const { orientation } = this.configuration;\n const eventData = evt.detail;\n\n const maxVOI =\n eventData.image.maxPixelValue * eventData.image.slope +\n eventData.image.intercept;\n const minVOI =\n eventData.image.minPixelValue * eventData.image.slope +\n eventData.image.intercept;\n const imageDynamicRange = maxVOI - minVOI;\n const multiplier = imageDynamicRange / 1024;\n\n const deltaX = eventData.deltaPoints.page.x * multiplier;\n const deltaY = eventData.deltaPoints.page.y * multiplier;\n\n if (orientation === 0) {\n eventData.viewport.voi.windowWidth += deltaX;\n eventData.viewport.voi.windowCenter += deltaY;\n } else {\n eventData.viewport.voi.windowWidth += deltaY;\n eventData.viewport.voi.windowCenter += deltaX;\n }\n}\n","/**\n * Changes the scale of the viewport.\n *\n * @private\n * @function changeViewportScale\n *\n * @param {Object} viewport The viewport to scale.\n * @param {number} ticks The change in magnifcation factor.\n * @param {Object} scaleLimits The limits in scale.\n * @returns {Object} The scaled viewport.\n */\nexport default function(viewport, ticks, scaleLimits) {\n const { maxScale, minScale } = scaleLimits;\n const pow = 1.7;\n const oldFactor = Math.log(viewport.scale) / Math.log(pow);\n const factor = oldFactor + ticks;\n const scale = Math.pow(pow, factor);\n\n if (maxScale && scale > maxScale) {\n viewport.scale = maxScale;\n } else if (minScale && scale < minScale) {\n viewport.scale = minScale;\n } else {\n viewport.scale = scale;\n }\n\n return viewport;\n}\n","import changeViewportScale from './changeViewportScale.js';\nimport correctShift from './correctShift.js';\n\n// Named\nexport { changeViewportScale, correctShift };\n\n// Default\nexport default {\n changeViewportScale,\n correctShift,\n};\n","/**\n * Corrects the shift by accountoing for viewport rotation and flips.\n * @export @public @method\n * @name correctShift\n *\n * @param {Object} shift The shift to correct.\n * @param {Object} viewportOrientation Object containing information on the viewport orientation.\n * @returns {Object} The corrected shift.\n */\nexport default function(shift, viewportOrientation) {\n const { hflip, vflip, rotation } = viewportOrientation;\n\n // Apply Flips\n shift.x *= hflip ? -1 : 1;\n shift.y *= vflip ? -1 : 1;\n\n // Apply rotations\n if (rotation !== 0) {\n const angle = (rotation * Math.PI) / 180;\n\n const cosA = Math.cos(angle);\n const sinA = Math.sin(angle);\n\n const newX = shift.x * cosA - shift.y * sinA;\n const newY = shift.x * sinA + shift.y * cosA;\n\n shift.x = newX;\n shift.y = newY;\n }\n\n return shift;\n}\n","import external from './../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\nimport { changeViewportScale } from '../util/zoom/index.js';\n\n/**\n * @public\n * @class ZoomMouseWheelTool\n * @memberof Tools\n *\n * @classdesc Tool for changing magnification with the mouse wheel.\n * @extends Tools.Base.BaseTool\n */\nexport default class ZoomMouseWheelTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'ZoomMouseWheel',\n supportedInteractionTypes: ['MouseWheel'],\n configuration: {\n minScale: 0.25,\n maxScale: 20.0,\n invert: false,\n },\n };\n\n super(props, defaultProps);\n }\n\n mouseWheelCallback(evt) {\n const { element, viewport, spinY } = evt.detail;\n const { invert, maxScale, minScale } = this.configuration;\n const ticks = invert ? spinY / 4 : -spinY / 4;\n\n const updatedViewport = changeViewportScale(viewport, ticks, {\n maxScale,\n minScale,\n });\n\n external.cornerstone.setViewport(element, updatedViewport);\n }\n}\n","import external from '../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\nimport { clipToBox } from '../util/clip.js';\nimport zoomUtils from '../util/zoom/index.js';\nimport { zoomCursor } from './cursors/index.js';\n\nconst { correctShift, changeViewportScale } = zoomUtils;\n\n/**\n * @public\n * @class ZoomTool\n * @memberof Tools\n *\n * @classdesc Tool for changing magnification.\n * @extends Tools.Base.BaseTool\n */\nexport default class ZoomTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'Zoom',\n strategies: {\n default: defaultStrategy,\n translate: translateStrategy,\n zoomToCenter: zoomToCenterStrategy,\n },\n defaultStrategy: 'default',\n supportedInteractionTypes: ['Mouse', 'Touch'],\n configuration: {\n invert: false,\n preventZoomOutsideImage: false,\n minScale: 0.25,\n maxScale: 20.0,\n },\n svgCursor: zoomCursor,\n };\n\n super(props, defaultProps);\n }\n\n touchDragCallback(evt) {\n dragCallback.call(this, evt);\n }\n\n mouseDragCallback(evt) {\n dragCallback.call(this, evt);\n }\n}\n\nconst dragCallback = function(evt) {\n const deltaY = evt.detail.deltaPoints.page.y;\n\n if (!deltaY) {\n return false;\n }\n\n this.applyActiveStrategy(evt, this.configuration);\n external.cornerstone.setViewport(evt.detail.element, evt.detail.viewport);\n};\n\n/**\n * The default strategy keeps the target location fixed on the page\n * as we zoom in/out.\n *\n * @param {*} evt\n * @param {*} { invert, maxScale, minScale }\n * @returns {void}\n */\nfunction defaultStrategy(evt) {\n const { invert, maxScale, minScale } = this.configuration;\n const deltaY = evt.detail.deltaPoints.page.y;\n const ticks = invert ? -deltaY / 100 : deltaY / 100;\n const { element, viewport } = evt.detail;\n const [startX, startY, imageX, imageY] = [\n evt.detail.startPoints.page.x,\n evt.detail.startPoints.page.y,\n evt.detail.startPoints.image.x,\n evt.detail.startPoints.image.y,\n ];\n\n // Calculate the new scale factor based on how far the mouse has changed\n const updatedViewport = changeViewportScale(viewport, ticks, {\n maxScale,\n minScale,\n });\n\n external.cornerstone.setViewport(element, updatedViewport);\n\n // Now that the scale has been updated, determine the offset we need to apply to the center so we can\n // Keep the original start location in the same position\n const newCoords = external.cornerstone.pageToPixel(element, startX, startY);\n\n // The shift we will use is the difference between the original image coordinates of the point we've selected\n // And the image coordinates of the same point on the page after the viewport scaling above has been performed\n // This shift is in image coordinates, and is designed to keep the target location fixed on the page.\n let shift = {\n x: imageX - newCoords.x,\n y: imageY - newCoords.y,\n };\n\n // Correct the required shift using the viewport rotation and flip parameters\n shift = correctShift(shift, updatedViewport);\n\n // Apply the shift to the Viewport's translation setting\n viewport.translation.x -= shift.x;\n viewport.translation.y -= shift.y;\n}\n\nfunction translateStrategy(evt) {\n const {\n invert,\n preventZoomOutsideImage,\n maxScale,\n minScale,\n } = this.configuration;\n const deltaY = evt.detail.deltaPoints.page.y;\n const ticks = invert ? -deltaY / 100 : deltaY / 100;\n const image = evt.detail.image;\n const viewport = evt.detail.viewport;\n const [startX, startY] = [\n evt.detail.startPoints.image.x,\n evt.detail.startPoints.image.y,\n ];\n\n // Calculate the new scale factor based on how far the mouse has changed\n // Note that in this case we don't need to update the viewport after the initial\n // Zoom step since we aren't don't intend to keep the target position static on\n // The page\n const updatedViewport = changeViewportScale(viewport, ticks, {\n maxScale,\n minScale,\n });\n\n // Define the default shift to take place during this zoom step\n const shift = {\n x: 0,\n y: 0,\n };\n\n // Define the parameters for the translate strategy\n const translateSpeed = 8;\n const outwardsMinScaleToTranslate = 3;\n const minTranslation = 0.01;\n\n if (ticks < 0) {\n // Zoom outwards from the image center\n if (updatedViewport.scale < outwardsMinScaleToTranslate) {\n // If the current translation is smaller than the minimum desired translation,\n // Set the translation to zero\n if (Math.abs(updatedViewport.translation.x) < minTranslation) {\n updatedViewport.translation.x = 0;\n } else {\n shift.x = updatedViewport.translation.x / translateSpeed;\n }\n\n // If the current translation is smaller than the minimum desired translation,\n // Set the translation to zero\n if (Math.abs(updatedViewport.translation.y) < minTranslation) {\n updatedViewport.translation.y = 0;\n } else {\n shift.y = updatedViewport.translation.y / translateSpeed;\n }\n }\n } else {\n // Zoom inwards to the current image point\n\n // Identify the coordinates of the point the user is trying to zoom into\n // If we are not allowed to zoom outside the image, bound the user-selected position to\n // A point inside the image\n if (preventZoomOutsideImage) {\n clipToBox(evt.detail.startPoints.image, image);\n }\n\n // Calculate the translation value that would place the desired image point in the center\n // Of the viewport\n let desiredTranslation = {\n x: image.width / 2 - startX,\n y: image.height / 2 - startY,\n };\n\n // Correct the target location using the viewport rotation and flip parameters\n desiredTranslation = correctShift(desiredTranslation, updatedViewport);\n\n // Calculate the difference between the current viewport translation value and the\n // Final desired translation values\n const distanceToDesired = {\n x: updatedViewport.translation.x - desiredTranslation.x,\n y: updatedViewport.translation.y - desiredTranslation.y,\n };\n\n // If the current translation is smaller than the minimum desired translation,\n // Stop translating in the x-direction\n if (Math.abs(distanceToDesired.x) < minTranslation) {\n updatedViewport.translation.x = desiredTranslation.x;\n } else {\n // Otherwise, shift the viewport by one step\n shift.x = distanceToDesired.x / translateSpeed;\n }\n\n // If the current translation is smaller than the minimum desired translation,\n // Stop translating in the y-direction\n if (Math.abs(distanceToDesired.y) < minTranslation) {\n updatedViewport.translation.y = desiredTranslation.y;\n } else {\n // Otherwise, shift the viewport by one step\n shift.y = distanceToDesired.y / translateSpeed;\n }\n }\n\n // Apply the shift to the Viewport's translation setting\n updatedViewport.translation.x -= shift.x;\n updatedViewport.translation.y -= shift.y;\n}\n\nfunction zoomToCenterStrategy(evt) {\n const { invert, maxScale, minScale } = this.configuration;\n const deltaY = evt.detail.deltaPoints.page.y;\n const ticks = invert ? -deltaY / 100 : deltaY / 100;\n const viewport = evt.detail.viewport;\n\n // Calculate the new scale factor based on how far the mouse has changed\n changeViewportScale(viewport, ticks, {\n maxScale,\n minScale,\n });\n}\n","import external from './../externalModules.js';\nimport BaseTool from './base/BaseTool.js';\nimport zoomUtils from '../util/zoom/index.js';\n\nconst { correctShift } = zoomUtils;\n\n/**\n *\n *\n * @public\n * @class ZoomTouchPinchTool\n * @memberof Tools\n *\n * @extends {BaseTool}\n */\nexport default class ZoomTouchPinchTool extends BaseTool {\n constructor(props = {}) {\n const defaultProps = {\n name: 'ZoomTouchPinch',\n // TODO: Do we need a better way to specify touchPinch?\n supportedInteractionTypes: ['TouchPinch'],\n configuration: {\n minScale: 0.25,\n maxScale: 20.0,\n },\n };\n\n super(props, defaultProps);\n }\n\n touchPinchCallback(evt) {\n const { element, viewport, scaleChange } = evt.detail;\n const [pageStartX, pageStartY, imageStartX, imageStartY] = [\n evt.detail.startPoints.page.x,\n evt.detail.startPoints.page.y,\n evt.detail.startPoints.image.x,\n evt.detail.startPoints.image.y,\n ];\n const { maxScale, minScale } = this.configuration;\n\n // Change the scale based on the pinch gesture's scale change\n viewport.scale += scaleChange * viewport.scale;\n if (maxScale && viewport.scale > maxScale) {\n viewport.scale = maxScale;\n } else if (minScale && viewport.scale < minScale) {\n viewport.scale = minScale;\n }\n\n external.cornerstone.setViewport(element, viewport);\n\n // Now that the scale has been updated, determine the offset we need to apply to the center so we can\n // Keep the original start location in the same position\n const newCoords = external.cornerstone.pageToPixel(\n element,\n pageStartX,\n pageStartY\n );\n let shift = {\n x: imageStartX - newCoords.x,\n y: imageStartY - newCoords.y,\n };\n\n shift = correctShift(shift, viewport);\n viewport.translation.x -= shift.x;\n viewport.translation.y -= shift.y;\n external.cornerstone.setViewport(element, viewport);\n }\n}\n","/**\n * Returns a copy of the points object.\n * @public\n * @function copyPoints\n *\n * @param {Object} points - The object to copy.\n * @returns {Object} - The copy.\n */\nexport default function(points) {\n const page = _copy(points.page);\n const image = _copy(points.image);\n const client = _copy(points.client);\n const canvas = _copy(points.canvas);\n\n return {\n page,\n image,\n client,\n canvas,\n };\n}\n\n/**\n *\n * @private\n * @function _copy\n *\n * @param {Object} point - { x, y }\n * @returns {Object} { x, y }\n */\nfunction _copy({ x, y } = {}) {\n return {\n x,\n y,\n };\n}\n","import EVENTS from '../events.js';\nimport external from '../externalModules.js';\nimport copyPoints from '../util/copyPoints.js';\nimport triggerEvent from '../util/triggerEvent.js';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('eventListeners:mouseEventListeners');\n\nlet isClickEvent = true;\nlet preventClickTimeout;\nconst clickDelay = 200;\n\nfunction getEventButtons(event) {\n if (typeof event.buttons === 'number') {\n return event.buttons;\n }\n\n switch (event.which) {\n // No button\n case 0:\n return 0;\n // Left\n case 1:\n return 1;\n // Middle\n case 2:\n return 4;\n // Right\n case 3:\n return 2;\n }\n\n return 0;\n}\n\nfunction preventClickHandler() {\n isClickEvent = false;\n}\n\nfunction mouseDoubleClick(e) {\n const element = e.currentTarget;\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n if (!enabledElement.image) {\n return;\n }\n\n const eventType = EVENTS.MOUSE_DOUBLE_CLICK;\n\n const startPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e),\n image: external.cornerstone.pageToPixel(element, e.pageX, e.pageY),\n client: {\n x: e.clientX,\n y: e.clientY,\n },\n };\n\n startPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n startPoints.image\n );\n\n const lastPoints = copyPoints(startPoints);\n\n logger.log('double-click: %o', getEventButtons(e));\n const eventData = {\n event: e,\n buttons: getEventButtons(e),\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n startPoints,\n lastPoints,\n currentPoints: startPoints,\n deltaPoints: {\n x: 0,\n y: 0,\n },\n type: eventType,\n };\n\n triggerEvent(element, eventType, eventData);\n}\n\nfunction mouseDown(e) {\n const element = e.currentTarget;\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n if (!enabledElement.image) {\n return;\n }\n\n preventClickTimeout = setTimeout(preventClickHandler, clickDelay);\n\n // Prevent CornerstoneToolsMouseMove while mouse is down\n element.removeEventListener('mousemove', mouseMove);\n\n const startPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e),\n image: external.cornerstone.pageToPixel(element, e.pageX, e.pageY),\n client: {\n x: e.clientX,\n y: e.clientY,\n },\n };\n\n startPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n startPoints.image\n );\n\n let lastPoints = copyPoints(startPoints);\n\n const eventData = {\n event: e,\n buttons: getEventButtons(e),\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n startPoints,\n lastPoints,\n currentPoints: startPoints,\n deltaPoints: {\n x: 0,\n y: 0,\n },\n type: EVENTS.MOUSE_DOWN,\n };\n\n const eventPropagated = triggerEvent(\n eventData.element,\n EVENTS.MOUSE_DOWN,\n eventData\n );\n\n if (eventPropagated) {\n // No tools responded to this event, create a new tool\n eventData.type = EVENTS.MOUSE_DOWN_ACTIVATE;\n triggerEvent(eventData.element, EVENTS.MOUSE_DOWN_ACTIVATE, eventData);\n }\n\n function onMouseMove(e) {\n // Calculate our current points in page and image coordinates\n const eventType = EVENTS.MOUSE_DRAG;\n const currentPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e),\n image: external.cornerstone.pageToPixel(element, e.pageX, e.pageY),\n client: {\n x: e.clientX,\n y: e.clientY,\n },\n };\n\n currentPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n currentPoints.image\n );\n\n // Calculate delta values in page and image coordinates\n const deltaPoints = {\n page: external.cornerstoneMath.point.subtract(\n currentPoints.page,\n lastPoints.page\n ),\n image: external.cornerstoneMath.point.subtract(\n currentPoints.image,\n lastPoints.image\n ),\n client: external.cornerstoneMath.point.subtract(\n currentPoints.client,\n lastPoints.client\n ),\n canvas: external.cornerstoneMath.point.subtract(\n currentPoints.canvas,\n lastPoints.canvas\n ),\n };\n\n logger.log('mousemove: %o', getEventButtons(e));\n const eventData = {\n buttons: getEventButtons(e),\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n startPoints,\n lastPoints,\n currentPoints,\n deltaPoints,\n type: eventType,\n ctrlKey: e.ctrlKey,\n metaKey: e.metaKey,\n shiftKey: e.shiftKey,\n };\n\n triggerEvent(eventData.element, eventType, eventData);\n\n // Update the last points\n lastPoints = copyPoints(currentPoints);\n }\n\n // Hook mouseup so we can unbind our event listeners\n // When they stop dragging\n function onMouseUp(e) {\n // Cancel the timeout preventing the click event from triggering\n clearTimeout(preventClickTimeout);\n\n let eventType = EVENTS.MOUSE_UP;\n\n if (isClickEvent) {\n eventType = EVENTS.MOUSE_CLICK;\n }\n\n // Calculate our current points in page and image coordinates\n const currentPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e),\n image: external.cornerstone.pageToPixel(element, e.pageX, e.pageY),\n client: {\n x: e.clientX,\n y: e.clientY,\n },\n };\n\n currentPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n currentPoints.image\n );\n\n // Calculate delta values in page and image coordinates\n const deltaPoints = {\n page: external.cornerstoneMath.point.subtract(\n currentPoints.page,\n lastPoints.page\n ),\n image: external.cornerstoneMath.point.subtract(\n currentPoints.image,\n lastPoints.image\n ),\n client: external.cornerstoneMath.point.subtract(\n currentPoints.client,\n lastPoints.client\n ),\n canvas: external.cornerstoneMath.point.subtract(\n currentPoints.canvas,\n lastPoints.canvas\n ),\n };\n\n logger.log('mouseup: %o', getEventButtons(e));\n const eventData = {\n event: e,\n buttons: getEventButtons(e),\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n startPoints,\n lastPoints,\n currentPoints,\n deltaPoints,\n type: eventType,\n };\n\n triggerEvent(eventData.element, eventType, eventData);\n\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n\n element.addEventListener('mousemove', mouseMove);\n\n isClickEvent = true;\n }\n\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n}\n\nfunction mouseMove(e) {\n const element = e.currentTarget;\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n if (!enabledElement.image) {\n return;\n }\n\n const eventType = EVENTS.MOUSE_MOVE;\n\n const startPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e),\n image: external.cornerstone.pageToPixel(element, e.pageX, e.pageY),\n client: {\n x: e.clientX,\n y: e.clientY,\n },\n };\n\n startPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n startPoints.image\n );\n\n let lastPoints = copyPoints(startPoints);\n\n // Calculate our current points in page and image coordinates\n const currentPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e),\n image: external.cornerstone.pageToPixel(element, e.pageX, e.pageY),\n client: {\n x: e.clientX,\n y: e.clientY,\n },\n };\n\n currentPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n currentPoints.image\n );\n\n // Calculate delta values in page and image coordinates\n const deltaPoints = {\n page: external.cornerstoneMath.point.subtract(\n currentPoints.page,\n lastPoints.page\n ),\n image: external.cornerstoneMath.point.subtract(\n currentPoints.image,\n lastPoints.image\n ),\n client: external.cornerstoneMath.point.subtract(\n currentPoints.client,\n lastPoints.client\n ),\n canvas: external.cornerstoneMath.point.subtract(\n currentPoints.canvas,\n lastPoints.canvas\n ),\n };\n\n const eventData = {\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n startPoints,\n lastPoints,\n currentPoints,\n deltaPoints,\n type: eventType,\n };\n\n triggerEvent(element, eventType, eventData);\n\n // Update the last points\n lastPoints = copyPoints(currentPoints);\n}\n\nfunction disable(element) {\n element.removeEventListener('mousedown', mouseDown);\n element.removeEventListener('mousemove', mouseMove);\n element.removeEventListener('dblclick', mouseDoubleClick);\n}\n\nfunction enable(element) {\n // Prevent handlers from being attached multiple times\n disable(element);\n\n element.addEventListener('mousedown', mouseDown);\n element.addEventListener('mousemove', mouseMove);\n element.addEventListener('dblclick', mouseDoubleClick);\n}\n\nexport default {\n enable,\n disable,\n};\n","// Reasonable defaults\nconst PIXEL_STEP = 10;\nconst LINE_HEIGHT = 40;\nconst PAGE_HEIGHT = 800;\n\n/**\n * Normalizes wheel events and provides properties that are more\n * consistent and helpful across different browsers\n *\n * @private\n * @function normalizeWheel\n * @param {WheelEvent} event\n * @returns {Object} { spinX, spinY, pixlX, pixelY }\n */\nexport default function(event) {\n let spinX = 0,\n spinY = 0,\n pixelX = 0,\n pixelY = 0;\n\n // Legacy\n if ('detail' in event) {\n spinY = event.detail;\n }\n if ('wheelDelta' in event) {\n spinY = -event.wheelDelta / 120;\n }\n if ('wheelDeltaY' in event) {\n spinY = -event.wheelDeltaY / 120;\n }\n if ('wheelDeltaX' in event) {\n spinX = -event.wheelDeltaX / 120;\n }\n\n pixelX = spinX * PIXEL_STEP;\n pixelY = spinY * PIXEL_STEP;\n\n if ('deltaY' in event) {\n pixelY = event.deltaY;\n }\n if ('deltaX' in event) {\n pixelX = event.deltaX;\n }\n\n if ((pixelX || pixelY) && event.deltaMode) {\n if (event.deltaMode === 1) {\n // Delta in LINE units\n pixelX *= LINE_HEIGHT;\n pixelY *= LINE_HEIGHT;\n } else {\n // Delta in PAGE units\n pixelX *= PAGE_HEIGHT;\n pixelY *= PAGE_HEIGHT;\n }\n }\n\n // Fall-back if spin cannot be determined\n if (pixelX && !spinX) {\n spinX = pixelX < 1 ? -1 : 1;\n }\n if (pixelY && !spinY) {\n spinY = pixelY < 1 ? -1 : 1;\n }\n\n return {\n spinX,\n spinY,\n pixelX,\n pixelY,\n };\n}\n","/**\n * Internal module used to turn on listening, handling, and normalizing of the\n * native `wheel` event\n */\n\nimport EVENTS from '../events.js';\nimport external from '../externalModules.js';\nimport triggerEvent from '../util/triggerEvent.js';\nimport normalizeWheel from './internals/normalizeWheel.js';\n\n/**\n *\n * @private\n * @function wheelEventHandler\n * @param {WheelEvent} evt\n * @returns {undefined}\n */\nfunction wheelEventHandler(evt) {\n const element = evt.currentTarget;\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n if (!enabledElement.image) {\n return;\n }\n\n // Prevent triggering MouseWheel events that are not real scroll events:\n // E.g. when clicking the MiddleMouseWheelButton, a deltaY of 0 is emitted.\n // See https://github.com/cornerstonejs/cornerstoneTools/issues/935\n if (evt.deltaY > -1 && evt.deltaY < 1) {\n return;\n }\n\n evt.preventDefault();\n\n const { pageX, pageY } = evt;\n const startingCoords = external.cornerstone.pageToPixel(\n element,\n pageX,\n pageY\n );\n const { spinX, spinY, pixelX, pixelY } = normalizeWheel(evt);\n const direction = spinY < 0 ? -1 : 1;\n\n const mouseWheelData = {\n element,\n viewport: external.cornerstone.getViewport(element),\n detail: evt,\n image: enabledElement.image,\n direction,\n spinX,\n spinY,\n pixelX,\n pixelY,\n pageX,\n pageY,\n imageX: startingCoords.x,\n imageY: startingCoords.y,\n };\n\n triggerEvent(element, EVENTS.MOUSE_WHEEL, mouseWheelData);\n}\n\n/**\n * Listens for the wheel event, and handles it. Handled event\n * will be \"normalized\" and re-emitted as `EVENTS.MOUSE_WHEEL`\n *\n * @private\n * @param {HTMLElement} element\n * @returns {undefined}\n */\nfunction enable(element) {\n disable(element);\n element.addEventListener('wheel', wheelEventHandler, { passive: false });\n}\n\n/**\n * Removes listener and handler for wheel event. `EVENTS.MOUSE_WHEEL`\n * will no longer be emitted.\n *\n * @private\n * @param {HTMLElement} element\n * @returns {undefined}\n */\nfunction disable(element) {\n element.removeEventListener('wheel', wheelEventHandler, { passive: false });\n}\n\nexport default {\n enable,\n disable,\n};\n","// Functions to prevent ghost clicks following a touch\n// All credit to @kosich\n// https://gist.github.com/kosich/23188dd86633b6c2efb7\n\nconst antiGhostDelay = 2000,\n pointerType = {\n mouse: 0,\n touch: 1,\n };\n\nlet lastInteractionType, lastInteractionTime;\n\nfunction handleTap(type, e) {\n const now = Date.now();\n\n if (type !== lastInteractionType) {\n if (now - lastInteractionTime <= antiGhostDelay) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n return false;\n }\n\n lastInteractionType = type;\n }\n\n lastInteractionTime = now;\n}\n\n// Cacheing the function references\n// Necessary because a new function reference is created after .bind() is called\n// http://stackoverflow.com/questions/11565471/removing-event-listener-which-was-added-with-bind\nconst handleTapMouse = handleTap.bind(null, pointerType.mouse);\nconst handleTapTouch = handleTap.bind(null, pointerType.touch);\n\nfunction attachEvents(element, eventList, interactionType) {\n const tapHandler = interactionType ? handleTapMouse : handleTapTouch;\n\n eventList.forEach(function(eventName) {\n element.addEventListener(eventName, tapHandler, { passive: false });\n });\n}\n\nfunction removeEvents(element, eventList, interactionType) {\n const tapHandler = interactionType ? handleTapMouse : handleTapTouch;\n\n eventList.forEach(function(eventName) {\n element.removeEventListener(eventName, tapHandler);\n });\n}\n\nconst mouseEvents = ['mousedown', 'mouseup'];\nconst touchEvents = ['touchstart', 'touchend'];\n\nfunction disable(element) {\n removeEvents(element, mouseEvents, pointerType.mouse);\n removeEvents(element, touchEvents, pointerType.touch);\n}\n\nfunction enable(element) {\n disable(element);\n attachEvents(element, mouseEvents, pointerType.mouse);\n attachEvents(element, touchEvents, pointerType.touch);\n}\n\nexport default {\n enable,\n disable,\n};\n","import EVENTS from '../events.js';\nimport external from '../externalModules.js';\nimport copyPoints from '../util/copyPoints.js';\nimport preventGhostClick from './preventGhostClick.js';\nimport triggerEvent from '../util/triggerEvent.js';\nimport { setToolOptions, getToolOptions } from '../toolOptions.js';\n\nlet startPoints,\n currentPoints,\n lastPoints,\n deltaPoints,\n eventData,\n touchStartDelay,\n pressTimeout,\n pageDistanceMoved;\n\nlet lastScale = 1.0,\n lastRotation = 0.0,\n preventNextPinch = false,\n isPress = false,\n lastDelta;\n\nconst pressDelay = 700,\n pressMaxDistance = 5;\n\nconst toolType = 'touchInput';\n\nfunction onTouch(e) {\n const element = e.currentTarget || e.srcEvent.currentTarget;\n const enabledElement = external.cornerstone.getEnabledElement(element);\n\n if (!enabledElement.image) {\n return;\n }\n\n let eventType, scaleChange, delta, remainingPointers, rotation;\n\n // Prevent mouse events from occurring alongside touch events\n e.preventDefault();\n\n // If more than one finger is placed on the element, stop the press timeout\n if (\n (e.pointers && e.pointers.length > 1) ||\n (e.touches && e.touches.length > 1)\n ) {\n isPress = false;\n clearTimeout(pressTimeout);\n }\n\n switch (e.type) {\n case 'tap':\n isPress = false;\n clearTimeout(pressTimeout);\n\n // Calculate our current points in page and image coordinates\n currentPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e.pointers[0]),\n image: external.cornerstone.pageToPixel(\n element,\n e.pointers[0].pageX,\n e.pointers[0].pageY\n ),\n client: {\n x: e.pointers[0].clientX,\n y: e.pointers[0].clientY,\n },\n };\n currentPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n currentPoints.image\n );\n\n eventType = EVENTS.TAP;\n eventData = {\n event: e,\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n currentPoints,\n type: eventType,\n isTouchEvent: true,\n };\n\n triggerEvent(element, eventType, eventData);\n break;\n\n case 'doubletap':\n isPress = false;\n clearTimeout(pressTimeout);\n\n // Calculate our current points in page and image coordinates\n currentPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e.pointers[0]),\n image: external.cornerstone.pageToPixel(\n element,\n e.pointers[0].pageX,\n e.pointers[0].pageY\n ),\n client: {\n x: e.pointers[0].clientX,\n y: e.pointers[0].clientY,\n },\n };\n currentPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n currentPoints.image\n );\n\n eventType = EVENTS.DOUBLE_TAP;\n eventData = {\n event: e,\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n currentPoints,\n type: eventType,\n isTouchEvent: true,\n };\n\n triggerEvent(element, eventType, eventData);\n break;\n\n case 'pinchstart':\n isPress = false;\n clearTimeout(pressTimeout);\n\n lastScale = 1.0;\n break;\n\n case 'pinchmove':\n isPress = false;\n clearTimeout(pressTimeout);\n\n if (preventNextPinch === true) {\n lastScale = e.scale;\n preventNextPinch = false;\n break;\n }\n\n scaleChange = (e.scale - lastScale) / lastScale;\n\n startPoints = {\n page: e.center,\n image: external.cornerstone.pageToPixel(\n element,\n e.center.x,\n e.center.y\n ),\n };\n startPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n startPoints.image\n );\n\n eventType = EVENTS.TOUCH_PINCH;\n eventData = {\n event: e,\n startPoints,\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n direction: e.scale < 1 ? 1 : -1,\n scaleChange,\n type: eventType,\n isTouchEvent: true,\n };\n\n triggerEvent(element, eventType, eventData);\n\n lastScale = e.scale;\n break;\n\n case 'touchstart':\n lastScale = 1.0;\n\n clearTimeout(pressTimeout);\n\n clearTimeout(touchStartDelay);\n touchStartDelay = setTimeout(function() {\n startPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e.touches[0]),\n image: external.cornerstone.pageToPixel(\n element,\n e.touches[0].pageX,\n e.touches[0].pageY\n ),\n client: {\n x: e.touches[0].clientX,\n y: e.touches[0].clientY,\n },\n };\n startPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n startPoints.image\n );\n\n eventType = EVENTS.TOUCH_START;\n if (e.touches.length > 1) {\n eventType = EVENTS.MULTI_TOUCH_START;\n }\n\n eventData = {\n event: e,\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n startPoints,\n currentPoints: startPoints,\n type: eventType,\n isTouchEvent: true,\n };\n\n const eventPropagated = triggerEvent(element, eventType, eventData);\n\n if (eventPropagated === true) {\n // IsPress = false;\n // ClearTimeout(pressTimeout);\n\n // No current tools responded to the drag action.\n // Create new tool measurement\n eventType = EVENTS.TOUCH_START_ACTIVE;\n if (e.touches.length > 1) {\n eventType = EVENTS.MULTI_TOUCH_START_ACTIVE;\n }\n\n eventData.type = eventType;\n triggerEvent(element, eventType, eventData);\n }\n\n // Console.log(eventType);\n lastPoints = copyPoints(startPoints);\n }, 50);\n\n isPress = true;\n pageDistanceMoved = 0;\n pressTimeout = setTimeout(function() {\n if (!isPress) {\n return;\n }\n\n currentPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e.touches[0]),\n image: external.cornerstone.pageToPixel(\n element,\n e.touches[0].pageX,\n e.touches[0].pageY\n ),\n client: {\n x: e.touches[0].clientX,\n y: e.touches[0].clientY,\n },\n };\n currentPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n startPoints.image\n );\n\n eventType = EVENTS.TOUCH_PRESS;\n eventData = {\n event: e,\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n currentPoints,\n type: eventType,\n isTouchEvent: true,\n };\n\n triggerEvent(element, eventType, eventData);\n\n // Console.log(eventType);\n }, pressDelay);\n break;\n\n case 'touchend':\n lastScale = 1.0;\n\n isPress = false;\n clearTimeout(pressTimeout);\n\n setTimeout(function() {\n startPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e.changedTouches[0]),\n image: external.cornerstone.pageToPixel(\n element,\n e.changedTouches[0].pageX,\n e.changedTouches[0].pageY\n ),\n client: {\n x: e.changedTouches[0].clientX,\n y: e.changedTouches[0].clientY,\n },\n };\n startPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n startPoints.image\n );\n\n eventType = EVENTS.TOUCH_END;\n\n eventData = {\n event: e,\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n startPoints,\n currentPoints: startPoints,\n type: eventType,\n isTouchEvent: true,\n };\n\n triggerEvent(element, eventType, eventData);\n }, 50);\n break;\n\n case 'panmove':\n // Using the delta-value of HammerJS, because it takes all pointers into account\n // This is very important when using panning in combination with pinch-zooming\n // But HammerJS' delta is relative to the start of the pan event\n // So it needs to be converted to a per-event-delta for CornerstoneTools\n delta = {\n x: e.deltaX - lastDelta.x,\n y: e.deltaY - lastDelta.y,\n };\n\n lastDelta = {\n x: e.deltaX,\n y: e.deltaY,\n };\n\n // Calculate our current points in page and image coordinates\n currentPoints = {\n page: {\n x: lastPoints.page.x + delta.x,\n y: lastPoints.page.y + delta.y,\n },\n image: external.cornerstone.pageToPixel(\n element,\n lastPoints.page.x + delta.x,\n lastPoints.page.y + delta.y\n ),\n client: {\n x: lastPoints.client.x + delta.x,\n y: lastPoints.client.y + delta.y,\n },\n };\n currentPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n currentPoints.image\n );\n\n // Calculate delta values in page and image coordinates\n deltaPoints = {\n page: external.cornerstoneMath.point.subtract(\n currentPoints.page,\n lastPoints.page\n ),\n image: external.cornerstoneMath.point.subtract(\n currentPoints.image,\n lastPoints.image\n ),\n client: external.cornerstoneMath.point.subtract(\n currentPoints.client,\n lastPoints.client\n ),\n canvas: external.cornerstoneMath.point.subtract(\n currentPoints.canvas,\n lastPoints.canvas\n ),\n };\n\n pageDistanceMoved += Math.sqrt(\n deltaPoints.page.x * deltaPoints.page.x +\n deltaPoints.page.y * deltaPoints.page.y\n );\n // Console.log(\"pageDistanceMoved: \" + pageDistanceMoved);\n if (pageDistanceMoved > pressMaxDistance) {\n // Console.log('Press event aborted due to movement');\n isPress = false;\n clearTimeout(pressTimeout);\n }\n\n eventType = EVENTS.TOUCH_DRAG;\n if (e.pointers.length > 1) {\n eventType = EVENTS.MULTI_TOUCH_DRAG;\n }\n\n eventData = {\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n startPoints,\n lastPoints,\n currentPoints,\n deltaPoints,\n numPointers: e.pointers.length,\n type: eventType,\n isTouchEvent: true,\n };\n\n triggerEvent(element, eventType, eventData);\n\n lastPoints = copyPoints(currentPoints);\n break;\n\n case 'panstart':\n lastDelta = {\n x: e.deltaX,\n y: e.deltaY,\n };\n\n currentPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e.pointers[0]),\n image: external.cornerstone.pageToPixel(\n element,\n e.pointers[0].pageX,\n e.pointers[0].pageY\n ),\n client: {\n x: e.pointers[0].clientX,\n y: e.pointers[0].clientY,\n },\n };\n currentPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n currentPoints.image\n );\n lastPoints = copyPoints(currentPoints);\n break;\n\n case 'panend':\n isPress = false;\n clearTimeout(pressTimeout);\n\n // If lastPoints is not yet set, it means panend fired without panstart or pan,\n // So we can ignore this event\n if (!lastPoints) {\n return false;\n }\n\n currentPoints = {\n page: external.cornerstoneMath.point.pageToPoint(e.pointers[0]),\n image: external.cornerstone.pageToPixel(\n element,\n e.pointers[0].pageX,\n e.pointers[0].pageY\n ),\n client: {\n x: e.pointers[0].clientX,\n y: e.pointers[0].clientY,\n },\n };\n currentPoints.canvas = external.cornerstone.pixelToCanvas(\n element,\n currentPoints.image\n );\n\n // Calculate delta values in page and image coordinates\n deltaPoints = {\n page: external.cornerstoneMath.point.subtract(\n currentPoints.page,\n lastPoints.page\n ),\n image: external.cornerstoneMath.point.subtract(\n currentPoints.image,\n lastPoints.image\n ),\n client: external.cornerstoneMath.point.subtract(\n currentPoints.client,\n lastPoints.client\n ),\n canvas: external.cornerstoneMath.point.subtract(\n currentPoints.canvas,\n lastPoints.canvas\n ),\n };\n\n eventType = EVENTS.TOUCH_DRAG_END;\n\n eventData = {\n event: e.srcEvent,\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n startPoints,\n lastPoints,\n currentPoints,\n deltaPoints,\n type: eventType,\n isTouchEvent: true,\n };\n\n triggerEvent(element, eventType, eventData);\n\n remainingPointers = e.pointers.length - e.changedPointers.length;\n\n if (remainingPointers === 2) {\n preventNextPinch = true;\n }\n break;\n\n case 'rotatemove':\n isPress = false;\n clearTimeout(pressTimeout);\n\n rotation = e.rotation - lastRotation;\n\n lastRotation = e.rotation;\n\n eventType = EVENTS.TOUCH_ROTATE;\n eventData = {\n event: e.srcEvent,\n viewport: external.cornerstone.getViewport(element),\n image: enabledElement.image,\n element,\n rotation,\n type: eventType,\n };\n triggerEvent(element, eventType, eventData);\n break;\n }\n\n return false;\n}\n\nfunction enable(element) {\n disable(element);\n const Hammer = external.Hammer;\n\n const hammerOptions = {\n inputClass: Hammer.SUPPORT_POINTER_EVENTS\n ? Hammer.PointerEventInput\n : Hammer.TouchInput,\n };\n\n const mc = new Hammer.Manager(element, hammerOptions);\n\n const panOptions = {\n pointers: 0,\n direction: Hammer.DIRECTION_ALL,\n threshold: 0,\n };\n\n const pan = new Hammer.Pan(panOptions);\n const pinch = new Hammer.Pinch({\n threshold: 0,\n });\n const rotate = new Hammer.Rotate({\n threshold: 0,\n });\n\n pinch.recognizeWith(pan);\n pinch.recognizeWith(rotate);\n rotate.recognizeWith(pan);\n\n const doubleTap = new Hammer.Tap({\n event: 'doubletap',\n taps: 2,\n interval: 1500,\n threshold: 50,\n posThreshold: 50,\n });\n\n doubleTap.recognizeWith(pan);\n\n // Add to the Manager\n mc.add([doubleTap, pan, rotate, pinch]);\n mc.on(\n 'tap doubletap panstart panmove panend pinchstart pinchmove rotatemove',\n onTouch\n );\n\n preventGhostClick.enable(element);\n\n const touchEvents = ['touchstart', 'touchend'];\n\n touchEvents.forEach(eventType => {\n element.addEventListener(eventType, onTouch, { passive: false });\n });\n\n const options = getToolOptions(toolType, element);\n\n options.hammer = mc;\n\n setToolOptions(toolType, element, options);\n}\n\nfunction disable(element) {\n preventGhostClick.disable(element);\n\n const touchEvents = ['touchstart', 'touchend'];\n\n touchEvents.forEach(eventType => {\n element.removeEventListener(eventType, onTouch);\n });\n\n const options = getToolOptions(toolType, element);\n const mc = options.hammer;\n\n if (mc) {\n mc.off(\n 'tap doubletap panstart panmove panend pinchstart pinchmove rotatemove',\n onTouch\n );\n }\n}\n\n// Module exports\nconst touchInput = {\n enable,\n disable,\n};\n\nexport default touchInput;\n","import { getModule } from '../../store/index.js';\nimport {\n getNewContext,\n resetCanvasContextTransform,\n transformCanvasContext,\n} from '../../drawing/index.js';\nimport external from '../../externalModules';\n\nconst segmentationModule = getModule('segmentation');\n\nexport default function renderSegmentationFill(\n evt,\n labelmap3D,\n labelmap2D,\n labelmapIndex,\n isActiveLabelMap\n) {\n const labelmapCanvas = getLabelmapCanvas(evt, labelmap3D, labelmap2D);\n\n renderFill(evt, labelmapCanvas, isActiveLabelMap);\n}\n\n/**\n * Generates a canvas of the `Labelmap2D` data with transparent background, to draw onto the\n * cornerstone canvas. Reduces the number of `putImageData` calls that need to be made by\n * scanning across the labelmap and painting to the canvas in chunks.\n *\n * @param {Object} evt The cornerstone event.\n * @param {Labelmap3D} labelmap3D The `Labelmap3D` object.\n * @param {Labelmap2D} labelmap2D The `Labelmap2D` object containing the pixelData to render.\n * @returns {HTMLCanvasElement}\n */\nexport function getLabelmapCanvas(evt, labelmap3D, labelmap2D) {\n const { state } = segmentationModule;\n const eventData = evt.detail;\n const { image } = eventData;\n const cols = image.width;\n const rows = image.height;\n const { segmentsHidden } = labelmap3D;\n const pixelData = labelmap2D.pixelData;\n const colorLutTable = state.colorLutTables[labelmap3D.colorLUTIndex];\n const canvasElement = document.createElement('canvas');\n\n canvasElement.width = cols;\n canvasElement.height = rows;\n\n const ctx = getNewContext(canvasElement);\n\n // Image data initialized with all transparent black.\n const imageData = new ImageData(cols, rows);\n const data = imageData.data;\n\n for (let i = 0; i < pixelData.length; i++) {\n const segmentIndex = pixelData[i];\n\n if (segmentIndex !== 0 && !segmentsHidden[segmentIndex]) {\n const color = colorLutTable[pixelData[i]];\n\n // Modify ImageData.\n data[4 * i] = color[0]; // R value\n data[4 * i + 1] = color[1]; // G value\n data[4 * i + 2] = color[2]; // B value\n data[4 * i + 3] = color[3]; // A value\n }\n }\n\n // Put this image data onto the labelmapCanvas.\n ctx.putImageData(imageData, 0, 0);\n\n return canvasElement;\n}\n\n/**\n * Renders the filled region of each segment in the segmentation.\n * @param {Object} evt The cornerstone event.\n * @param {HTMLCanvasElement} labelmapCanvas The canvas generated for the labelmap.\n * @param {boolean} isActiveLabelMap Whether or not the labelmap is active.\n * @returns {null}\n */\nexport function renderFill(evt, labelmapCanvas, isActiveLabelMap) {\n const { configuration } = segmentationModule;\n const eventData = evt.detail;\n const context = getNewContext(eventData.canvasContext.canvas);\n\n const canvasTopLeft = external.cornerstone.pixelToCanvas(eventData.element, {\n x: 0,\n y: 0,\n });\n\n const canvasTopRight = external.cornerstone.pixelToCanvas(eventData.element, {\n x: eventData.image.width,\n y: 0,\n });\n\n const canvasBottomRight = external.cornerstone.pixelToCanvas(\n eventData.element,\n {\n x: eventData.image.width,\n y: eventData.image.height,\n }\n );\n\n const cornerstoneCanvasWidth = external.cornerstoneMath.point.distance(\n canvasTopLeft,\n canvasTopRight\n );\n const cornerstoneCanvasHeight = external.cornerstoneMath.point.distance(\n canvasTopRight,\n canvasBottomRight\n );\n\n const canvas = eventData.canvasContext.canvas;\n const viewport = eventData.viewport;\n\n const previousImageSmoothingEnabled = context.imageSmoothingEnabled;\n const previousGlobalAlpha = context.globalAlpha;\n\n context.imageSmoothingEnabled = false;\n context.globalAlpha = isActiveLabelMap\n ? configuration.fillAlpha\n : configuration.fillAlphaInactive;\n\n transformCanvasContext(context, canvas, viewport);\n\n const canvasViewportTranslation = {\n x: viewport.translation.x * viewport.scale,\n y: viewport.translation.y * viewport.scale,\n };\n\n context.drawImage(\n labelmapCanvas,\n canvas.width / 2 - cornerstoneCanvasWidth / 2 + canvasViewportTranslation.x,\n canvas.height / 2 -\n cornerstoneCanvasHeight / 2 +\n canvasViewportTranslation.y,\n cornerstoneCanvasWidth,\n cornerstoneCanvasHeight\n );\n\n context.globalAlpha = previousGlobalAlpha;\n context.imageSmoothingEnabled = previousImageSmoothingEnabled;\n\n resetCanvasContextTransform(context);\n}\n","import { getModule } from '../../store/index.js';\nimport external from '../../externalModules.js';\nimport { getNewContext, draw, drawLines } from '../../drawing/index.js';\nimport { disableLogger } from '../../index.js';\n\nconst segmentationModule = getModule('segmentation');\n\nexport default function renderSegmentationOutline(\n evt,\n labelmap3D,\n labelmap2D,\n labelmapIndex,\n isActiveLabelMap\n) {\n const { configuration } = segmentationModule;\n const outline = getOutline(\n evt,\n labelmap3D,\n labelmap2D,\n configuration.outlineWidth\n );\n\n renderOutline(evt, outline, labelmap3D.colorLUTIndex, isActiveLabelMap);\n}\n\n/**\n * RenderOutline - Renders the outlines of segments to the canvas.\n *\n * @param {Object} evt The cornerstone event.\n * @param {Object} outline The outline to render.\n * @param {number} colorLUTIndex The index of the colorLUT.\n * @param {number} isActiveLabelMap Whether the labelmap is active.\n * @returns {null}\n */\nexport function renderOutline(\n evt,\n outline,\n colorLUTIndex,\n isActiveLabelMap = true\n) {\n const { configuration, state } = segmentationModule;\n const eventData = evt.detail;\n const { element, canvasContext } = eventData;\n\n const lineWidth = configuration.outlineWidth || 1;\n\n const context = getNewContext(canvasContext.canvas);\n const colorLutTable = state.colorLutTables[colorLUTIndex];\n\n const previousAlpha = context.globalAlpha;\n\n context.globalAlpha = isActiveLabelMap\n ? configuration.outlineAlpha\n : configuration.outlineAlphaInactive;\n\n // Draw outlines.\n draw(context, context => {\n for (let i = 1; i < outline.length; i++) {\n if (outline[i]) {\n const color = colorLutTable[i];\n\n drawLines(\n context,\n element,\n outline[i],\n {\n color: `rgba(${color[0]}, ${color[1]}, ${color[2]}, 1.0 )`,\n lineWidth,\n },\n 'canvas'\n );\n }\n }\n });\n\n context.globalAlpha = previousAlpha;\n}\n\n/**\n * GetOutline - Returns an object containing all the line segments to be\n * drawn the canvas.\n *\n * @param {Object} evt The cornerstone event.\n * @param {Labelmap3D} labelmap3D The 3D labelmap.\n * @param {Labelmap2D} labelmap2D The 2D labelmap for this current image.\n * @param {number} lineWidth The width of the outline in canvas pixels.\n *\n * @returns {Object[][]} An array of arrays of lines for each segment.\n */\nexport function getOutline(evt, labelmap3D, labelmap2D, lineWidth) {\n const eventData = evt.detail;\n const { element, image, viewport } = eventData;\n const cols = image.width;\n const rows = image.height;\n\n lineWidth = lineWidth || 1;\n\n const { segmentsHidden } = labelmap3D;\n\n const pixelData = labelmap2D.pixelData;\n const activeSegmentIndex = labelmap3D.activeSegmentIndex;\n const lineSegments = [];\n\n labelmap2D.segmentsOnLabelmap.forEach(segmentIndex => {\n const visible = !segmentsHidden[segmentIndex];\n\n if (visible) {\n lineSegments[segmentIndex] = [];\n }\n });\n\n if (!lineSegments[activeSegmentIndex]) {\n lineSegments[activeSegmentIndex] = [];\n }\n\n const _getPixelCoordinateFromPixelIndex = pixelIndex => ({\n x: pixelIndex % cols,\n y: Math.floor(pixelIndex / cols),\n });\n\n const offset = getOutlineOffset(viewport, lineWidth);\n\n for (let i = 0; i < pixelData.length; i++) {\n const segmentIndex = pixelData[i];\n\n if (segmentIndex === 0) {\n continue;\n }\n\n const visible = !segmentsHidden[segmentIndex];\n\n if (!visible) {\n continue;\n }\n\n const coord = _getPixelCoordinateFromPixelIndex(i);\n const pixels = _getPixelIndiciesAroundPixel(coord, rows, cols);\n\n // Check pixel above\n if (pixels.top === undefined || pixelData[pixels.top] !== segmentIndex) {\n _addTopOutline(lineSegments[segmentIndex], element, coord, offset);\n }\n\n // Check pixel below\n if (\n pixels.bottom === undefined ||\n pixelData[pixels.bottom] !== segmentIndex\n ) {\n _addBottomOutline(lineSegments[segmentIndex], element, coord, offset);\n }\n\n // Check pixel to the left\n if (pixels.left === undefined || pixelData[pixels.left] !== segmentIndex) {\n _addLeftOutline(lineSegments[segmentIndex], element, coord, offset);\n }\n\n // Check pixel to the right\n if (\n pixels.right === undefined ||\n pixelData[pixels.right] !== segmentIndex\n ) {\n _addRightOutline(lineSegments[segmentIndex], element, coord, offset);\n }\n\n // Top left corner\n if (\n pixels.topLeft !== undefined &&\n pixelData[pixels.topLeft] !== segmentIndex &&\n pixelData[pixels.top] === segmentIndex &&\n pixelData[pixels.left] === segmentIndex\n ) {\n _addTopLeftCorner(lineSegments[segmentIndex], element, coord, offset);\n }\n\n // Top right corner\n if (\n pixels.topRight !== undefined &&\n pixelData[pixels.topRight] !== segmentIndex &&\n pixelData[pixels.top] === segmentIndex &&\n pixelData[pixels.right] === segmentIndex\n ) {\n _addTopRightCorner(lineSegments[segmentIndex], element, coord, offset);\n }\n\n // Bottom left corner\n if (\n pixels.bottomLeft !== undefined &&\n pixelData[pixels.bottomLeft] !== segmentIndex &&\n pixelData[pixels.bottom] === segmentIndex &&\n pixelData[pixels.left] === segmentIndex\n ) {\n _addBottomLeftCorner(lineSegments[segmentIndex], element, coord, offset);\n }\n\n // Bottom right corner\n if (\n pixels.bottomRight !== undefined &&\n pixelData[pixels.bottomRight] !== segmentIndex &&\n pixelData[pixels.bottom] === segmentIndex &&\n pixelData[pixels.right] === segmentIndex\n ) {\n _addBottomRightCorner(lineSegments[segmentIndex], element, coord, offset);\n }\n }\n\n return lineSegments;\n}\n\n/**\n * GetOutlineOffset - Returns the outline offset (half line width) in the\n * i (column) and j (row) pixel directions in the viewport's rotated frame.\n * @param {Object} viewport The cornerstone viewport.\n * @param {number} lineWidth The width of the outline.\n * @returns {Object} Two vectors in the i and j pixel directions, with magnitude\n * lineWidth / 2\n */\nfunction getOutlineOffset(viewport, lineWidth) {\n const halfLineWidth = lineWidth / 2;\n let theta = viewport.rotation;\n\n theta *= Math.PI / 180;\n\n const cosTheta = Math.cos(theta);\n const sinTheta = Math.sin(theta);\n\n const unitVectorI = [cosTheta, sinTheta];\n const unitVectorJ = [-sinTheta, cosTheta];\n\n const i = {\n x: halfLineWidth * unitVectorI[0],\n y: halfLineWidth * unitVectorI[1],\n };\n\n const j = {\n x: halfLineWidth * unitVectorJ[0],\n y: halfLineWidth * unitVectorJ[1],\n };\n\n if (viewport.hflip) {\n i.x *= -1;\n i.y *= -1;\n }\n\n if (viewport.vflip) {\n j.x *= -1;\n j.y *= -1;\n }\n\n return {\n i,\n j,\n };\n}\n\n/**\n * _getPixelIndiciesAroundPixel - Returnns the coordinates for up to 8 surrounding\n * pixels, if they within the bounds of the image.\n *\n * @param {Object} coord The coordinate to check.\n * @param {number} rows The number of rows in the image.\n * @param {number} cols The number of cols in the image.\n *\n * @returns {Object} Object containing the position of adjacent pixels.\n */\nfunction _getPixelIndiciesAroundPixel(coord, rows, cols) {\n const pixelIndex = coord.y * cols + coord.x;\n const pixel = {};\n\n const hasPixelToTop = coord.y - 1 >= 0;\n const hasPixelToBotoom = coord.y + 1 < rows;\n const hasPixelToLeft = coord.x - 1 >= 0;\n const hasPixelToRight = coord.x + 1 < cols;\n\n if (hasPixelToTop) {\n pixel.top = pixelIndex - cols;\n\n if (hasPixelToRight) {\n pixel.topRight = pixel.top + 1;\n }\n\n if (hasPixelToLeft) {\n pixel.topLeft = pixel.top - 1;\n }\n }\n\n if (hasPixelToBotoom) {\n pixel.bottom = pixelIndex + cols;\n\n if (hasPixelToRight) {\n pixel.bottomRight = pixel.bottom + 1;\n }\n\n if (hasPixelToLeft) {\n pixel.bottomLeft = pixel.bottom - 1;\n }\n }\n\n if (hasPixelToLeft) {\n pixel.left = pixelIndex - 1;\n }\n\n if (hasPixelToRight) {\n pixel.right = pixelIndex + 1;\n }\n\n return pixel;\n}\n\n/**\n * _addTopLeftCorner - Adds an outline to the top left corner of the pixel.\n *\n * @param {Object[]} lineSegmentsForSegment - The list to append.\n * @param {Object} element - The Cornerstone enabled element.\n * @param {Object} coord - The pixel to add a line to.\n * @param {Object} offset - The x and y offset in the rotated frame.\n *\n * @returns {null}\n */\nfunction _addTopLeftCorner(lineSegmentsForSegment, element, coord, offset) {\n const { pixelToCanvas } = external.cornerstone;\n const start = pixelToCanvas(element, coord);\n\n start.x += offset.j.x;\n start.y += offset.j.y;\n\n const end = {\n x: start.x,\n y: start.y,\n };\n\n end.x += offset.i.x * 2;\n end.y += offset.i.y * 2;\n\n lineSegmentsForSegment.push({\n start,\n end,\n });\n}\n\n/**\n * _addTopRightCorner - Adds an outline to the top right corner of the pixel.\n *\n * @param {Object[]} lineSegmentsForSegment - The list to append.\n * @param {Object} element - The Cornerstone enabled element.\n * @param {Object} coord - The pixel to add a line to.\n * @param {Object} offset - The x and y offset in the rotated frame.\n *\n * @returns {null}\n */\nexport function _addTopRightCorner(\n lineSegmentsForSegment,\n element,\n coord,\n offset\n) {\n const { pixelToCanvas } = external.cornerstone;\n const start = pixelToCanvas(element, { x: coord.x + 1, y: coord.y });\n\n start.x += offset.j.x;\n start.y += offset.j.y;\n\n const end = {\n x: start.x,\n y: start.y,\n };\n\n end.x -= offset.i.x * 2;\n end.y -= offset.i.y * 2;\n\n lineSegmentsForSegment.push({\n start,\n end,\n });\n}\n\n/**\n * _addBottomLeftCorner - Adds an outline to the bottom left corner of the pixel.\n *\n * @param {Object[]} lineSegmentsForSegment - The list to append.\n * @param {Object} element - The Cornerstone enabled element.\n * @param {Object} coord - The pixel to add a line to.\n * @param {Object} offset - The x and y offset in the rotated frame.\n *\n * @returns {null}\n */\nfunction _addBottomLeftCorner(lineSegmentsForSegment, element, coord, offset) {\n const { pixelToCanvas } = external.cornerstone;\n const start = pixelToCanvas(element, { x: coord.x, y: coord.y + 1 });\n\n start.x -= offset.j.x;\n start.y -= offset.j.y;\n\n const end = {\n x: start.x,\n y: start.y,\n };\n\n end.x += offset.i.x * 2;\n end.y += offset.i.y * 2;\n\n lineSegmentsForSegment.push({\n start,\n end,\n });\n}\n\n/**\n * _addBottomRightCorner - Adds an outline to the bottom right corner of the pixel.\n *\n * @param {Object[]} lineSegmentsForSegment - The list to append.\n * @param {Object} element - The Cornerstone enabled element.\n * @param {Object} coord - The pixel to add a line to.\n * @param {Object} offset - The x and y offset in the rotated frame.\n *\n * @returns {null}\n */\nfunction _addBottomRightCorner(lineSegmentsForSegment, element, coord, offset) {\n const { pixelToCanvas } = external.cornerstone;\n const start = pixelToCanvas(element, { x: coord.x + 1, y: coord.y + 1 });\n\n start.x -= offset.j.x;\n start.y -= offset.j.y;\n\n const end = {\n x: start.x,\n y: start.y,\n };\n\n end.x -= offset.i.x * 2;\n end.y -= offset.i.y * 2;\n\n lineSegmentsForSegment.push({\n start,\n end,\n });\n}\n\n/**\n * _addTopOutline - adds an outline at the top of the pixel.\n *\n * @param {Object[]} lineSegmentsForSegment - The list to append.\n * @param {Object} element - The Cornerstone enabled element.\n * @param {Object} coord - The pixel to add a line to.\n * @param {number} halfLineWidth - Half the line width, to place line within the pixel.\n * @param {Object} offset - The x and y offset in the rotated frame.\n *\n * @returns {null}\n */\nfunction _addTopOutline(lineSegmentsForSegment, element, coord, offset) {\n const { pixelToCanvas } = external.cornerstone;\n const start = pixelToCanvas(element, coord);\n const end = pixelToCanvas(element, { x: coord.x + 1, y: coord.y });\n\n // Move the line in the y-direction.\n start.x += offset.j.x;\n start.y += offset.j.y;\n\n end.x += offset.j.x;\n end.y += offset.j.y;\n\n lineSegmentsForSegment.push({\n start,\n end,\n });\n}\n\n/**\n * _addBottomOutline - adds an outline at the bottom of the pixel.\n *\n * @param {Object[]} lineSegmentsForSegment - The list to append.\n * @param {Object} element - The Cornerstone enabled element.\n * @param {Object} coord - The pixel to add a line to.\n * @param {Object} offset - The x and y offset in the rotated frame.\n *\n * @returns {null}\n */\nfunction _addBottomOutline(lineSegmentsForSegment, element, coord, offset) {\n const { pixelToCanvas } = external.cornerstone;\n const start = pixelToCanvas(element, { x: coord.x, y: coord.y + 1 });\n const end = pixelToCanvas(element, { x: coord.x + 1, y: coord.y + 1 });\n\n // Move the line in the negative y-direction.\n start.x -= offset.j.x;\n start.y -= offset.j.y;\n\n end.x -= offset.j.x;\n end.y -= offset.j.y;\n\n lineSegmentsForSegment.push({\n start,\n end,\n });\n}\n\n/**\n * _addLeftOutline - adds an outline at the left side of the pixel.\n *\n * @param {Object[]} lineSegmentsForSegment - The list to append.\n * @param {Object} element - The Cornerstone enabled element.\n * @param {Object} coord - The pixel to add a line to.\n * @param {Object} offset - The x and y offset in the rotated frame.\n *\n * @returns {null}\n */\nfunction _addLeftOutline(lineSegmentsForSegment, element, coord, offset) {\n const { pixelToCanvas } = external.cornerstone;\n const start = pixelToCanvas(element, coord);\n const end = pixelToCanvas(element, { x: coord.x, y: coord.y + 1 });\n\n // Move the line in the x-direction.\n\n start.x += offset.i.x;\n start.y += offset.i.y;\n\n end.x += offset.i.x;\n end.y += offset.i.y;\n\n lineSegmentsForSegment.push({\n start,\n end,\n });\n}\n\n/**\n * _addRightOutline - adds an outline at the right side of the pixel.\n *\n * @param {Object[]} lineSegmentsForSegment - The list to append.\n * @param {Object} element - The Cornerstone enabled element.\n * @param {Object} coord - The pixel to add a line to.\n * @param {Object} offset - The x and y offset in the rotated frame.\n *\n * @returns {null}\n */\nfunction _addRightOutline(lineSegmentsForSegment, element, coord, offset) {\n const { pixelToCanvas } = external.cornerstone;\n const start = pixelToCanvas(element, { x: coord.x + 1, y: coord.y });\n const end = pixelToCanvas(element, { x: coord.x + 1, y: coord.y + 1 });\n\n // Move the line in the negative x-direction.\n\n start.x -= offset.i.x;\n start.y -= offset.i.y;\n\n end.x -= offset.i.x;\n end.y -= offset.i.y;\n\n lineSegmentsForSegment.push({\n start,\n end,\n });\n}\n","import { getModule } from '../../store/index.js';\nimport renderSegmentationFill from './renderSegmentationFill';\nimport renderSegmentationOutline from './renderSegmentationOutline';\n\nconst segmentationModule = getModule('segmentation');\n\n/**\n * Renders the segmentation based on the brush configuration and\n * the active status of the labelmap.\n * @param {Object} evt The cornerstone event.\n * @param {Labelmap3D} labelmap3D The `Labelmap3D` object.\n * @param {number} labelmapIndex The index of the active label map.\n * @param {Labelmap2D} labelmap2D The `Labelmap2D` object to render.\n * @param {boolean} isActiveLabelMap Whether or not the labelmap is active.\n * @returns {null}\n */\nexport default function renderSegmentation(\n evt,\n labelmap3D,\n labelmapIndex,\n labelmap2D,\n isActiveLabelMap\n) {\n if (shouldRenderFill(isActiveLabelMap)) {\n renderSegmentationFill(\n evt,\n labelmap3D,\n labelmap2D,\n labelmapIndex,\n isActiveLabelMap\n );\n }\n\n if (shouldRenderOutline(isActiveLabelMap)) {\n renderSegmentationOutline(\n evt,\n labelmap3D,\n labelmap2D,\n labelmapIndex,\n isActiveLabelMap\n );\n }\n}\n\n/**\n * ShouldRenderFill - Returns true if `configuration.renderFill`\n * is true , and if the global alpha is not zero.\n *\n * @param {boolean} isActiveLabelMap\n * @returns {boolean} True if the segmentation should be filled.\n */\nfunction shouldRenderFill(isActiveLabelMap) {\n const { configuration } = segmentationModule;\n\n return (\n configuration.renderFill &&\n ((isActiveLabelMap && configuration.fillAlpha !== 0) ||\n (!isActiveLabelMap && configuration.fillAlphaInactive !== 0))\n );\n}\n\n/**\n * ShouldRenderOutline - Returns true if `configuration.renderOutline`\n * is true , and if the global alpha is not zero.\n *\n * @param {boolean} isActiveLabelMap\n * @returns {boolean} True if the segmentation should be outlined.\n */\nfunction shouldRenderOutline(isActiveLabelMap) {\n const { configuration } = segmentationModule;\n\n return (\n configuration.renderOutline &&\n ((isActiveLabelMap && configuration.outlineAlpha !== 0) ||\n (!isActiveLabelMap && configuration.outlineAlphaInactive !== 0))\n );\n}\n","import { getModule } from '../store/index.js';\nimport renderSegmentation from './internals/renderSegmentation.js';\n\nconst segmentationModule = getModule('segmentation');\n\n/**\n * Finds which segmentations need to be rendered based on the configuration and\n * presence of `Labelmap2D` data on these frames.\n *\n * @param {Object} evt - The cornerstone event.\n * @returns {null}\n */\nexport default function(evt) {\n const eventData = evt.detail;\n const element = eventData.element;\n const { configuration, getters } = segmentationModule;\n\n const {\n activeLabelmapIndex,\n labelmaps3D,\n currentImageIdIndex,\n } = getters.labelmaps3D(element);\n\n if (!labelmaps3D) {\n return;\n }\n\n if (configuration.shouldRenderInactiveLabelmaps) {\n renderInactiveLabelMaps(\n evt,\n labelmaps3D,\n activeLabelmapIndex,\n currentImageIdIndex\n );\n }\n\n renderActiveLabelMap(\n evt,\n labelmaps3D,\n activeLabelmapIndex,\n currentImageIdIndex\n );\n}\n\n/**\n * RenderActiveLabelMap - Renders the `Labelmap3D` for this element if a `Labelmap2D`\n * view of the `currentImageIdIndex` exists.\n *\n * @param {Object} evt The cornerstone event.\n * @param {Labelmap3D[]} labelmaps3D An array of `Labelmap3D` objects.\n * @param {number} activeLabelmapIndex The index of the active label map.\n * @param {number} currentImageIdIndex The in-stack image position.\n * @returns {null}\n */\nfunction renderActiveLabelMap(\n evt,\n labelmaps3D,\n activeLabelmapIndex,\n currentImageIdIndex\n) {\n const labelmap3D = labelmaps3D[activeLabelmapIndex];\n\n if (!labelmap3D) {\n return;\n }\n\n const labelmap2D = labelmap3D.labelmaps2D[currentImageIdIndex];\n\n if (labelmap2D) {\n renderSegmentation(evt, labelmap3D, activeLabelmapIndex, labelmap2D, true);\n }\n}\n\n/**\n * RenderInactiveLabelMaps - Renders all the inactive `Labelmap3D`s for this element.\n *\n * @param {Object} evt The cornerstone event.\n * @param {Labelmap3D[]} labelmaps3D An array of labelmaps.\n * @param {number} activeLabelmapIndex The index of the active label map.\n * @param {number} currentImageIdIndex The in-stack image position.\n * @returns {null}\n */\nfunction renderInactiveLabelMaps(\n evt,\n labelmaps3D,\n activeLabelmapIndex,\n currentImageIdIndex\n) {\n for (let i = 0; i < labelmaps3D.length; i++) {\n const labelmap3D = labelmaps3D[i];\n\n if (i === activeLabelmapIndex || !labelmap3D) {\n continue;\n }\n\n const labelmap2D = labelmap3D.labelmaps2D[currentImageIdIndex];\n\n if (labelmap2D) {\n renderSegmentation(evt, labelmap3D, i, labelmap2D, false);\n }\n }\n}\n","import { state, getModule } from './../store/index.js';\nimport { getToolState } from '../stateManagement/toolState';\nimport onImageRenderedBrushEventHandler from '../eventListeners/onImageRenderedBrushEventHandler.js';\nimport external from './../externalModules.js';\n\nconst segmentationModule = getModule('segmentation');\n\nconst onImageRendered = function(evt) {\n const eventData = evt.detail;\n const element = eventData.element;\n\n // Render Annotation Tools\n const toolsToRender = state.tools.filter(\n tool =>\n tool.element === element &&\n (tool.mode === 'active' ||\n tool.mode === 'passive' ||\n tool.mode === 'enabled')\n );\n\n // Must be using stacks in order to use segmentation tools.\n const stackToolState = getToolState(element, 'stack');\n\n const segmentationConfiguration = segmentationModule.configuration;\n\n if (\n stackToolState &&\n (segmentationConfiguration.renderFill ||\n segmentationConfiguration.renderOutline)\n ) {\n onImageRenderedBrushEventHandler(evt);\n }\n\n toolsToRender.forEach(tool => {\n if (tool.renderToolData) {\n tool.renderToolData(evt);\n }\n });\n};\n\nconst enable = function(element) {\n element.addEventListener(\n external.cornerstone.EVENTS.IMAGE_RENDERED,\n onImageRendered\n );\n};\n\nconst disable = function(element) {\n element.removeEventListener(\n external.cornerstone.EVENTS.IMAGE_RENDERED,\n onImageRendered\n );\n};\n\nexport default {\n enable,\n disable,\n};\n","import { state } from './../../store/index.js';\nimport getActiveToolsForElement from './../../store/getActiveToolsForElement.js';\nimport filterToolsUseableWithMultiPartTools from './../../store/filterToolsUsableWithMultiPartTools.js';\n\nexport default function(handlerType, customFunction, evt) {\n if (state.isToolLocked) {\n return false;\n }\n\n // TODO: We sometimes see a null detail for TOUCH_PRESS\n const element = evt.detail.element;\n let tools = state.tools.filter(tool =>\n tool.supportedInteractionTypes.includes(handlerType)\n );\n\n // Tool is active, and specific callback is active\n tools = getActiveToolsForElement(element, tools, handlerType);\n\n // Tool has expected callback custom function\n tools = tools.filter(tool => typeof tool[customFunction] === 'function');\n\n if (state.isMultiPartToolActive) {\n tools = filterToolsUseableWithMultiPartTools(tools);\n }\n\n if (tools.length === 0) {\n return false;\n }\n\n tools[0][customFunction](evt);\n}\n","import { state } from './index.js';\nimport { getToolState } from '../stateManagement/toolState.js';\nimport getHandleNearImagePoint from '../manipulators/getHandleNearImagePoint.js';\n\n/**\n * Filters an array of tools, returning only tools with moveable handles at the\n * mouse location.\n *\n * @public\n * @function getToolsWithMoveableHandles\n *\n * @param {HTMLElement} element The element\n * @param {Object[]} tools The input tool array.\n * @param {Object} coords The coordinates of the mouse position.\n * @param {string} [interactionType=mouse]\n * @returns {Object[]} The filtered array.\n */\nexport default function(element, tools, coords, interactionType = 'mouse') {\n const proximity =\n interactionType === 'mouse' ? state.clickProximity : state.touchProximity;\n\n return tools.filter(tool => {\n const toolState = getToolState(element, tool.name);\n\n for (let i = 0; i < toolState.data.length; i++) {\n if (\n getHandleNearImagePoint(\n element,\n toolState.data[i].handles,\n coords,\n proximity\n ) !== undefined\n ) {\n return true;\n }\n }\n\n return false;\n });\n}\n","/**\n * Filters an array of tools, returning only tools which are active or passive.\n * @export\n * @public\n * @method\n * @name getInteractiveToolsForElement\n *\n * @param {HTMLElement} element The element.\n * @param {Object[]} tools The input tool array.\n * @returns {Object[]} The filtered array.\n */\nexport default function(element, tools) {\n return tools.filter(\n tool =>\n tool.element === element &&\n (tool.mode === 'active' || tool.mode === 'passive')\n );\n}\n","import { getToolState } from './../stateManagement/toolState.js';\n\n/**\n * Filters an array of tools, returning only tools which have annotation data.\n * @export\n * @public\n * @method\n * @name getToolsWithDataForElement\n *\n * @param {HTMLElement} element The element.\n * @param {Object[]} tools The input tool array.\n * @returns {Object[]} The filtered array.\n */\nexport default function(element, tools) {\n return tools.filter(tool => {\n const toolState = getToolState(element, tool.name);\n\n return toolState && toolState.data.length > 0;\n });\n}\n","// State\nimport { getters, state } from './../../store/index.js';\nimport { getToolState } from './../../stateManagement/toolState.js';\n// Util\nimport getToolsWithMoveableHandles from '../../store/getToolsWithMoveableHandles.js';\nimport { findHandleDataNearImagePoint } from '../../util/findAndMoveHelpers.js';\nimport getInteractiveToolsForElement from './../../store/getInteractiveToolsForElement.js';\nimport getToolsWithDataForElement from './../../store/getToolsWithDataForElement.js';\nimport filterToolsUseableWithMultiPartTools from './../../store/filterToolsUsableWithMultiPartTools.js';\n\n/**\n * MouseDown is called before MouseDownActivate. If MouseDown\n * finds an existing tool to interact with, it can prevent the\n * event from bubbling to MouseDownActivate.\n *\n * @private\n * @param {mousedown} evt\n * @listens {CornerstoneTools.event:cornerstonetoolsmousedown}\n * @returns {undefined}\n */\nexport default function(evt) {\n if (state.isToolLocked) {\n return;\n }\n\n const eventData = evt.detail;\n const element = evt.detail.element;\n const coords = evt.detail.currentPoints.canvas;\n\n // High level filtering\n const activeAndPassiveTools = getInteractiveToolsForElement(\n element,\n getters.mouseTools()\n );\n\n // ACTIVE TOOL W/ PRE CALLBACK?\n // Note: In theory, this should only ever be a single tool.\n let activeTools = activeAndPassiveTools.filter(\n tool =>\n tool.mode === 'active' &&\n Array.isArray(tool.options.mouseButtonMask) &&\n tool.options.mouseButtonMask.includes(eventData.buttons) &&\n tool.options.isMouseActive\n );\n\n if (state.isMultiPartToolActive) {\n activeTools = filterToolsUseableWithMultiPartTools(activeTools);\n }\n\n // If any tools are active, check if they have a special reason for dealing with the event.\n if (activeTools.length > 0) {\n // TODO: If length > 1, you could assess fitness and select the ideal tool\n // TODO: But because we're locking this to 'active' tools, that should rarely be an issue\n // Super-Meta-TODO: ^ I think we should just take the approach of one active tool per mouse button?\n const firstActiveToolWithCallback = activeTools.find(\n tool => typeof tool.preMouseDownCallback === 'function'\n );\n\n if (firstActiveToolWithCallback) {\n const consumedEvent = firstActiveToolWithCallback.preMouseDownCallback(\n evt\n );\n\n if (consumedEvent) {\n return;\n }\n }\n }\n\n if (state.isMultiPartToolActive) {\n // Don't fire events to Annotation Tools during a multi part loop.\n return;\n }\n\n // Annotation tool specific\n const annotationTools = getToolsWithDataForElement(\n element,\n activeAndPassiveTools\n );\n\n // NEAR HANDLES?\n const annotationToolsWithMoveableHandles = getToolsWithMoveableHandles(\n element,\n annotationTools,\n coords,\n 'mouse'\n );\n\n if (annotationToolsWithMoveableHandles.length > 0) {\n const firstToolWithMoveableHandles = annotationToolsWithMoveableHandles[0];\n const toolState = getToolState(element, firstToolWithMoveableHandles.name);\n\n const { handle, data } = findHandleDataNearImagePoint(\n element,\n toolState,\n firstToolWithMoveableHandles.name,\n coords\n );\n\n firstToolWithMoveableHandles.handleSelectedCallback(\n evt,\n data,\n handle,\n 'mouse'\n );\n\n return;\n }\n\n // NEAR TOOL?\n const annotationToolsWithPointNearClick = activeAndPassiveTools.filter(\n tool => {\n const toolState = getToolState(element, tool.name);\n const isNearPoint =\n toolState &&\n toolState.data &&\n tool.pointNearTool &&\n toolState.data.some(data =>\n tool.pointNearTool(element, data, coords, 'mouse')\n );\n\n return isNearPoint;\n }\n );\n\n if (annotationToolsWithPointNearClick.length > 0) {\n const firstToolNearPoint = annotationToolsWithPointNearClick[0];\n const toolState = getToolState(element, firstToolNearPoint.name);\n const firstAnnotationNearPoint = toolState.data.find(data =>\n firstToolNearPoint.pointNearTool(element, data, coords)\n );\n\n firstToolNearPoint.toolSelectedCallback(\n evt,\n firstAnnotationNearPoint,\n 'mouse'\n );\n\n return;\n }\n\n // ACTIVE TOOL W/ POST CALLBACK?\n // If any tools are active, check if they have a special reason for dealing with the event.\n if (activeTools.length > 0) {\n // TODO: If length > 1, you could assess fitness and select the ideal tool\n // TODO: But because we're locking this to 'active' tools, that should rarely be an issue\n // Super-Meta-TODO: ^ I think we should just take the approach of one active tool per mouse button?\n const firstActiveToolWithCallback = activeTools.find(\n tool => typeof tool.postMouseDownCallback === 'function'\n );\n\n if (firstActiveToolWithCallback) {\n const consumedEvent = firstActiveToolWithCallback.postMouseDownCallback(\n evt\n );\n\n if (consumedEvent) {\n return;\n }\n }\n }\n}\n","import EVENTS from '../../events.js';\nimport external from '../../externalModules.js';\nimport { addToolState } from '../../stateManagement/toolState.js';\nimport { moveHandle, moveNewHandle } from '../../manipulators/index.js';\nimport { getLogger } from '../../util/logger.js';\nimport triggerEvent from '../../util/triggerEvent.js';\n\nconst logger = getLogger('eventDispatchers:mouseEventHandlers');\n\nexport default function(evt, tool) {\n logger.log('addNewMeasurement');\n\n evt.preventDefault();\n evt.stopPropagation();\n const eventData = evt.detail;\n const element = eventData.element;\n const measurementData = tool.createNewMeasurement(eventData);\n\n if (!measurementData) {\n return;\n }\n\n // Associate this data with this imageId so we can render it and manipulate it\n addToolState(element, tool.name, measurementData);\n\n external.cornerstone.updateImage(element);\n\n const handleMover =\n Object.keys(measurementData.handles).length === 1\n ? moveHandle\n : moveNewHandle;\n\n handleMover(\n eventData,\n tool.name,\n measurementData,\n measurementData.handles.end,\n tool.options,\n 'mouse',\n () => {\n const eventType = EVENTS.MEASUREMENT_COMPLETED;\n const eventData = {\n toolName: tool.name,\n element,\n measurementData,\n };\n\n triggerEvent(element, eventType, eventData);\n }\n );\n}\n","import addNewMeasurement from './addNewMeasurement.js';\nimport { state } from './../../store/index.js';\nimport BaseAnnotationTool from './../../tools/base/BaseAnnotationTool.js';\nimport getActiveTool from '../../util/getActiveTool';\n\nexport default function(evt) {\n if (state.isToolLocked) {\n return;\n }\n\n const { element, buttons } = evt.detail;\n const activeTool = getActiveTool(element, buttons, 'mouse');\n\n if (!activeTool) {\n return;\n }\n\n if (typeof activeTool.preMouseDownActivateCallback === 'function') {\n const consumedEvent = activeTool.preMouseDownActivateCallback(evt);\n\n if (consumedEvent) {\n return;\n }\n }\n\n if (state.isMultiPartToolActive) {\n return;\n }\n\n // Note: custom `addNewMeasurement` will need to prevent event bubbling\n if (activeTool.addNewMeasurement) {\n activeTool.addNewMeasurement(evt, 'mouse');\n } else if (activeTool instanceof BaseAnnotationTool) {\n addNewMeasurement(evt, activeTool);\n }\n}\n","import { getters, state } from './../../store/index.js';\nimport getActiveToolsForElement from './../../store/getActiveToolsForElement.js';\nimport filterToolsUseableWithMultiPartTools from './../../store/filterToolsUsableWithMultiPartTools.js';\n\n// Tools like wwwc. Non-annotation tools w/ specific\n// Down + mouse behavior\n// TODO: I don't like filtering in drag because it's such\n// A high frequency event. Anything we can do to reduce\n// Repeat math here would be a big help\nexport default function(evt) {\n if (state.isToolLocked) {\n return;\n }\n\n let tools;\n const eventData = evt.detail;\n const element = eventData.element;\n\n // Filter out disabled, enabled, and passive\n tools = getActiveToolsForElement(element, getters.mouseTools());\n tools = tools.filter(\n tool =>\n Array.isArray(tool.options.mouseButtonMask) &&\n tool.options.mouseButtonMask.includes(eventData.buttons) &&\n tool.options.isMouseActive\n );\n tools = tools.filter(tool => typeof tool.mouseDragCallback === 'function');\n\n if (state.isMultiPartToolActive) {\n tools = filterToolsUseableWithMultiPartTools(tools);\n }\n\n if (tools.length === 0) {\n return;\n }\n\n const activeTool = tools[0];\n\n activeTool.mouseDragCallback(evt);\n}\n","import external from './../../externalModules.js';\n// State\nimport { getters, state } from './../../store/index.js';\nimport getInteractiveToolsForElement from './../../store/getInteractiveToolsForElement.js';\nimport getToolsWithDataForElement from './../../store/getToolsWithDataForElement.js';\n\n/**\n * This is mostly used to update the [un]hover state\n * of a tool.\n *\n * @private\n * @param {*} evt\n * @returns {void}\n */\nexport default function(evt) {\n if (state.isToolLocked || state.isMultiPartToolActive) {\n return;\n }\n\n let tools;\n const { element, currentPoints } = evt.detail;\n\n // Set the mouse position incase any tool needs it.\n state.mousePositionImage = currentPoints.image;\n\n // TODO: instead of filtering these for every interaction, we can change our\n // TODO: State's structure to always know these values.\n // Filter out disabled and enabled\n tools = getInteractiveToolsForElement(element, getters.mouseTools());\n\n const activeTools = tools.filter(\n tool => tool.mode === 'active' && tool.options.isMouseActive\n );\n\n let imageNeedsUpdate = false;\n\n // If any tools are active, check if they have a canvas cursor, and if so update image.\n if (activeTools.length > 0) {\n imageNeedsUpdate = activeTools.some(tool => tool.updateOnMouseMove);\n }\n\n tools = getToolsWithDataForElement(element, tools);\n\n // Iterate over each tool, and each tool's data\n // Activate any handles we're hovering over, or whole tools if we're near the tool\n // If we've changed the state of anything, redrawn the image\n\n for (let t = 0; t < tools.length; t++) {\n const tool = tools[t];\n\n if (typeof tool.mouseMoveCallback === 'function') {\n imageNeedsUpdate = tool.mouseMoveCallback(evt) || imageNeedsUpdate;\n }\n }\n\n // Tool data activation status changed, redraw the image\n if (imageNeedsUpdate === true) {\n external.cornerstone.updateImage(element);\n }\n}\n","import customCallbackHandler from './../shared/customCallbackHandler.js';\nimport mouseDown from './mouseDown.js';\nimport mouseDownActivate from './mouseDownActivate.js';\nimport mouseDrag from './mouseDrag.js';\nimport mouseMove from './mouseMove.js';\n\nconst mouseClick = customCallbackHandler.bind(\n null,\n 'Mouse',\n 'mouseClickCallback'\n);\n\nconst mouseDoubleClick = customCallbackHandler.bind(\n null,\n 'Mouse',\n 'doubleClickCallback'\n);\n\nconst mouseUp = customCallbackHandler.bind(null, 'Mouse', 'mouseUpCallback');\n\nconst mouseWheel = customCallbackHandler.bind(\n null,\n 'MouseWheel',\n 'mouseWheelCallback'\n);\n\nexport {\n mouseClick,\n mouseDown,\n mouseDownActivate,\n mouseDoubleClick,\n mouseDrag,\n mouseMove,\n mouseUp,\n mouseWheel,\n};\n","import EVENTS from './../events.js';\nimport {\n mouseClick,\n mouseDown,\n mouseDownActivate,\n mouseDoubleClick,\n mouseDrag,\n mouseMove,\n mouseUp,\n mouseWheel,\n} from './mouseEventHandlers/index.js';\n\n/**\n * These listeners are emitted in order, and can be cancelled/prevented from bubbling\n * by any previous event.\n * - mouseMove: used to update the [un]hover state of a tool (highlighting)\n * - mouseDown: check to see if we are close to an existing annotation, grab it\n * - mouseDownActivate: createNewMeasurement (usually)\n * - mouseDrag: update measurement or apply strategy (wwwc)\n * - mouseDoubleClick: usually a one-time apply specialty action\n * - onImageRendered: redraw visible tool data\n * @private\n * @param {*} element\n * @returns {undefined}\n */\nconst enable = function(element) {\n element.addEventListener(EVENTS.MOUSE_CLICK, mouseClick);\n element.addEventListener(EVENTS.MOUSE_DOWN, mouseDown);\n element.addEventListener(EVENTS.MOUSE_DOWN_ACTIVATE, mouseDownActivate);\n element.addEventListener(EVENTS.MOUSE_DOUBLE_CLICK, mouseDoubleClick);\n element.addEventListener(EVENTS.MOUSE_DRAG, mouseDrag);\n element.addEventListener(EVENTS.MOUSE_MOVE, mouseMove);\n element.addEventListener(EVENTS.MOUSE_UP, mouseUp);\n element.addEventListener(EVENTS.MOUSE_WHEEL, mouseWheel);\n};\n\nconst disable = function(element) {\n element.removeEventListener(EVENTS.MOUSE_CLICK, mouseClick);\n element.removeEventListener(EVENTS.MOUSE_DOWN, mouseDown);\n element.removeEventListener(EVENTS.MOUSE_DOWN_ACTIVATE, mouseDownActivate);\n element.removeEventListener(EVENTS.MOUSE_DOUBLE_CLICK, mouseDoubleClick);\n element.removeEventListener(EVENTS.MOUSE_DRAG, mouseDrag);\n element.removeEventListener(EVENTS.MOUSE_MOVE, mouseMove);\n element.removeEventListener(EVENTS.MOUSE_UP, mouseUp);\n element.removeEventListener(EVENTS.MOUSE_WHEEL, mouseWheel);\n};\n\nexport default {\n enable,\n disable,\n};\n","import { state } from './../store/index.js';\nimport external from './../externalModules.js';\n\nconst onNewImage = function(evt) {\n if (state.isToolLocked) {\n return false;\n }\n\n const element = evt.detail.element;\n\n const tools = state.tools.filter(\n tool =>\n tool.element === element &&\n (tool.mode === 'active' ||\n tool.mode === 'passive' ||\n tool.mode === 'enabled')\n );\n\n if (tools.length === 0) {\n return false;\n }\n\n tools.forEach(tool => {\n if (tool.newImageCallback) {\n tool.newImageCallback(evt);\n }\n });\n};\n\nconst enable = function(element) {\n element.addEventListener(external.cornerstone.EVENTS.NEW_IMAGE, onNewImage);\n};\n\nconst disable = function(element) {\n element.removeEventListener(\n external.cornerstone.EVENTS.NEW_IMAGE,\n onNewImage\n );\n};\n\nexport default {\n enable,\n disable,\n};\n","import { state } from '../../store/index.js';\nimport getActiveToolsForElement from '../../store/getActiveToolsForElement.js';\nimport filterToolsUseableWithMultiPartTools from './../../store/filterToolsUsableWithMultiPartTools.js';\n\nexport default function(evt) {\n if (state.isToolLocked) {\n return false;\n }\n\n // TODO: We sometimes see a null detail for TOUCH_PRESS\n const { element, numPointers } = evt.detail;\n let tools = state.tools.filter(tool =>\n tool.supportedInteractionTypes.includes('MultiTouch')\n );\n\n // Tool is active, and specific callback is active\n tools = getActiveToolsForElement(element, tools, 'MultiTouch');\n // Tool has expected callback custom function\n tools = tools.filter(\n tool =>\n typeof tool.multiTouchDragCallback === 'function' &&\n numPointers === tool.configuration.touchPointers\n );\n\n if (state.isMultiPartToolActive) {\n tools = filterToolsUseableWithMultiPartTools(tools);\n }\n\n if (tools.length === 0) {\n return false;\n }\n\n const activeTool = tools[0];\n\n activeTool.multiTouchDragCallback(evt);\n}\n","import EVENTS from '../../events.js';\nimport external from '../../externalModules.js';\nimport { state } from '../../store/index.js';\nimport anyHandlesOutsideImage from './../../manipulators/anyHandlesOutsideImage.js';\nimport { moveNewHandle } from '../../manipulators/index.js';\nimport {\n addToolState,\n removeToolState,\n} from '../../stateManagement/toolState.js';\nimport triggerEvent from '../../util/triggerEvent.js';\nimport { getLogger } from '../../util/logger.js';\n\nconst logger = getLogger('eventDispatchers:touchEventHandlers');\n\nexport default function(evt, tool) {\n logger.log('addNewMeasurement');\n\n evt.preventDefault();\n evt.stopPropagation();\n\n const touchEventData = evt.detail;\n const element = touchEventData.element;\n const measurementData = tool.createNewMeasurement(touchEventData);\n\n if (!measurementData) {\n return;\n }\n\n addToolState(element, tool.name, measurementData);\n\n // Todo: Looks like we're handling the \"up\" of the tap?\n if (\n Object.keys(measurementData.handles).length === 1 &&\n touchEventData.type === EVENTS.TAP\n ) {\n // Todo: bold assumptions about measurement data for all tools?\n measurementData.active = false;\n measurementData.handles.end.active = false;\n measurementData.handles.end.highlight = false;\n measurementData.invalidated = true;\n\n const deleteIfHandleOutsideImage =\n state.deleteIfHandleOutsideImage ||\n tool.options.deleteIfHandleOutsideImage;\n\n if (\n deleteIfHandleOutsideImage &&\n anyHandlesOutsideImage(touchEventData, measurementData.handles)\n ) {\n // Delete the measurement\n removeToolState(element, tool.name, measurementData);\n }\n\n external.cornerstone.updateImage(element);\n\n return;\n }\n\n external.cornerstone.updateImage(element);\n\n moveNewHandle(\n touchEventData,\n tool.name,\n measurementData,\n measurementData.handles.end,\n tool.options,\n 'touch',\n () => {\n const eventType = EVENTS.MEASUREMENT_COMPLETED;\n const eventData = {\n toolName: tool.name,\n element,\n measurementData,\n };\n\n triggerEvent(element, eventType, eventData);\n }\n );\n}\n","// State\nimport { state } from './../../store/index.js';\nimport addNewMeasurement from './addNewMeasurement.js';\nimport BaseAnnotationTool from './../../tools/base/BaseAnnotationTool.js';\nimport getActiveTool from '../../util/getActiveTool';\n\nexport default function(evt) {\n if (state.isToolLocked || state.isMultiPartToolActive) {\n return;\n }\n\n const element = evt.detail.element;\n const activeTool = getActiveTool(element, null, 'touch');\n\n // Note: custom `addNewMeasurement` will need to prevent event bubbling\n if (activeTool && activeTool.addNewMeasurement) {\n activeTool.addNewMeasurement(evt, 'touch');\n } else if (activeTool instanceof BaseAnnotationTool) {\n addNewMeasurement(evt, activeTool);\n }\n}\n","export default function(toolData) {\n if (!toolData) {\n return;\n }\n\n for (let i = 0; i < toolData.data.length; i++) {\n const data = toolData.data[i];\n\n data.active = false;\n if (!data.handles) {\n continue;\n }\n\n deactivateAllHandles(data.handles);\n }\n}\n\nfunction deactivateAllHandles(handles) {\n Object.keys(handles).forEach(function(name) {\n const handle = handles[name];\n\n handle.active = false;\n });\n}\n","import external from '../../externalModules.js';\nimport touchStartActive from './touchStartActive.js';\n// State\nimport { getters, state } from '../../store/index.js';\nimport getActiveToolsForElement from '../../store/getActiveToolsForElement.js';\nimport getToolsWithDataForElement from '../../store/getToolsWithDataForElement.js';\nimport { getToolState } from '../../stateManagement/toolState.js';\n//\nimport getHandleNearImagePoint from '../../manipulators/getHandleNearImagePoint.js';\nimport { moveHandle, moveAllHandles } from '../../manipulators/index.js';\n//\nimport deactivateAllToolInstances from './shared/deactivateAllToolInstances.js';\n\nexport default function(evt) {\n if (state.isToolLocked || state.isMultiPartToolActive) {\n return;\n }\n\n let tools;\n const distanceFromHandle = 28;\n const element = evt.detail.element;\n const coords = evt.detail.currentPoints.canvas;\n\n tools = getActiveToolsForElement(element, getters.touchTools());\n tools = getToolsWithDataForElement(element, tools);\n\n // Deactivate everything\n // DeactivateAllToolInstances(toolData);\n\n // Find all tools w/ handles that we are near\n const toolsWithMoveableHandles = tools.filter(tool => {\n const toolState = getToolState(element, tool.name);\n\n for (let i = 0; i < toolState.data.length; i++) {\n if (\n getHandleNearImagePoint(\n element,\n toolState.data[i].handles,\n coords,\n distanceFromHandle\n ) !== undefined\n ) {\n return true;\n }\n }\n\n return false;\n });\n\n // TODO: More than one? Which one was moved most recently?\n // We'll just grab the first one we encounter for now\n if (toolsWithMoveableHandles.length > 0) {\n // Todo: ignore: touch_start, tap\n\n const firstToolWithMoveableHandles = toolsWithMoveableHandles[0];\n const toolState = getToolState(element, firstToolWithMoveableHandles.name);\n const moveableHandle = toolState.data.find(\n d =>\n getHandleNearImagePoint(\n element,\n d.handles,\n coords,\n distanceFromHandle\n ) !== undefined\n );\n\n toolState.data.active = true;\n moveableHandle.active = true; // Why here, but not touchStart?\n external.cornerstone.updateImage(element);\n\n moveHandle(\n evt.detail,\n firstToolWithMoveableHandles.name,\n toolState.data,\n moveableHandle,\n firstToolWithMoveableHandles.options,\n 'touch',\n () => deactivateAllToolInstances(toolState)\n );\n evt.stopImmediatePropagation();\n evt.preventDefault();\n // Why no stopPropagation?\n\n return;\n }\n\n // Find all tools near our point\n const toolsNearPoint = tools.filter(tool => {\n const toolState = getToolState(element, tool.name);\n const isNearPoint =\n toolState &&\n toolState.data &&\n tool.pointNearTool &&\n toolState.data.some(data => tool.pointNearTool(element, data, coords));\n\n return isNearPoint;\n });\n\n // TODO: More than one? Which one was moved most recently?\n // We'll just grab the first one we encounter for now\n if (toolsNearPoint.length > 0) {\n // Todo: Ignore: TAP, START, PRESS\n const firstToolNearPoint = toolsNearPoint[0];\n const toolState = getToolState(element, firstToolNearPoint.name);\n const firstAnnotationNearPoint = toolState.data.find(data =>\n firstToolNearPoint.pointNearTool(element, data, coords)\n );\n\n // Todo: ignore: touch_start, tap\n firstAnnotationNearPoint.active = true;\n external.cornerstone.updateImage(element);\n\n moveAllHandles(\n evt.detail,\n firstToolNearPoint.name,\n firstAnnotationNearPoint,\n null,\n firstToolNearPoint.options,\n 'touch',\n () => deactivateAllToolInstances(toolState)\n );\n\n evt.stopImmediatePropagation();\n evt.preventDefault();\n // TODO: Why no stop propagation?\n\n return;\n }\n\n // If there is nothing to move, add a new instance of the tool\n // Need to check here to see if activation is allowed!\n // TODO: What would this be? First active tool?\n // Or should _always_ pass through to our larger event handler that checks\n // All tools anyway?\n const allActiveTools = getActiveToolsForElement(\n element,\n getters.touchTools()\n );\n\n if (allActiveTools.length > 0 && allActiveTools[0].touchStartActiveCallback) {\n allActiveTools[0].touchStartActiveCallback(evt);\n } else {\n touchStartActive(evt);\n }\n\n return false;\n}\n","// State\nimport { getters, state } from '../../store/index.js';\nimport { findHandleDataNearImagePoint } from '../../util/findAndMoveHelpers.js';\nimport getToolsWithMoveableHandles from '../../store/getToolsWithMoveableHandles.js';\nimport { getToolState } from './../../stateManagement/toolState.js';\nimport getInteractiveToolsForElement from './../../store/getInteractiveToolsForElement.js';\nimport getToolsWithDataForElement from './../../store/getToolsWithDataForElement.js';\nimport filterToolsUseableWithMultiPartTools from './../../store/filterToolsUsableWithMultiPartTools.js';\n\nexport default function(evt) {\n if (state.isToolLocked) {\n return;\n }\n\n const eventData = evt.detail;\n const element = eventData.element;\n const coords = eventData.startPoints.canvas;\n\n const activeAndPassiveTools = getInteractiveToolsForElement(\n element,\n getters.touchTools()\n );\n\n let activeTools = activeAndPassiveTools.filter(\n tool => tool.mode === 'active' && tool.options.isTouchActive\n );\n\n if (state.isMultiPartToolActive) {\n activeTools = filterToolsUseableWithMultiPartTools(activeTools);\n }\n\n // If any tools are active, check if they have a special reason for dealing with the event.\n if (activeTools.length > 0) {\n // TODO: If length > 1, you could assess fitness and select the ideal tool\n // TODO: But because we're locking this to 'active' tools, that should rarely be an issue\n // Super-Meta-TODO: ^ I think we should just take the approach of one active tool per mouse button?\n const firstActiveToolWithCallback = activeTools.find(\n tool => typeof tool.preTouchStartCallback === 'function'\n );\n\n if (firstActiveToolWithCallback) {\n const consumedEvent = firstActiveToolWithCallback.preTouchStartCallback(\n evt\n );\n\n if (consumedEvent) {\n return;\n }\n }\n }\n\n if (state.isMultiPartToolActive) {\n return;\n }\n\n const annotationTools = getToolsWithDataForElement(\n element,\n activeAndPassiveTools\n );\n\n // NEAR HANDLES?\n const annotationToolsWithMoveableHandles = getToolsWithMoveableHandles(\n element,\n annotationTools,\n coords,\n 'touch'\n );\n\n // TODO: More than one? Which one was moved most recently?\n // We'll just grab the first one we encounter for now\n if (annotationToolsWithMoveableHandles.length > 0) {\n // Todo: Ignore TAP, START, PRESS\n\n const firstToolWithMoveableHandles = annotationToolsWithMoveableHandles[0];\n const toolState = getToolState(element, firstToolWithMoveableHandles.name);\n\n const { handle, data } = findHandleDataNearImagePoint(\n element,\n toolState,\n firstToolWithMoveableHandles.name,\n coords,\n 'touch'\n );\n\n firstToolWithMoveableHandles.handleSelectedCallback(\n evt,\n data,\n handle,\n 'touch'\n );\n\n return;\n }\n\n // NEAR POINT?\n const annotationToolsWithPointNearTouch = annotationTools.filter(tool => {\n const toolState = getToolState(element, tool.name);\n const isNearPoint =\n toolState &&\n toolState.data &&\n tool.pointNearTool &&\n toolState.data.some(data =>\n tool.pointNearTool(element, data, coords, 'touch')\n );\n\n return isNearPoint;\n });\n\n // TODO: More than one? Which one was moved most recently?\n // We'll just grab the first one we encounter for now\n if (annotationToolsWithPointNearTouch.length > 0) {\n // Todo: Ignore: TAP, START, PRESS\n const firstToolNearPoint = annotationToolsWithPointNearTouch[0];\n const toolState = getToolState(element, firstToolNearPoint.name);\n const firstAnnotationNearPoint = toolState.data.find(data =>\n firstToolNearPoint.pointNearTool(element, data, coords)\n );\n\n firstToolNearPoint.toolSelectedCallback(\n evt,\n firstAnnotationNearPoint,\n 'touch'\n );\n\n return;\n }\n\n // If any tools are active, check if they have a special reason for dealing with the event.\n if (activeTools.length > 0) {\n // TODO: If length > 1, you could assess fitness and select the ideal tool\n // TODO: But because we're locking this to 'active' tools, that should rarely be an issue\n // Super-Meta-TODO: ^ I think we should just take the approach of one active tool per mouse button?\n const firstActiveToolWithCallback = activeTools.find(\n tool => typeof tool.postTouchStartCallback === 'function'\n );\n\n if (firstActiveToolWithCallback) {\n const consumedEvent = firstActiveToolWithCallback.postTouchStartCallback(\n evt\n );\n\n if (consumedEvent) {\n return;\n }\n }\n }\n}\n","import customCallbackHandler from './../shared/customCallbackHandler.js';\nimport multiTouchDrag from './multiTouchDrag.js';\nimport tap from './tap.js';\nimport touchStart from './touchStart.js';\nimport touchStartActive from './touchStartActive.js';\n\nconst doubleTap = customCallbackHandler.bind(\n null,\n 'DoubleTap',\n 'doubleTapCallback'\n);\n// TODO: some touchDrag tools don't want to fire on touchStart\n// TODO: Drag tools have an option `fireOnTouchStart` used to filter\n// TODO: Them out of TOUCH_START handler\nconst touchDrag = customCallbackHandler.bind(\n null,\n 'Touch',\n 'touchDragCallback'\n);\nconst touchEnd = customCallbackHandler.bind(null, 'Touch', 'touchEndCallback');\nconst touchPinch = customCallbackHandler.bind(\n null,\n 'TouchPinch',\n 'touchPinchCallback'\n);\nconst touchPress = customCallbackHandler.bind(\n null,\n 'Touch',\n 'touchPressCallback'\n);\nconst touchRotate = customCallbackHandler.bind(\n null,\n 'TouchRotate',\n 'touchRotateCallback'\n);\n\nexport {\n doubleTap,\n multiTouchDrag,\n tap,\n touchDrag,\n touchEnd,\n touchPinch,\n touchPress,\n touchRotate,\n touchStart,\n touchStartActive,\n};\n","import EVENTS from '../events.js';\nimport {\n tap,\n doubleTap,\n multiTouchDrag,\n touchStart,\n touchStartActive,\n touchRotate,\n touchDrag,\n touchEnd,\n touchPress,\n touchPinch,\n} from './touchEventHandlers/index.js';\n\n/**\n * These listeners are emitted in order, and can be cancelled/prevented from bubbling\n * by any previous event.\n * - tap:\n * - touchStart: check to see if we are close to an existing annotation, grab it\n * - touchDrag:\n * - touchStartActive: createNewMeasurement (usually)\n * - touchPress:\n * - touchRotate:\n * - doubleTap: usually a one-time apply specialty action\n * - touchPinch:\n * - onImageRendered: redraw visible tool data\n * @private\n * @param {*} element\n * @returns {void}\n */\nconst enable = function(element) {\n element.addEventListener(EVENTS.TAP, tap);\n element.addEventListener(EVENTS.TOUCH_START, touchStart, { passive: false });\n element.addEventListener(EVENTS.TOUCH_DRAG, touchDrag, { passive: false });\n element.addEventListener(EVENTS.TOUCH_END, touchEnd);\n // Mouse equivelant is `mouse_down_activate`\n // Should the naming pattern here match?\n element.addEventListener(EVENTS.TOUCH_START_ACTIVE, touchStartActive);\n element.addEventListener(EVENTS.TOUCH_PRESS, touchPress);\n element.addEventListener(EVENTS.DOUBLE_TAP, doubleTap);\n element.addEventListener(EVENTS.TOUCH_PINCH, touchPinch);\n element.addEventListener(EVENTS.TOUCH_ROTATE, touchRotate);\n element.addEventListener(EVENTS.MULTI_TOUCH_DRAG, multiTouchDrag);\n};\n\nconst disable = function(element) {\n element.removeEventListener(EVENTS.TAP, tap);\n element.removeEventListener(EVENTS.TOUCH_START, touchStart);\n element.removeEventListener(EVENTS.TOUCH_DRAG, touchDrag);\n element.removeEventListener(EVENTS.TOUCH_END, touchEnd);\n // Mouse equivelant is `mouse_down_activate`\n // Should the naming pattern here match?\n element.removeEventListener(EVENTS.TOUCH_START_ACTIVE, touchStartActive);\n element.removeEventListener(EVENTS.TOUCH_PRESS, touchPress);\n element.removeEventListener(EVENTS.DOUBLE_TAP, doubleTap);\n element.removeEventListener(EVENTS.TOUCH_PINCH, touchPinch);\n element.removeEventListener(EVENTS.TOUCH_ROTATE, touchRotate);\n element.removeEventListener(EVENTS.MULTI_TOUCH_DRAG, multiTouchDrag);\n};\n\nexport default {\n enable,\n disable,\n};\n","import store, { getModule } from './index.js';\nimport getToolForElement from './getToolForElement.js';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('addTool');\n\n/**\n * Adds a tool to an enabled element.\n *\n * @public\n * @function addToolForElement\n * @memberof CornerstoneTools\n *\n * @param {HTMLElement} element The element to add the tool to.\n * @param {BaseTool} ApiTool The tool to add to the element.\n * @param {Object} [props] Override the default tool props\n * @returns {undefined}\n */\nconst addToolForElement = function(element, ApiTool, props) {\n // Instantiating the tool here makes it harder to accidentally add\n // The same tool (by reference) for multiple elements (which would reassign the tool\n // To a new element).\n const tool = new ApiTool(props);\n const toolAlreadyAddedToElement = getToolForElement(element, tool.name);\n\n if (toolAlreadyAddedToElement) {\n logger.warn('%s has already been added to the target element', tool.name);\n\n return;\n }\n\n tool.element = element;\n store.state.tools.push(tool);\n};\n\n/**\n * Adds a tool to all enabled element.\n *\n * @public\n * @function addTool\n * @memberof CornerstoneTools\n *\n * @param {BaseTool} ApiTool The tool to add to each element.\n * @param {Object} [props] Override the default tool configuration\n * @returns {undefined}\n */\nconst addTool = function(ApiTool, props) {\n _addToolGlobally(ApiTool, props);\n store.state.enabledElements.forEach(element => {\n addToolForElement(element, ApiTool, props);\n });\n};\n\n/**\n * Adds tool with matching name from globally registered tools.\n * Requires `globalToolSyncEnabled` to be set to true\n *\n * @private\n * @function addToolGlobally\n *\n * @param {BaseTool} ApiTool\n * @param {Object} [props] Override the default tool configuration\n * @returns {undefined}\n */\nconst _addToolGlobally = function(ApiTool, props) {\n const { configuration } = getModule('globalConfiguration');\n\n if (!configuration.globalToolSyncEnabled) {\n return;\n }\n\n const tool = new ApiTool(props);\n const toolAlreadyAddedGlobally =\n store.state.globalTools[tool.name] !== undefined;\n\n if (toolAlreadyAddedGlobally) {\n logger.warn('%s has already been added globally', tool.name);\n\n return;\n }\n\n store.state.globalTools[tool.name] = {\n tool: ApiTool,\n props,\n activeBindings: [],\n };\n};\n\nexport { addTool, addToolForElement };\n","import {\n mouseEventListeners,\n wheelEventListener,\n touchEventListeners,\n} from '../../eventListeners/index.js';\nimport {\n imageRenderedEventDispatcher,\n mouseToolEventDispatcher,\n newImageEventDispatcher,\n touchToolEventDispatcher,\n} from '../../eventDispatchers/index.js';\nimport { addToolForElement } from './../addTool.js';\nimport {\n setToolActiveForElement,\n setToolPassiveForElement,\n setToolEnabledForElement,\n setToolDisabledForElement,\n} from './../setToolMode.js';\nimport store, { getModule } from '../index.js';\nimport { getLogger } from '../../util/logger.js';\n\nconst logger = getLogger('internals:addEnabledElement');\n\n/**\n * Element Enabled event.\n *\n * @event Cornerstone#ElementEnabled\n * @type {Object}\n * @property {string} type\n * @property {Object} detail\n * @property {HTMLElement} detail.element - The element being enabled.\n */\n\n/* TODO: It would be nice if this automatically added \"all tools\"\n * To the enabledElement that already exist on all other tools.\n * A half-measure might be a new method to \"duplicate\" the tool\n * Configuration for an existing enabled element\n * We may need to also save/store the original class/constructor per tool\n * To accomplish this\n */\n/**\n * Adds an enabledElement to our store.\n * @export\n * @private\n * @method\n * @name addEnabledElement\n * @param {Cornerstone#ElementEnabled} elementEnabledEvt\n * @listens Cornerstone#ElementEnabled\n * @returns {void}\n */\nexport default function(elementEnabledEvt) {\n logger.log('EVENT:ELEMENT_ENABLED');\n const enabledElement = elementEnabledEvt.detail.element;\n\n // Dispatchers\n imageRenderedEventDispatcher.enable(enabledElement);\n newImageEventDispatcher.enable(enabledElement);\n\n const { configuration } = getModule('globalConfiguration');\n\n // Mouse\n if (configuration.mouseEnabled) {\n mouseEventListeners.enable(enabledElement);\n wheelEventListener.enable(enabledElement);\n mouseToolEventDispatcher.enable(enabledElement);\n }\n\n // Touch\n if (configuration.touchEnabled) {\n touchEventListeners.enable(enabledElement);\n touchToolEventDispatcher.enable(enabledElement);\n }\n\n // State\n _addEnabledElement(enabledElement);\n}\n\n/**\n * Adds the enabled element to the store.\n * @private\n * @method\n * @param {HTMLElement} enabledElement\n * @returns {void}\n */\nconst _addEnabledElement = function(enabledElement) {\n store.state.enabledElements.push(enabledElement);\n if (store.modules) {\n _initModulesOnElement(enabledElement);\n }\n _addGlobalToolsToElement(enabledElement);\n _repeatGlobalToolHistory(enabledElement);\n};\n\n/**\n * Iterate over our store's modules. If the module has an `enabledElementCallback`\n * call it and pass it a reference to our enabled element.\n * @private\n * @method\n * @param {Object} enabledElement\n * @returns {void}\n */\nfunction _initModulesOnElement(enabledElement) {\n const modules = store.modules;\n\n Object.keys(modules).forEach(function(key) {\n if (typeof modules[key].enabledElementCallback === 'function') {\n modules[key].enabledElementCallback(enabledElement);\n }\n });\n}\n\n/**\n * Iterate over our stores globalTools adding each one to `enabledElement`\n * @private\n * @method\n * @param {HTMLElement} enabledElement\n * @returns {void}\n */\nfunction _addGlobalToolsToElement(enabledElement) {\n const { configuration } = getModule('globalConfiguration');\n\n if (!configuration.globalToolSyncEnabled) {\n return;\n }\n\n Object.keys(store.state.globalTools).forEach(function(key) {\n const { tool, props } = store.state.globalTools[key];\n\n addToolForElement(enabledElement, tool, props);\n });\n}\n\n/**\n * Iterate over the globalToolChangeHistory and apply each `historyEvent`\n * to the supplied `enabledElement`.\n * @private\n * @method\n * @param {HTMLElement} enabledElement\n * @returns {void}\n */\nfunction _repeatGlobalToolHistory(enabledElement) {\n const { configuration } = getModule('globalConfiguration');\n\n if (!configuration.globalToolSyncEnabled) {\n return;\n }\n\n const setToolModeFns = {\n active: setToolActiveForElement,\n passive: setToolPassiveForElement,\n enabled: setToolEnabledForElement,\n disabled: setToolDisabledForElement,\n };\n\n store.state.globalToolChangeHistory.forEach(historyEvent => {\n const args = historyEvent.args.slice(0);\n\n args.unshift(enabledElement);\n setToolModeFns[historyEvent.mode].apply(null, args);\n });\n}\n","import {\n mouseEventListeners,\n wheelEventListener,\n touchEventListeners,\n} from '../../eventListeners/index.js';\nimport {\n imageRenderedEventDispatcher,\n mouseToolEventDispatcher,\n newImageEventDispatcher,\n touchToolEventDispatcher,\n} from '../../eventDispatchers/index.js';\nimport store, { getModule } from '../index.js';\nimport { getLogger } from '../../util/logger.js';\nimport loadHandlerManager from '../../stateManagement/loadHandlerManager.js';\n\nconst logger = getLogger('internals:removeEnabledElement');\n\n/**\n * Element Disabled event.\n *\n * @event Cornerstone#ElementDisabled\n * @type {Object}\n * @property {string} type\n * @property {Object} detail\n * @property {HTMLElement} detail.element - The element being disabled.\n */\n\n/**\n * Removes an enabledElement from our store, and all associated tools that were added to it.\n * @export\n * @private\n * @method\n * @name removeEnabledElement\n * @param {Cornerstone#ElementDisabled} elementDisabledEvt\n * @listens Cornerstone#ElementDisabled\n * @returns {void}\n */\nexport default function(elementDisabledEvt) {\n logger.log('EVENT:ELEMENT_DISABLED');\n const enabledElement = elementDisabledEvt.detail.element;\n const { configuration } = getModule('globalConfiguration');\n\n // Dispatchers\n imageRenderedEventDispatcher.disable(enabledElement);\n newImageEventDispatcher.disable(enabledElement);\n\n // Mouse\n if (configuration.mouseEnabled) {\n mouseEventListeners.disable(enabledElement);\n wheelEventListener.disable(enabledElement);\n mouseToolEventDispatcher.disable(enabledElement);\n }\n\n // Touch\n if (configuration.touchEnabled) {\n touchEventListeners.disable(enabledElement);\n touchToolEventDispatcher.disable(enabledElement);\n }\n\n // State\n _removeAllToolsForElement(enabledElement);\n _removeEnabledElement(enabledElement);\n _removeLoadHandlers(enabledElement);\n}\n\n/**\n * Remove all tools associated with enabled element.\n * @private\n * @method\n * @param {HTMLElement} enabledElement\n * @returns {void}\n */\nconst _removeAllToolsForElement = function(enabledElement) {\n // Note: We may want to `setToolDisabled` before removing from store\n // Or take other action to remove any lingering eventListeners/state\n store.state.tools = store.state.tools.filter(\n tool => tool.element !== enabledElement\n );\n};\n\n/**\n * Remove the enabled element from the store if it exists.\n * @private\n * @method\n * @param {HTMLElement} enabledElement\n * @returns {void}\n */\nconst _removeEnabledElement = function(enabledElement) {\n if (store.modules) {\n _cleanModulesOnElement(enabledElement);\n }\n\n const foundElementIndex = store.state.enabledElements.findIndex(\n element => element === enabledElement\n );\n\n if (foundElementIndex > -1) {\n store.state.enabledElements.splice(foundElementIndex, 1);\n } else {\n logger.warn('unable to remove element');\n }\n};\n\n/**\n * Remove load handler for the element\n * @private\n * @method\n * @param {HTMLElement} element\n * @returns {void}\n */\nconst _removeLoadHandlers = function(element) {\n loadHandlerManager.removeHandlers(element);\n};\n\n/**\n * Iterate over our store's modules. If the module has a\n * `removeEnabledElementCallback` call it and clean up unneeded metadata.\n * @private\n * @method\n * @param {Object} enabledElement\n * @returns {void}\n */\nfunction _cleanModulesOnElement(enabledElement) {\n const modules = store.modules;\n\n Object.keys(modules).forEach(function(key) {\n if (typeof modules[key].removeEnabledElementCallback === 'function') {\n modules[key].removeEnabledElementCallback(enabledElement);\n }\n });\n}\n","import { state } from './../store/index.js';\nimport external from './../externalModules.js';\n\nconst enable = function() {\n disable(); // Clean up any lingering listeners\n window.addEventListener('resize', resizeThrottler, false);\n};\n\nconst disable = function() {\n window.removeEventListener('resize', resizeThrottler, false);\n};\n\nlet resizeTimeout;\n\nfunction resizeThrottler() {\n // Ignore resize events as long as an actualResizeHandler execution is in the queue\n if (!resizeTimeout) {\n resizeTimeout = setTimeout(function() {\n resizeTimeout = null;\n forceEnabledElementResize();\n\n // The actualResizeHandler will execute at a rate of 15fps\n }, 66);\n }\n}\n\nexport const forceEnabledElementResize = function() {\n state.enabledElements.forEach(element => {\n external.cornerstone.resize(element);\n });\n};\n\nexport default {\n enable,\n disable,\n};\n","import external from './externalModules.js';\nimport store, { getModule } from './store/index.js';\nimport addEnabledElement from './store/internals/addEnabledElement.js';\nimport removeEnabledElement from './store/internals/removeEnabledElement.js';\nimport windowResizeHandler from './eventListeners/windowResizeHandler.js';\n\n/**\n * Merges the provided configuration with default values and returns a\n * configured CornerstoneTools instance.\n * @export\n * @public\n * @method\n * @name init\n *\n * @param {Object|Object[]} [defaultConfiguration = {}] The configuration to apply. Assumed globalConfiguration\n * only one value, otherwise moduleName, configuration entires in an array.\n * @returns {Object} A configured CornerstoneTools instance with top level API members.\n */\nexport default function(defaultConfiguration = {}) {\n _addCornerstoneEventListeners();\n _initModules();\n\n const globalConfigurationModule = getModule('globalConfiguration');\n\n if (Array.isArray(defaultConfiguration)) {\n defaultConfiguration.forEach(configurationEntry => {\n const { moduleName, configuration } = configurationEntry;\n\n const module = getModule(moduleName);\n\n if (module) {\n module.configuration = Object.assign(\n {},\n module.configuration,\n configuration\n );\n }\n });\n } else {\n // defaultConfiguration is an object, default to assigning it to globalConfiguration.\n globalConfigurationModule.configuration = Object.assign(\n {},\n globalConfigurationModule.configuration,\n defaultConfiguration\n );\n }\n\n if (globalConfigurationModule.configuration.autoResizeViewports) {\n windowResizeHandler.enable();\n }\n}\n\n/**\n * Wires up event listeners for the Cornerstone#ElementDisabled and\n * Cornerstone#ElementEnabled events.\n * @private\n * @method\n * @returns {void}\n */\nfunction _addCornerstoneEventListeners() {\n // Clear any listeners that may already be set\n _removeCornerstoneEventListeners();\n\n const cornerstone = external.cornerstone;\n const elementEnabledEvent = cornerstone.EVENTS.ELEMENT_ENABLED;\n const elementDisabledEvent = cornerstone.EVENTS.ELEMENT_DISABLED;\n\n cornerstone.events.addEventListener(elementEnabledEvent, addEnabledElement);\n cornerstone.events.addEventListener(\n elementDisabledEvent,\n removeEnabledElement\n );\n}\n\n/**\n * Removes event listeners for the Cornerstone#ElementDisabled and\n * Cornerstone#ElementEnabled events.\n * @private\n * @method\n * @returns {void}\n */\nfunction _removeCornerstoneEventListeners() {\n const cornerstone = external.cornerstone;\n const elementEnabledEvent = cornerstone.EVENTS.ELEMENT_ENABLED;\n const elementDisabledEvent = cornerstone.EVENTS.ELEMENT_DISABLED;\n\n cornerstone.events.removeEventListener(\n elementEnabledEvent,\n addEnabledElement\n );\n cornerstone.events.removeEventListener(\n elementDisabledEvent,\n removeEnabledElement\n );\n}\n\n/*\n * TODO: This could cause issues if the module was already initialized for\n * the store. As there's nothing stopping implementers from calling `init`\n * multiple times. Modules should self-check if they have already been\n * registered to prevent issues.\n */\n\n/**\n * Iterate over our store's modules. If the module has an `onRegisterCallback`\n * call it. This hook can be used to setup any global store requirements per\n * module.\n * @private\n * @method\n * @returns {void}\n */\nfunction _initModules() {\n const modules = store.modules;\n\n Object.keys(modules).forEach(function(key) {\n if (typeof modules[key].onRegisterCallback === 'function') {\n modules[key].onRegisterCallback();\n }\n });\n}\n","import external from './../externalModules.js';\nimport requestPoolManager from '../requestPool/requestPoolManager.js';\nimport loadHandlerManager from '../stateManagement/loadHandlerManager.js';\nimport { addToolState, getToolState } from '../stateManagement/toolState.js';\nimport { setMaxSimultaneousRequests } from '../util/getMaxSimultaneousRequests.js';\nimport { getLogger } from '../util/logger.js';\nimport triggerEvent from '../util/triggerEvent';\nimport EVENTS from '../events.js';\n\nconst logger = getLogger('stackTools:stackPrefetch');\n\nconst toolType = 'stackPrefetch';\nconst requestType = 'prefetch';\n\nlet configuration = {\n maxImagesToPrefetch: Infinity,\n preserveExistingPool: false,\n};\n\nlet resetPrefetchTimeout;\nconst resetPrefetchDelay = 10;\n\nfunction range(lowEnd, highEnd) {\n // Javascript version of Python's range function\n // http://stackoverflow.com/questions/3895478/does-javascript-have-a-method-like-range-to-generate-an-array-based-on-suppl\n lowEnd = Math.round(lowEnd) || 0;\n highEnd = Math.round(highEnd) || 0;\n\n const arr = [];\n let c = highEnd - lowEnd + 1;\n\n if (c <= 0) {\n return arr;\n }\n\n while (c--) {\n arr[c] = highEnd--;\n }\n\n return arr;\n}\n\nconst max = function(arr) {\n return Math.max.apply(null, arr);\n};\n\nconst min = function(arr) {\n return Math.min.apply(null, arr);\n};\n\nfunction nearestIndex(arr, x) {\n // Return index of nearest values in array\n // http://stackoverflow.com/questions/25854212/return-index-of-nearest-values-in-an-array\n const l = [];\n const h = [];\n\n arr.forEach(function(v) {\n if (v < x) {\n l.push(v);\n } else if (v > x) {\n h.push(v);\n }\n });\n\n return {\n low: arr.indexOf(max(l)),\n high: arr.indexOf(min(h)),\n };\n}\n\nfunction prefetch(element) {\n // Check to make sure stack data exists\n const stackData = getToolState(element, 'stack');\n\n if (!stackData || !stackData.data || !stackData.data.length) {\n return;\n }\n\n const stack = stackData.data[0];\n\n // Get the stackPrefetch tool data\n const stackPrefetchData = getToolState(element, toolType);\n\n if (!stackPrefetchData) {\n return;\n }\n\n const stackPrefetch = stackPrefetchData.data[0] || {};\n\n // If all the requests are complete, disable the stackPrefetch tool\n if (\n !stackPrefetch.indicesToRequest ||\n !stackPrefetch.indicesToRequest.length\n ) {\n stackPrefetch.enabled = false;\n }\n\n // Make sure the tool is still enabled\n if (stackPrefetch.enabled === false) {\n return;\n }\n\n // Remove an imageIdIndex from the list of indices to request\n // This fires when the individual image loading deferred is resolved\n function removeFromList(imageIdIndex) {\n const index = stackPrefetch.indicesToRequest.indexOf(imageIdIndex);\n\n if (index > -1) {\n // Don't remove last element if imageIdIndex not found\n stackPrefetch.indicesToRequest.splice(index, 1);\n }\n }\n\n // Remove all already cached images from the\n // IndicesToRequest array\n stackPrefetchData.data[0].indicesToRequest.sort((a, b) => a - b);\n const indicesToRequestCopy = stackPrefetch.indicesToRequest.slice();\n\n indicesToRequestCopy.forEach(function(imageIdIndex) {\n const imageId = stack.imageIds[imageIdIndex];\n\n if (!imageId) {\n return;\n }\n\n const imageLoadObject = external.cornerstone.imageCache.getImageLoadObject(\n imageId\n );\n\n if (imageLoadObject) {\n removeFromList(imageIdIndex);\n }\n });\n\n // Stop here if there are no images left to request\n // After those in the cache have been removed\n if (!stackPrefetch.indicesToRequest.length) {\n return;\n }\n\n // Clear the requestPool of prefetch requests, if needed.\n if (!configuration.preserveExistingPool) {\n requestPoolManager.clearRequestStack(requestType);\n }\n\n // Identify the nearest imageIdIndex to the currentImageIdIndex\n const nearest = nearestIndex(\n stackPrefetch.indicesToRequest,\n stack.currentImageIdIndex\n );\n\n let imageId;\n let nextImageIdIndex;\n const preventCache = false;\n\n function doneCallback(image) {\n logger.log('prefetch done: %s', image.imageId);\n const imageIdIndex = stack.imageIds.indexOf(image.imageId);\n\n removeFromList(imageIdIndex);\n\n triggerEvent(element, EVENTS.STACK_PREFETCH_IMAGE_LOADED, {\n element,\n imageId: image.imageId,\n imageIndex: imageIdIndex,\n stackPrefetch,\n stack,\n });\n\n // If there are no more images to fetch\n if (\n !(\n stackPrefetch.indicesToRequest &&\n stackPrefetch.indicesToRequest.length > 0\n )\n ) {\n triggerEvent(element, EVENTS.STACK_PREFETCH_DONE, {\n element,\n stackPrefetch,\n stack,\n });\n }\n }\n\n // Retrieve the errorLoadingHandler if one exists\n const errorLoadingHandler = loadHandlerManager.getErrorLoadingHandler(\n element\n );\n\n function failCallback(error) {\n logger.log('prefetch errored: %o', error);\n if (errorLoadingHandler) {\n errorLoadingHandler(element, imageId, error, 'stackPrefetch');\n }\n }\n\n // Prefetch images around the current image (before and after)\n let lowerIndex = nearest.low;\n let higherIndex = nearest.high;\n const imageIdsToPrefetch = [];\n\n while (\n lowerIndex >= 0 ||\n higherIndex < stackPrefetch.indicesToRequest.length\n ) {\n const currentIndex = stack.currentImageIdIndex;\n const shouldSkipLower =\n currentIndex - stackPrefetch.indicesToRequest[lowerIndex] >\n configuration.maxImagesToPrefetch;\n const shouldSkipHigher =\n stackPrefetch.indicesToRequest[higherIndex] - currentIndex >\n configuration.maxImagesToPrefetch;\n\n const shouldLoadLower = !shouldSkipLower && lowerIndex >= 0;\n const shouldLoadHigher =\n !shouldSkipHigher && higherIndex < stackPrefetch.indicesToRequest.length;\n\n if (!shouldLoadHigher && !shouldLoadLower) {\n break;\n }\n\n if (shouldLoadLower) {\n nextImageIdIndex = stackPrefetch.indicesToRequest[lowerIndex--];\n imageId = stack.imageIds[nextImageIdIndex];\n imageIdsToPrefetch.push(imageId);\n }\n\n if (shouldLoadHigher) {\n nextImageIdIndex = stackPrefetch.indicesToRequest[higherIndex++];\n imageId = stack.imageIds[nextImageIdIndex];\n imageIdsToPrefetch.push(imageId);\n }\n }\n // Load images in reverse order, by adding them at the beginning of the pool.\n for (const imageToLoad of imageIdsToPrefetch.reverse()) {\n requestPoolManager.addRequest(\n element,\n imageToLoad,\n requestType,\n preventCache,\n doneCallback,\n failCallback,\n true\n );\n }\n\n // Try to start the requestPool's grabbing procedure\n // In case it isn't already running\n requestPoolManager.startGrabbing();\n}\n\nfunction getPromiseRemovedHandler(element) {\n return function(e) {\n const eventData = e.detail;\n\n // When an imagePromise has been pushed out of the cache, re-add its index\n // It to the indicesToRequest list so that it will be retrieved later if the\n // CurrentImageIdIndex is changed to an image nearby\n let stackData;\n\n try {\n // It will throw an exception in some cases (eg: thumbnails)\n stackData = getToolState(element, 'stack');\n } catch (error) {\n return;\n }\n\n if (!stackData || !stackData.data || !stackData.data.length) {\n return;\n }\n\n const stack = stackData.data[0];\n const imageIdIndex = stack.imageIds.indexOf(eventData.imageId);\n\n // Make sure the image that was removed is actually in this stack\n // Before adding it to the indicesToRequest array\n if (imageIdIndex < 0) {\n return;\n }\n\n const stackPrefetchData = getToolState(element, toolType);\n\n if (\n !stackPrefetchData ||\n !stackPrefetchData.data ||\n !stackPrefetchData.data.length\n ) {\n return;\n }\n\n stackPrefetchData.data[0].indicesToRequest.push(imageIdIndex);\n };\n}\n\nfunction onImageUpdated(e) {\n // Start prefetching again (after a delay)\n // When the user has scrolled to a new image\n clearTimeout(resetPrefetchTimeout);\n resetPrefetchTimeout = setTimeout(function() {\n const element = e.target;\n\n // If playClip is enabled and the user loads a different series in the viewport\n // An exception will be thrown because the element will not be enabled anymore\n try {\n prefetch(element);\n } catch (error) {\n return;\n }\n }, resetPrefetchDelay);\n}\n\nfunction enable(element) {\n // Clear old prefetch data. Skipping this can cause problems when changing the series inside an element\n const stackPrefetchDataArray = getToolState(element, toolType);\n\n stackPrefetchDataArray.data = [];\n\n // First check that there is stack data available\n const stackData = getToolState(element, 'stack');\n\n if (!stackData || !stackData.data || !stackData.data.length) {\n return;\n }\n\n const stack = stackData.data[0];\n\n // Check if we are allowed to cache images in this stack\n if (stack.preventCache === true) {\n logger.warn(\n 'A stack that should not be cached was given the stackPrefetch'\n );\n\n return;\n }\n\n // Use the currentImageIdIndex from the stack as the initalImageIdIndex\n const stackPrefetchData = {\n indicesToRequest: range(0, stack.imageIds.length - 1),\n enabled: true,\n direction: 1,\n };\n\n // Remove the currentImageIdIndex from the list to request\n const indexOfCurrentImage = stackPrefetchData.indicesToRequest.indexOf(\n stack.currentImageIdIndex\n );\n\n stackPrefetchData.indicesToRequest.splice(indexOfCurrentImage, 1);\n\n addToolState(element, toolType, stackPrefetchData);\n\n prefetch(element);\n\n element.removeEventListener(\n external.cornerstone.EVENTS.NEW_IMAGE,\n onImageUpdated\n );\n element.addEventListener(\n external.cornerstone.EVENTS.NEW_IMAGE,\n onImageUpdated\n );\n\n const promiseRemovedHandler = getPromiseRemovedHandler(element);\n\n external.cornerstone.events.removeEventListener(\n external.cornerstone.EVENTS.IMAGE_CACHE_PROMISE_REMOVED,\n promiseRemovedHandler\n );\n external.cornerstone.events.addEventListener(\n external.cornerstone.EVENTS.IMAGE_CACHE_PROMISE_REMOVED,\n promiseRemovedHandler\n );\n}\n\nfunction disable(element) {\n clearTimeout(resetPrefetchTimeout);\n element.removeEventListener(\n external.cornerstone.EVENTS.NEW_IMAGE,\n onImageUpdated\n );\n\n const promiseRemovedHandler = getPromiseRemovedHandler(element);\n\n external.cornerstone.events.removeEventListener(\n external.cornerstone.EVENTS.IMAGE_CACHE_PROMISE_REMOVED,\n promiseRemovedHandler\n );\n\n const stackPrefetchData = getToolState(element, toolType);\n // If there is actually something to disable, disable it\n\n if (stackPrefetchData && stackPrefetchData.data.length) {\n stackPrefetchData.data[0].enabled = false;\n\n // Clear current prefetch requests from the requestPool\n requestPoolManager.clearRequestStack(requestType);\n }\n}\n\nfunction getConfiguration() {\n return configuration;\n}\n\nfunction setConfiguration(config) {\n configuration = config;\n\n if (config.maxSimultaneousRequests) {\n setMaxSimultaneousRequests(config.maxSimultaneousRequests);\n }\n}\n\n// Module/private exports\nconst stackPrefetch = {\n enable,\n disable,\n getConfiguration,\n setConfiguration,\n};\n\nexport default stackPrefetch;\n","import external from '../externalModules.js';\nimport { getToolState } from '../stateManagement/toolState.js';\n\nexport default class FusionRenderer {\n constructor() {\n this.currentImageIdIndex = 0;\n this.layerIds = [];\n this.findImageFn = undefined;\n }\n\n render(element, imageStacks) {\n // Move this to base Renderer class\n if (!Number.isInteger(this.currentImageIdIndex)) {\n throw new Error(\n 'FusionRenderer: render - Image ID Index is not an integer'\n );\n }\n\n if (!this.findImageFn) {\n throw new Error('No findImage function has been defined');\n }\n\n if (!imageStacks) {\n const toolData = getToolState(element, 'stack');\n\n imageStacks = toolData.data;\n }\n // TODO: Figure out what to do with LoadHandlers in this scenario...\n\n const cornerstone = external.cornerstone;\n\n // For the base layer, go to the currentImageIdIndex\n const baseImageObject = imageStacks[0];\n const currentImageId = baseImageObject.imageIds[this.currentImageIdIndex];\n const overlayImageStacks = imageStacks.slice(1, imageStacks.length);\n\n cornerstone.loadAndCacheImage(currentImageId).then(baseImage => {\n let baseLayerId = this.layerIds[0];\n\n // Get the base layer if one exists\n if (baseLayerId) {\n cornerstone.setLayerImage(element, baseImage, baseLayerId);\n } else {\n // Otherwise, create a new layer with the base layer's image\n baseLayerId = cornerstone.addLayer(\n element,\n baseImage,\n baseImageObject.options\n );\n this.layerIds.push(baseLayerId);\n }\n\n // Display the image immediately while the overlay images are identified\n cornerstone.displayImage(element, baseImage);\n\n // Loop through the remaining 'overlay' image stacks\n overlayImageStacks.forEach((imgObj, overlayLayerIndex) => {\n const imageId = this.findImageFn(imgObj.imageIds, currentImageId);\n const layerIndex = overlayLayerIndex + 1;\n let currentLayerId = this.layerIds[layerIndex];\n\n // If no layer exists yet for this overlaid stack, create\n // One and add it to the layerIds property for this instance\n // Of the fusion renderer.\n if (!currentLayerId) {\n currentLayerId = cornerstone.addLayer(\n element,\n undefined,\n imgObj.options\n );\n this.layerIds.push(currentLayerId);\n }\n\n if (imageId) {\n // If an imageId was returned from the findImage function,\n // Load it, make sure it's visible and update the layer\n // With the new image object.\n cornerstone.loadAndCacheImage(imageId).then(image => {\n cornerstone.setLayerImage(element, image, currentLayerId);\n cornerstone.updateImage(element);\n });\n } else {\n // If no imageId was returned from the findImage function.\n // This means that there is no relevant image to display.\n cornerstone.setLayerImage(element, undefined, currentLayerId);\n cornerstone.setActiveLayer(element, baseLayerId);\n cornerstone.updateImage(element);\n }\n });\n });\n }\n}\n","import FusionRenderer from './fusionRenderer.js';\n\nconst stackRenderers = {};\n\nstackRenderers.FusionRenderer = FusionRenderer;\n\nexport default stackRenderers;\n","import EVENTS from '../events.js';\nimport external from '../externalModules.js';\nimport loadHandlerManager from '../stateManagement/loadHandlerManager.js';\nimport { addToolState, getToolState } from '../stateManagement/toolState.js';\nimport triggerEvent from '../util/triggerEvent.js';\n\nconst toolType = 'playClip';\n\n/**\n * [private] Turns a Frame Time Vector (0018,1065) array into a normalized array of timeouts. Each element\n * ... of the resulting array represents the amount of time each frame will remain on the screen.\n * @param {Array} vector A Frame Time Vector (0018,1065) as specified in section C.7.6.5.1.2 of DICOM standard.\n * @param {Number} speed A speed factor which will be applied to each element of the resulting array.\n * @returns {Array} An array with timeouts for each animation frame.\n */\nfunction getPlayClipTimeouts(vector, speed) {\n let i;\n let sample;\n let delay;\n let sum = 0;\n const limit = vector.length;\n const timeouts = [];\n\n // Initialize time varying to false\n timeouts.isTimeVarying = false;\n\n if (typeof speed !== 'number' || speed <= 0) {\n speed = 1;\n }\n\n // First element of a frame time vector must be discarded\n for (i = 1; i < limit; i++) {\n // eslint-disable-next-line no-bitwise\n delay = (Number(vector[i]) / speed) | 0; // Integral part only\n timeouts.push(delay);\n if (i === 1) {\n // Use first item as a sample for comparison\n sample = delay;\n } else if (delay !== sample) {\n timeouts.isTimeVarying = true;\n }\n\n sum += delay;\n }\n\n if (timeouts.length > 0) {\n if (timeouts.isTimeVarying) {\n // If it's a time varying vector, make the last item an average...\n // eslint-disable-next-line no-bitwise\n delay = (sum / timeouts.length) | 0;\n } else {\n delay = timeouts[0];\n }\n\n timeouts.push(delay);\n }\n\n return timeouts;\n}\n\n/**\n * [private] Performs the heavy lifting of stopping an ongoing animation.\n * @param {Object} playClipData The data from playClip that needs to be stopped.\n * @returns {void}\n */\nfunction stopClipWithData(playClipData) {\n const id = playClipData.intervalId;\n\n if (typeof id !== 'undefined') {\n playClipData.intervalId = undefined;\n if (playClipData.usingFrameTimeVector) {\n clearTimeout(id);\n } else {\n clearInterval(id);\n }\n }\n}\n\n/**\n * [private] Trigger playClip tool stop event.\n * @param {HTMLElement} element\n * @returns {void}\n */\nfunction triggerStopEvent(element) {\n const eventDetail = {\n element,\n };\n\n triggerEvent(element, EVENTS.CLIP_STOPPED, eventDetail);\n}\n\n/**\n * Starts playing a clip or adjusts the frame rate of an already playing clip. framesPerSecond is\n * optional and defaults to 30 if not specified. A negative framesPerSecond will play the clip in reverse.\n * The element must be a stack of images\n * @param {HTMLElement} element\n * @param {number} framesPerSecond\n * @returns {void}\n */\nfunction playClip(element, framesPerSecond) {\n let playClipData;\n let playClipTimeouts;\n\n if (element === undefined) {\n throw new Error('playClip: element must not be undefined');\n }\n\n const stackToolData = getToolState(element, 'stack');\n\n if (!stackToolData || !stackToolData.data || !stackToolData.data.length) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n // If we have more than one stack, check if we have a stack renderer defined\n let stackRenderer;\n\n if (stackToolData.data.length > 1) {\n const stackRendererData = getToolState(element, 'stackRenderer');\n\n if (\n stackRendererData &&\n stackRendererData.data &&\n stackRendererData.data.length\n ) {\n stackRenderer = stackRendererData.data[0];\n }\n }\n\n const stackData = stackToolData.data[0];\n\n const playClipToolData = getToolState(element, toolType);\n\n if (\n !playClipToolData ||\n !playClipToolData.data ||\n !playClipToolData.data.length\n ) {\n playClipData = {\n intervalId: undefined,\n framesPerSecond: 30,\n lastFrameTimeStamp: undefined,\n frameRate: 0,\n frameTimeVector: undefined,\n ignoreFrameTimeVector: false,\n usingFrameTimeVector: false,\n speed: 1,\n reverse: false,\n loop: true,\n };\n addToolState(element, toolType, playClipData);\n } else {\n playClipData = playClipToolData.data[0];\n // Make sure the specified clip is not running before any property update\n stopClipWithData(playClipData);\n }\n\n // If a framesPerSecond is specified and is valid, update the playClipData now\n if (framesPerSecond < 0 || framesPerSecond > 0) {\n playClipData.framesPerSecond = Number(framesPerSecond);\n playClipData.reverse = playClipData.framesPerSecond < 0;\n // If framesPerSecond is given, frameTimeVector will be ignored...\n playClipData.ignoreFrameTimeVector = true;\n }\n\n // Determine if frame time vector should be used instead of a fixed frame rate...\n if (\n playClipData.ignoreFrameTimeVector !== true &&\n playClipData.frameTimeVector &&\n playClipData.frameTimeVector.length === stackData.imageIds.length\n ) {\n playClipTimeouts = getPlayClipTimeouts(\n playClipData.frameTimeVector,\n playClipData.speed\n );\n }\n\n // This function encapsulates the frame rendering logic...\n const playClipAction = () => {\n // Hoisting of context variables\n let loader,\n startLoadingHandler,\n endLoadingHandler,\n errorLoadingHandler,\n newImageIdIndex = stackData.currentImageIdIndex;\n\n const imageCount = stackData.imageIds.length;\n\n if (playClipData.reverse) {\n newImageIdIndex--;\n } else {\n newImageIdIndex++;\n }\n\n if (\n !playClipData.loop &&\n (newImageIdIndex < 0 || newImageIdIndex >= imageCount)\n ) {\n stopClipWithData(playClipData);\n triggerStopEvent(element);\n\n return;\n }\n\n // Loop around if we go outside the stack\n if (newImageIdIndex >= imageCount) {\n newImageIdIndex = 0;\n }\n\n if (newImageIdIndex < 0) {\n newImageIdIndex = imageCount - 1;\n }\n\n if (newImageIdIndex !== stackData.currentImageIdIndex) {\n startLoadingHandler = loadHandlerManager.getStartLoadHandler(element);\n endLoadingHandler = loadHandlerManager.getEndLoadHandler(element);\n errorLoadingHandler = loadHandlerManager.getErrorLoadingHandler(element);\n\n if (startLoadingHandler) {\n startLoadingHandler(element);\n }\n\n if (stackData.preventCache === true) {\n loader = cornerstone.loadImage(stackData.imageIds[newImageIdIndex]);\n } else {\n loader = cornerstone.loadAndCacheImage(\n stackData.imageIds[newImageIdIndex]\n );\n }\n\n loader.then(\n function(image) {\n try {\n stackData.currentImageIdIndex = newImageIdIndex;\n if (stackRenderer) {\n stackRenderer.currentImageIdIndex = newImageIdIndex;\n stackRenderer.render(element, stackToolData.data);\n } else {\n cornerstone.displayImage(element, image);\n }\n if (endLoadingHandler) {\n endLoadingHandler(element, image);\n }\n } catch (error) {\n return;\n }\n },\n function(error) {\n const imageId = stackData.imageIds[newImageIdIndex];\n\n if (errorLoadingHandler) {\n errorLoadingHandler(element, imageId, error);\n }\n }\n );\n }\n };\n\n // If playClipTimeouts array is available, not empty and its elements are NOT uniform ...\n // ... (at least one timeout is different from the others), use alternate setTimeout implementation\n if (\n playClipTimeouts &&\n playClipTimeouts.length > 0 &&\n playClipTimeouts.isTimeVarying\n ) {\n playClipData.usingFrameTimeVector = true;\n playClipData.intervalId = setTimeout(function playClipTimeoutHandler() {\n playClipData.intervalId = setTimeout(\n playClipTimeoutHandler,\n playClipTimeouts[stackData.currentImageIdIndex]\n );\n playClipAction();\n }, 0);\n } else {\n // ... otherwise user setInterval implementation which is much more efficient.\n playClipData.usingFrameTimeVector = false;\n playClipData.intervalId = setInterval(\n playClipAction,\n 1000 / Math.abs(playClipData.framesPerSecond)\n );\n }\n}\n\n/**\n * Stops an already playing clip.\n * @param {HTMLElement} element\n * @returns {void}\n */\nfunction stopClip(element) {\n const playClipToolData = getToolState(element, toolType);\n\n if (\n !playClipToolData ||\n !playClipToolData.data ||\n !playClipToolData.data.length\n ) {\n return;\n }\n\n stopClipWithData(playClipToolData.data[0]);\n}\n\nexport { playClip, stopClip };\n","import store, { getModule } from './index.js';\n\n/**\n * Deactivates and removes the tool from the target element with the provided name\n *\n * @export\n * @public\n * @method\n * @name removeToolForElement\n * @param {HTMLElement} element The element.\n * @param {string} toolName The name of the tool.\n * @returns {void}\n */\nconst removeToolForElement = function(element, toolName) {\n const toolIndex = store.state.tools.findIndex(\n tool => tool.element === element && tool.name === toolName\n );\n\n if (toolIndex >= 0) {\n store.state.tools.splice(toolIndex, 1);\n }\n};\n\n/**\n * Removes all tools from all enabled elements with the provided name.\n *\n * @export\n * @public\n * @method\n * @name removeTool\n * @param {string} toolName The name of the tool.\n * @returns {void}\n */\nconst removeTool = function(toolName) {\n _removeToolGlobally(toolName);\n store.state.enabledElements.forEach(element => {\n removeToolForElement(element, toolName);\n });\n};\n\n/**\n * Removes tool with matching name from globally registered tools.\n * Requires `globalToolSyncEnabled` to be set to true\n *\n * @private\n * @method\n * @name removeToolGlobally\n * @param {string} toolName The name of the tool to remove.\n * @returns {void}\n */\nconst _removeToolGlobally = function(toolName) {\n const { configuration } = getModule('globalConfiguration');\n\n if (!configuration.globalToolSyncEnabled) {\n return;\n }\n\n if (store.state.globalTools[toolName]) {\n delete store.state.globalTools[toolName];\n }\n};\n\nexport { removeTool, removeToolForElement };\n","import getToolForElement from './getToolForElement.js';\nimport { state } from './index.js';\n\n/**\n * Sets the options of a tool on a specific element.\n * @export\n * @public\n * @method\n * @name setToolOptionsForElement\n *\n * @param {HTMLElement} element The element.\n * @param {string} toolName The name of the tool.\n * @param {Object} options The options to set.\n * @returns {void}\n */\nconst setToolOptionsForElement = function(element, toolName, options) {\n const tool = getToolForElement(element, toolName);\n\n if (tool) {\n tool.mergeOptions(options);\n }\n};\n\n/**\n * Sets the options of a tool for all elements.\n * @export\n * @public\n * @method\n * @name setToolOptions\n *\n * @param {string} toolName\n * @param {Object} options\n * @returns {void}\n */\nconst setToolOptions = function(toolName, options) {\n state.enabledElements.forEach(element => {\n setToolOptionsForElement(element, toolName, options);\n });\n};\n\nexport { setToolOptions, setToolOptionsForElement };\n","import { globalImageIdSpecificToolStateManager } from './imageIdSpecificStateManager.js';\nimport {\n getElementToolStateManager,\n setElementToolStateManager,\n} from './toolState.js';\n\n/**\n * Implements an Stack specific tool state management strategy. This means\n * That tool data is shared between all imageIds in a given stack.\n * @public\n * @constructor newStackSpecificToolStateManager\n * @memberof StateManagement\n *\n * @param {string[]} toolTypes The tool types to apply to the stack.\n * @param {Object} oldStateManager The imageIdSpecificStateManager.\n * @returns {Object} A stackSpecificToolStateManager instance.\n */\nfunction newStackSpecificToolStateManager(toolTypes, oldStateManager) {\n let toolState = {};\n\n function saveToolState() {\n return toolState;\n }\n\n function restoreToolState(stackToolState) {\n toolState = stackToolState;\n }\n\n // Here we add tool state, this is done by tools as well\n // As modules that restore saved state\n function addStackSpecificToolState(element, toolType, data) {\n // If this is a tool type to apply to the stack, do so\n if (toolTypes.indexOf(toolType) >= 0) {\n // If we don't have tool state for this type of tool, add an empty object\n if (toolState.hasOwnProperty(toolType) === false) {\n toolState[toolType] = {\n data: [],\n };\n }\n\n const toolData = toolState[toolType];\n\n // Finally, add this new tool to the state\n toolData.data.push(data);\n } else {\n // Call the imageId specific tool state manager\n return oldStateManager.add(element, toolType, data);\n }\n }\n\n // Here you can get state - used by tools as well as modules\n // That save state persistently\n function getStackSpecificToolState(element, toolType) {\n // If this is a tool type to apply to the stack, do so\n if (toolTypes.indexOf(toolType) >= 0) {\n // If we don't have tool state for this type of tool, add an empty object\n if (toolState.hasOwnProperty(toolType) === false) {\n toolState[toolType] = {\n data: [],\n };\n }\n\n return toolState[toolType];\n }\n\n // Call the imageId specific tool state manager\n return oldStateManager.get(element, toolType);\n }\n\n const stackSpecificToolStateManager = {\n get: getStackSpecificToolState,\n add: addStackSpecificToolState,\n saveToolState,\n restoreToolState,\n toolState,\n };\n\n return stackSpecificToolStateManager;\n}\n\nconst stackStateManagers = [];\n\nfunction addStackStateManager(element, otherTools) {\n let oldStateManager = getElementToolStateManager(element);\n\n if (!oldStateManager) {\n oldStateManager = globalImageIdSpecificToolStateManager;\n }\n\n let stackTools = [\n 'stack',\n 'stackPrefetch',\n 'playClip',\n 'volume',\n 'slab',\n 'referenceLines',\n 'crosshairs',\n 'stackRenderer',\n ];\n\n if (otherTools) {\n stackTools = stackTools.concat(otherTools);\n }\n\n const stackSpecificStateManager = newStackSpecificToolStateManager(\n stackTools,\n oldStateManager\n );\n\n stackStateManagers.push(stackSpecificStateManager);\n setElementToolStateManager(element, stackSpecificStateManager);\n}\n\nconst stackSpecificStateManager = {\n newStackSpecificToolStateManager,\n addStackStateManager,\n};\n\nexport {\n stackSpecificStateManager,\n newStackSpecificToolStateManager,\n addStackStateManager,\n};\n","/**\n * Implements a frame-of-reference specific tool state management strategy. This means that\n * Measurement data are tied to a specific frame of reference UID and only visible to objects using\n * That frame-of-reference UID.\n * @public\n * @constructor newFrameOfReferenceSpecificToolStateManager\n * @memberof StateManagement\n *\n * @returns {Object} A frameOfReferenceSpecificToolStateManager instance.\n */\nfunction newFrameOfReferenceSpecificToolStateManager() {\n const toolState = {};\n\n // Here we add tool state, this is done by tools as well\n // As modules that restore saved state\n function addFrameOfReferenceSpecificToolState(\n frameOfReference,\n toolType,\n data\n ) {\n // If we don't have any tool state for this frameOfReference, add an empty object\n if (toolState.hasOwnProperty(frameOfReference) === false) {\n toolState[frameOfReference] = {};\n }\n\n const frameOfReferenceToolState = toolState[frameOfReference];\n\n // If we don't have tool state for this type of tool, add an empty object\n if (frameOfReferenceToolState.hasOwnProperty(toolType) === false) {\n frameOfReferenceToolState[toolType] = {\n data: [],\n };\n }\n\n const toolData = frameOfReferenceToolState[toolType];\n\n // Finally, add this new tool to the state\n toolData.data.push(data);\n }\n\n // Here you can get state - used by tools as well as modules\n // That save state persistently\n function getFrameOfReferenceSpecificToolState(frameOfReference, toolType) {\n // If we don't have any tool state for this frame of reference, return undefined\n if (toolState.hasOwnProperty(frameOfReference) === false) {\n return;\n }\n\n const frameOfReferenceToolState = toolState[frameOfReference];\n\n // If we don't have tool state for this type of tool, return undefined\n if (frameOfReferenceToolState.hasOwnProperty(toolType) === false) {\n return;\n }\n\n const toolData = frameOfReferenceToolState[toolType];\n\n return toolData;\n }\n\n function removeFrameOfReferenceSpecificToolState(\n frameOfReference,\n toolType,\n data\n ) {\n // If we don't have any tool state for this frame of reference, return undefined\n if (toolState.hasOwnProperty(frameOfReference) === false) {\n return;\n }\n\n const frameOfReferenceToolState = toolState[frameOfReference];\n\n // If we don't have tool state for this type of tool, return undefined\n if (frameOfReferenceToolState.hasOwnProperty(toolType) === false) {\n return;\n }\n\n const toolData = frameOfReferenceToolState[toolType];\n // Find this tool data\n let indexOfData = -1;\n\n for (let i = 0; i < toolData.data.length; i++) {\n if (toolData.data[i] === data) {\n indexOfData = i;\n }\n }\n\n if (indexOfData !== -1) {\n toolData.data.splice(indexOfData, 1);\n }\n }\n\n return {\n get: getFrameOfReferenceSpecificToolState,\n add: addFrameOfReferenceSpecificToolState,\n remove: removeFrameOfReferenceSpecificToolState,\n };\n}\n\n// A global frameOfReferenceSpecificToolStateManager - the most common case is to share 3d information\n// Between stacks of images\nconst globalFrameOfReferenceSpecificToolStateManager = newFrameOfReferenceSpecificToolStateManager();\n\nexport {\n newFrameOfReferenceSpecificToolStateManager,\n globalFrameOfReferenceSpecificToolStateManager,\n};\n","/**\n * Exports an image of the canvas.\n * @export @public @method\n * @name saveAs\n *\n * @param {HTMLElement} element The element to export.\n * @param {string} filename The name of the exported image.\n * @param {string} [mimetype = 'image/png'] The mimetype of the exported image.\n * @returns {void}\n */\nexport default (element, filename, mimetype = 'image/png') => {\n const canvas = element.querySelector('canvas');\n\n // If we are using IE, use canvas.msToBlob\n if (canvas.msToBlob) {\n const blob = canvas.msToBlob();\n\n return window.navigator.msSaveBlob(blob, filename);\n }\n\n // Thanks to Ken Fyrstenber\n // http://stackoverflow.com/questions/18480474/how-to-save-an-image-from-canvas\n const lnk = document.createElement('a');\n\n // The key here is to set the download attribute of the a tag\n lnk.download = filename;\n\n // Convert canvas content to data-uri for link. When download\n // Attribute is set the content pointed to by link will be\n // Pushed as 'download' in HTML5 capable browsers\n lnk.href = canvas.toDataURL(mimetype, 1);\n\n // Create a 'fake' click-event to trigger the download\n if (document.createEvent) {\n const e = document.createEvent('MouseEvents');\n\n e.initMouseEvent(\n 'click',\n true,\n true,\n window,\n 0,\n 0,\n 0,\n 0,\n 0,\n false,\n false,\n false,\n false,\n 0,\n null\n );\n\n lnk.dispatchEvent(e);\n } else if (lnk.fireEvent) {\n lnk.fireEvent('onclick');\n }\n};\n","import { modules } from '../store/index.js';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('thirdParty:registerModule');\n\n/**\n * Register a module.\n * @export\n * @private\n * @method\n * @name registerModule\n *\n * @param {string} name The name of the module.\n * @param {Object} newModule The module to register.\n * @param {boolean} [overwrite] Whether a module should be overwritten,\n * should it have the same name.\n * @returns {void}\n */\nexport default function(name, newModule, overwrite = false) {\n const alreadyRegistered = isModuleNameRegistered(name);\n\n if (alreadyRegistered && !overwrite) {\n logger.warn('A module with the name %s is already registered', name);\n\n return;\n }\n\n if (alreadyRegistered) {\n logger.warn('Overwriting module %s', name);\n }\n\n modules[name] = newModule;\n\n if (typeof modules[name].onRegisterCallback === 'function') {\n modules[name].onRegisterCallback();\n }\n}\n\nfunction isModuleNameRegistered(name) {\n return modules[name] !== undefined;\n}\n","import external from '../externalModules.js';\n\n/**\n * Sets the canvas context transformation matrix so it is scaled to show text\n * more cleanly even if the image is scaled up. See\n * https://github.com/cornerstonejs/cornerstoneTools/wiki/DrawingText\n * for more information\n * @export @public @function\n * @name setContextToDisplayFontSize\n *\n * @param {HTMLElement} enabledElement The cornerstone enabled element.\n * @param {CanvasRenderingContext2D} context The canvas context.\n * @param {number} fontSize The font size.\n * @returns {Object} {fontSize: number, lineHeight: number, fontScale: number}\n */\nexport default function(enabledElement, context, fontSize) {\n const fontScale = 0.1;\n\n external.cornerstone.setToPixelCoordinateSystem(\n enabledElement,\n context,\n fontScale\n );\n // Return the font size to use\n const scaledFontSize = fontSize / enabledElement.viewport.scale / fontScale;\n // TODO: actually calculate this?\n const lineHeight = fontSize / enabledElement.viewport.scale / fontScale;\n\n return {\n fontSize: scaledFontSize,\n lineHeight,\n fontScale,\n };\n}\n","import BaseTool from './tools/base/BaseTool.js';\nimport BaseAnnotationTool from './tools/base/BaseAnnotationTool.js';\nimport BaseBrushTool from './tools/base/BaseBrushTool.js';\n\nimport {\n anyHandlesOutsideImage,\n getHandleNearImagePoint,\n handleActivator,\n moveHandle,\n moveAllHandles,\n moveNewHandle,\n} from './manipulators/index.js';\n\nimport {\n moveHandleNearImagePoint,\n findHandleDataNearImagePoint,\n moveAnnotation,\n} from './util/findAndMoveHelpers.js';\n\nimport mixins from './mixins/index.js';\nimport * as cursors from './tools/cursors/index.js';\n\nimport {\n getNewContext,\n draw,\n path,\n setShadow,\n drawLine,\n drawLines,\n drawJoinedLines,\n drawCircle,\n drawEllipse,\n drawRect,\n fillOutsideRect,\n fillBox,\n fillTextLines,\n} from './drawing/index.js';\nimport { clip, clipToBox } from './util/clip.js';\nimport debounce from './util/debounce';\nimport deepmerge from './util/deepmerge';\nimport getDefault from './util/getDefault';\nimport getPixelSpacing from './util/getPixelSpacing';\nimport isEmptyObject from './util/isEmptyObject';\nimport isObject from './util/isObject';\nimport isPointInImage from './util/isPointInImage';\nimport isPointInPolygon from './util/isPointInPolygon';\nimport throttle from './util/throttle';\nimport { wait, waitForEnabledElementImageToLoad } from './util/wait';\nimport getKeyPressData from './util/getKeyPressData';\n\nimport drawTextBox, { textBoxWidth } from './drawing/drawTextBox.js';\nimport drawArrow from './drawing/drawArrow.js';\nimport drawLink from './drawing/drawLink.js';\nimport drawLinkedTextBox from './drawing/drawLinkedTextBox.js';\nimport drawHandles from './drawing/drawHandles.js';\n\nimport getLuminance from './util/getLuminance.js';\nimport getROITextBoxCoords from './util/getROITextBoxCoords';\nimport copyPoints from './util/copyPoints.js';\nimport calculateSUV from './util/calculateSUV.js';\nimport setContextToDisplayFontSize from './util/setContextToDisplayFontSize.js';\nimport scrollToIndex from './util/scrollToIndex.js';\nimport scroll from './util/scroll.js';\nimport roundToDecimal from './util/roundToDecimal.js';\nimport {\n projectPatientPointToImagePlane,\n imagePointToPatientPoint,\n planePlaneIntersection,\n} from './util/pointProjector.js';\nimport lineSegDistance from './util/lineSegDistance.js';\nimport { getLogger } from './util/logger';\n\nimport pointInsideBoundingBox from './util/pointInsideBoundingBox.js';\nimport makeUnselectable from './util/makeUnselectable.js';\nimport getRGBPixels from './util/getRGBPixels.js';\nimport {\n getDefaultSimultaneousRequests,\n getMaxSimultaneousRequests,\n getBrowserInfo,\n isMobileDevice,\n} from './util/getMaxSimultaneousRequests.js';\nimport angleBetweenPoints from './util/angleBetweenPoints.js';\nimport numbersWithCommas from './util/numbersWithCommas.js';\nimport MouseCursor from './tools/cursors/MouseCursor.js';\n\nimport ellipseUtils from './util/ellipse/index.js';\nimport freehandUtils from './util/freehand/index.js';\nimport * as segmentationUtils from './util/segmentation';\nimport zoomUtils from './util/zoom/index.js';\nimport triggerEvent from './util/triggerEvent.js';\nimport convertToVector3 from './util/convertToVector3.js';\n\nexport const lib = {\n 'base/BaseTool': BaseTool,\n 'base/BaseAnnotationTool': BaseAnnotationTool,\n 'base/BaseBrushTool': BaseBrushTool,\n\n 'tools/cursors/MouseCursor': MouseCursor,\n 'tools/cursors': cursors,\n\n 'manipulators/anyHandlesOutsideImage': anyHandlesOutsideImage,\n 'manipulators/getHandleNearImagePoint': getHandleNearImagePoint,\n 'manipulators/handleActivator': handleActivator,\n 'manipulators/moveAllHandles': moveAllHandles,\n 'manipulators/moveHandle': moveHandle,\n 'manipulators/moveNewHandle': moveNewHandle,\n 'manipulators/moveHandleNearImagePoint': moveHandleNearImagePoint,\n 'manipulators/findHandleDataNearImagePoint': findHandleDataNearImagePoint,\n 'manipulators/moveAnnotation': moveAnnotation,\n\n 'mixins/activeOrDisabledBinaryTool': mixins.activeOrDisabledBinaryTool,\n 'mixins/enabledOrDisabledBinaryTool': mixins.enabledOrDisabledBinaryTool,\n\n 'drawing/getNewContext': getNewContext,\n 'drawing/draw': draw,\n 'drawing/path': path,\n 'drawing/setShadow': setShadow,\n 'drawing/drawLine': drawLine,\n 'drawing/drawLines': drawLines,\n 'drawing/drawJoinedLines': drawJoinedLines,\n 'drawing/drawCircle': drawCircle,\n 'drawing/drawEllipse': drawEllipse,\n 'drawing/drawRect': drawRect,\n 'drawing/fillOutsideRect': fillOutsideRect,\n 'drawing/drawTextBox': drawTextBox,\n 'drawing/drawArrow': drawArrow,\n 'drawing/fillBox': fillBox,\n 'drawing/fillTextLines': fillTextLines,\n 'drawing/drawLink': drawLink,\n 'drawing/drawLinkedTextBox': drawLinkedTextBox,\n 'drawing/drawHandles': drawHandles,\n 'drawing/textBoxWidth': textBoxWidth,\n\n 'util/getLuminance': getLuminance,\n 'util/getROITextBoxCoords': getROITextBoxCoords,\n 'util/copyPoints': copyPoints,\n 'util/calculateSUV': calculateSUV,\n 'util/setContextToDisplayFontSize': setContextToDisplayFontSize,\n 'util/scrollToIndex': scrollToIndex,\n 'util/scroll': scroll,\n 'util/roundToDecimal': roundToDecimal,\n 'util/projectPatientPointToImagePlane': projectPatientPointToImagePlane,\n 'util/imagePointToPatientPoint': imagePointToPatientPoint,\n 'util/planePlaneIntersection': planePlaneIntersection,\n 'util/pointInsideBoundingBox': pointInsideBoundingBox,\n 'util/makeUnselectable': makeUnselectable,\n 'util/getRGBPixels': getRGBPixels,\n 'util/getDefaultSimultaneousRequests': getDefaultSimultaneousRequests,\n 'util/getMaxSimultaneousRequests': getMaxSimultaneousRequests,\n 'util/getBrowserInfo': getBrowserInfo,\n 'util/isMobileDevice': isMobileDevice,\n 'util/angleBetweenPoints': angleBetweenPoints,\n 'util/numbersWithCommas': numbersWithCommas,\n 'util/lineSegDistance': lineSegDistance,\n 'util/triggerEvent': triggerEvent,\n 'util/convertToVector3': convertToVector3,\n 'util/clip': clip,\n 'util/clipToBox': clipToBox,\n 'util/debounce': debounce,\n 'util/deepmerge': deepmerge,\n 'util/getDefault': getDefault,\n 'util/getPixelSpacing': getPixelSpacing,\n 'util/isEmptyObject': isEmptyObject,\n 'util/isObject': isObject,\n 'util/isPointInImage': isPointInImage,\n 'util/isPointInPolygon': isPointInPolygon,\n 'util/getLogger': getLogger,\n 'util/throttle': throttle,\n 'util/wait': wait,\n 'util/waitForEnabledElementImageToLoad': waitForEnabledElementImageToLoad,\n 'util/getKeyPressData': getKeyPressData,\n\n // Whole tool specific util packages\n 'util/ellipseUtils': ellipseUtils,\n 'util/freehandUtils': freehandUtils,\n 'util/segmentationUtils': segmentationUtils,\n 'util/zoomUtils': zoomUtils,\n};\n","import external from './../externalModules.js';\nimport path from './path.js';\n\n/**\n * Fill the region outside a rectangle defined by `corner1` and `corner2`.\n * @public\n * @method fillOutsideRect\n * @memberof Drawing\n *\n * @param {CanvasRenderingContext2D} context - Target context\n * @param {HTMLElement} element - The DOM Element to draw on\n * @param {Object} corner1 - `{ x, y }` in either pixel or canvas coordinates.\n * @param {Object} corner2 - `{ x, y }` in either pixel or canvas coordinates.\n * @param {Object} options - See {@link path}\n * @param {String} [coordSystem='pixel'] - Can be \"pixel\" (default) or \"canvas\". The coordinate\n * system of the points passed in to the function. If \"pixel\" then cornerstone.pixelToCanvas\n * is used to transform the points from pixel to canvas coordinates.\n * @returns {undefined}\n */\nexport default function(\n context,\n element,\n corner1,\n corner2,\n options,\n coordSystem = 'pixel'\n) {\n if (coordSystem === 'pixel') {\n const cornerstone = external.cornerstone;\n\n corner1 = cornerstone.pixelToCanvas(element, corner1);\n corner2 = cornerstone.pixelToCanvas(element, corner2);\n }\n\n const left = Math.min(corner1.x, corner2.x);\n const top = Math.min(corner1.y, corner2.y);\n const width = Math.abs(corner1.x - corner2.x);\n const height = Math.abs(corner1.y - corner2.y);\n\n path(context, options, context => {\n context.rect(0, 0, context.canvas.clientWidth, context.canvas.clientHeight);\n context.rect(left + width, top, -width, height);\n });\n}\n","/**\n * A helper function to make an element (and its content) being non selectable.\n * @export @public @method\n * @name makeUnselectable\n *\n * @param {HTMLElement} element The element to make unselectable\n * @param {Boolean} ignorePointerEvents true to make this element also\n * ignore events (e.g. mouse click), false otherwise.\n * @returns {void}\n */\nexport default function(element, ignorePointerEvents) {\n element.style.webkitUserSelect = 'none';\n element.style.webkitTouchCallout = 'none';\n element.style.mozUserSelect = 'none';\n element.style.msUserSelect = 'none';\n element.style.oUserSelect = 'none';\n element.style.khtmlUserSelect = 'none';\n element.style.userSelect = 'none';\n\n element.unselectable = 'on';\n element.oncontextmenu = () => false;\n\n if (ignorePointerEvents === true) {\n element.style.pointerEvents = 'none';\n }\n}\n","import store from '../store/';\nimport external from '../externalModules';\n\nexport default function getKeyPressData(e) {\n const cornerstone = external.cornerstone;\n const element = e.currentTarget;\n const enabledElement = cornerstone.getEnabledElement(element);\n\n if (!enabledElement || !enabledElement.image) {\n return;\n }\n\n const currentPointsImage = store.state.mousePositionImage;\n\n return {\n event: window.event || e, // Old IE support\n element,\n viewport: cornerstone.getViewport(element),\n image: enabledElement.image,\n currentPoints: {\n image: currentPointsImage,\n canvas: cornerstone.pixelToCanvas(element, currentPointsImage),\n },\n keyCode: e.keyCode,\n which: e.which,\n };\n}\n","import { lib } from '../lib.js';\nimport mixins from '../mixins/index.js';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('thirdParty:registerMixin');\n/**\n * Register an mixin to cornerstoneTools.\n * @export\n * @private\n * @method\n * @name registerMixin\n *\n * @param {string} name The name of the mixin.\n * @param {Object} mixin The mixin itself.\n * @param {boolean} [overwrite=false] Whether an mixin should be overwritten,\n * should it have the same name.\n * @returns {void}\n */\n\nexport default function(name, mixin, overwrite = false) {\n const alreadyRegistered = isMixinRegistered(name);\n\n if (alreadyRegistered && !overwrite) {\n logger.warn('mixins/%s is already registered', name);\n\n return;\n }\n\n if (alreadyRegistered) {\n logger.warn('Overwriting mixins/%s', name);\n }\n\n // Register to the mixins object\n mixins[name] = mixin;\n\n // Reference the mixin from the library so it can be exported externally.\n lib[`mixins/${name}`] = mixins[name];\n}\n\nfunction isMixinRegistered(name) {\n return mixins[name] !== undefined;\n}\n","import { lib } from '../lib.js';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('thirdParty:registerType');\n\n/**\n * Register an item to cornerstoneTools.\n * @export\n * @private\n * @method\n * @name registerItem\n *\n * @param {string} type The type of the item.\n * @param {string} name The name of the item.\n * @param {Object|function} item The item itself.\n * @param {boolean} [overwrite=false] Whether an item should be overwritten,\n * should it have the same name.\n * @returns {void}\n */\nexport default function(type, name, item, overwrite = false) {\n const itemKey = `${type}/${name}`;\n const alreadyRegistered = isItemNameRegistered(itemKey);\n\n if (alreadyRegistered && !overwrite) {\n logger.warn('%s is already registered', itemKey);\n\n return;\n }\n\n if (alreadyRegistered) {\n logger.warn('Overwriting %s', itemKey);\n }\n\n lib[itemKey] = item;\n}\n\nfunction isItemNameRegistered(itemKey) {\n return lib[itemKey] !== undefined;\n}\n","import registerModule from './registerModule.js';\nimport registerMixin from './registerMixin.js';\nimport registerItem from './registerItem.js';\nimport { getLogger } from '../util/logger.js';\n\nconst logger = getLogger('thirdParty:register');\n\n/**\n * Register an item or module to cornerstoneTools.\n * @export\n * @public\n * @method\n * @name register\n *\n * @param {string} type The type of the item/module.\n * @param {string} name The name of the item/module.\n * @param {Object|function} item The item/module itself.\n * @param {boolean} [overwrite=false] Whether an item/module should be\n * overwritten, should it have the same name.\n * @returns {void}\n */\nexport default function(type, name, item, overwrite = false) {\n if (!isValidInput(type, name, item)) {\n return;\n }\n\n switch (type) {\n case 'module':\n registerModule(name, item, overwrite);\n break;\n case 'mixin':\n registerMixin(name, item, overwrite);\n break;\n default:\n registerItem(type, name, item, overwrite);\n }\n}\n\n/**\n * Returns true if the item is valid, this avoids\n * clogging up the library with invalid data.\n * @private\n * @method\n * @name isValidInput\n *\n * @param {string} type The type of the item/module.\n * @param {string} name The name of the item/module.\n * @param {Object|function} item The item/module itself.\n * @returns {boolean} Whether the input is valid.\n */\nfunction isValidInput(type, name, item) {\n if (!type) {\n logger.warn('The type must be given in order to register.');\n\n return false;\n }\n\n if (!name) {\n logger.warn(`The %s must have a name in order to register.`, type);\n\n return false;\n }\n\n if (typeof item !== 'object' && typeof item !== 'function') {\n logger.warn(\n `The %s is a %s, it should be an Object or a function.`,\n item,\n typeof item\n );\n\n return false;\n }\n\n return true;\n}\n","import register from './register.js';\n\n/**\n * Register an array of items and/or modules to cornerstoneTools.\n * @export\n * @public\n * @method\n * @name registerSome\n *\n * @param {Object[]} items An array of items/modules to register.\n * @param {boolean} [overwrite=false] Whether an item/module should be\n * overwritten, should it have the same name.\n * @returns {void}\n */\nexport default function(items, overwrite = false) {\n items.forEach(({ type, name, item }) => {\n register(type, name, item, overwrite);\n });\n}\n","import external from '../externalModules.js';\n\n/**\n * Synchronize the target viewport ww/wc to match the source element.\n * @export\n * @public\n * @method\n * @name wwwcSynchronizer\n *\n * @param {Object} synchronizer - The Synchronizer instance that attaches this\n * handler to an event\n * @param {HTMLElement} sourceElement - The source element for the ww/wc values\n * @param {HTMLElement} targetElement - The target element\n * @returns {void}\n */\nexport default function(synchronizer, sourceElement, targetElement) {\n // Ignore the case where the source and target are the same enabled element\n if (targetElement === sourceElement) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n // Get the source and target viewports\n const sourceViewport = cornerstone.getViewport(sourceElement);\n const targetViewport = cornerstone.getViewport(targetElement);\n\n // Do nothing if the ww/wc already match\n if (\n targetViewport.voi.windowWidth === sourceViewport.voi.windowWidth &&\n targetViewport.voi.windowCenter === sourceViewport.voi.windowCenter &&\n targetViewport.invert === sourceViewport.invert\n ) {\n return;\n }\n\n // Www/wc are different, sync them\n targetViewport.voi.windowWidth = sourceViewport.voi.windowWidth;\n targetViewport.voi.windowCenter = sourceViewport.voi.windowCenter;\n targetViewport.invert = sourceViewport.invert;\n synchronizer.setViewport(targetElement, targetViewport);\n}\n","import external from '../externalModules.js';\n\n/**\n * Redraw target image immediately any time handler is called from source element.\n * @export\n * @public\n * @method\n * @name updateImageSynchronizer\n *\n * @param {Object} synchronizer - The Synchronizer instance that attaches this\n * handler to an event\n * @param {HTMLElement} sourceElement - The source element\n * @param {HTMLElement} targetElement - The target element\n * @returns {void}\n */\nexport default function(synchronizer, sourceElement, targetElement) {\n // Ignore the case where the source and target are the same enabled element\n if (targetElement === sourceElement) {\n return;\n }\n\n external.cornerstone.updateImage(targetElement);\n}\n","import external from '../externalModules.js';\nimport convertToVector3 from '../util/convertToVector3.js';\nimport { clearToolOptionsByElement } from '../toolOptions.js';\n\n/**\n * Return an array filtered to only its unique members\n *\n * @private\n * @param {Array} array - The array to filter\n * @returns {Array}\n */\nfunction unique(array) {\n return array.filter(function(value, index, self) {\n return self.indexOf(value) === index;\n });\n}\n\n/**\n * Synchronize target and source elements when an event fires on the source element\n * @export @public constructor\n * @name Synchronizer\n *\n * @param {String} event - The event(s) that will trigger synchronization. Separate multiple events by a space\n * @param {Function} handler - The function that will make the necessary changes to the target element in order to synchronize it with the source element\n * @returns {void}\n */\nfunction Synchronizer(event, handler) {\n const cornerstone = external.cornerstone;\n const that = this;\n const sourceElements = []; // Source elements fire the events we want to synchronize to\n const targetElements = []; // Target elements we want to synchronize to source elements\n\n let ignoreFiredEvents = false;\n const initialData = {};\n let eventHandler = handler;\n\n this.enabled = true;\n\n /**\n * Update the event handler to perform synchronization\n * @param {Function} handler - The event handler function\n * @returns {void}\n */\n this.setHandler = function(handler) {\n eventHandler = handler;\n };\n\n /**\n * Return a reference to the event handler function\n * @returns {Function}\n */\n this.getHandler = function() {\n return eventHandler;\n };\n\n /**\n * Calculate the initial distances between the source image and each\n * of the target images\n * @returns {void}\n */\n this.getDistances = function() {\n if (!sourceElements.length || !targetElements.length) {\n return;\n }\n\n initialData.distances = {};\n initialData.imageIds = {\n sourceElements: [],\n targetElements: [],\n };\n\n sourceElements.forEach(function(sourceElement) {\n const sourceEnabledElement = cornerstone.getEnabledElement(sourceElement);\n\n if (!sourceEnabledElement || !sourceEnabledElement.image) {\n return;\n }\n\n const sourceImageId = sourceEnabledElement.image.imageId;\n const sourceImagePlane = cornerstone.metaData.get(\n 'imagePlaneModule',\n sourceImageId\n );\n\n if (!sourceImagePlane || !sourceImagePlane.imagePositionPatient) {\n return;\n }\n\n const sourceImagePosition = convertToVector3(\n sourceImagePlane.imagePositionPatient\n );\n\n if (initialData.hasOwnProperty(sourceEnabledElement)) {\n return;\n }\n initialData.distances[sourceImageId] = {};\n\n initialData.imageIds.sourceElements.push(sourceImageId);\n\n targetElements.forEach(function(targetElement) {\n const targetEnabledElement = cornerstone.getEnabledElement(\n targetElement\n );\n\n if (!targetEnabledElement || !targetEnabledElement.image) {\n return;\n }\n\n const targetImageId = targetEnabledElement.image.imageId;\n\n initialData.imageIds.targetElements.push(targetImageId);\n\n if (sourceElement === targetElement) {\n return;\n }\n\n if (sourceImageId === targetImageId) {\n return;\n }\n\n if (\n initialData.distances[sourceImageId].hasOwnProperty(targetImageId)\n ) {\n return;\n }\n\n const targetImagePlane = cornerstone.metaData.get(\n 'imagePlaneModule',\n targetImageId\n );\n\n if (!targetImagePlane || !targetImagePlane.imagePositionPatient) {\n return;\n }\n\n const targetImagePosition = convertToVector3(\n targetImagePlane.imagePositionPatient\n );\n\n initialData.distances[sourceImageId][\n targetImageId\n ] = targetImagePosition.clone().sub(sourceImagePosition);\n });\n\n if (!Object.keys(initialData.distances[sourceImageId]).length) {\n delete initialData.distances[sourceImageId];\n }\n });\n };\n\n /**\n * Gather necessary event data and call synchronization handler\n *\n * @private\n * @param {HTMLElement} sourceElement - The source element for the event\n * @param {Object} eventData - The data object for the source event\n * @returns {void}\n */\n function fireEvent(sourceElement, eventData) {\n const isDisabled = !that.enabled;\n const noElements = !sourceElements.length || !targetElements.length;\n\n if (isDisabled || noElements) {\n return;\n }\n\n ignoreFiredEvents = true;\n targetElements.forEach(function(targetElement) {\n const targetIndex = targetElements.indexOf(targetElement);\n\n if (targetIndex === -1) {\n return;\n }\n\n const targetImageId = initialData.imageIds.targetElements[targetIndex];\n const sourceIndex = sourceElements.indexOf(sourceElement);\n\n if (sourceIndex === -1) {\n return;\n }\n\n const sourceImageId = initialData.imageIds.sourceElements[sourceIndex];\n\n let positionDifference;\n\n if (sourceImageId === targetImageId) {\n positionDifference = 0;\n } else if (initialData.distances[sourceImageId] !== undefined) {\n positionDifference =\n initialData.distances[sourceImageId][targetImageId];\n }\n\n eventHandler(\n that,\n sourceElement,\n targetElement,\n eventData,\n positionDifference\n );\n });\n ignoreFiredEvents = false;\n }\n\n /**\n * Call fireEvent if not ignoring events, and pass along event data\n *\n * @private\n * @param {Event} e - The source event object\n * @returns {void}\n */\n function onEvent(e) {\n const eventData = e.detail;\n\n if (ignoreFiredEvents === true) {\n return;\n }\n\n fireEvent(e.currentTarget, eventData);\n }\n\n /**\n * Add a source element to this synchronizer\n *\n * @param {HTMLElement} element - The new source element\n * @returns {void}\n */\n this.addSource = function(element) {\n // Return if this element was previously added\n const index = sourceElements.indexOf(element);\n\n if (index !== -1) {\n return;\n }\n\n // Add to our list of enabled elements\n sourceElements.push(element);\n\n // Subscribe to the event\n event.split(' ').forEach(oneEvent => {\n element.addEventListener(oneEvent, onEvent);\n });\n\n // Update the initial distances between elements\n that.getDistances();\n\n that.updateDisableHandlers();\n };\n\n /**\n * Add a target element to this synchronizer\n *\n * @param {HTMLElement} element - The new target element to be synchronized\n * @returns {void}\n */\n this.addTarget = function(element) {\n // Return if this element was previously added\n const index = targetElements.indexOf(element);\n\n if (index !== -1) {\n return;\n }\n\n // Add to our list of enabled elements\n targetElements.push(element);\n\n // Update the initial distances between elements\n that.getDistances();\n\n // Invoke the handler for this new target element\n eventHandler(that, element, element, 0);\n\n that.updateDisableHandlers();\n };\n\n /**\n * Add an element to this synchronizer as both a source and a target\n *\n * @param {HTMLElement} element - The new element\n * @returns {void}\n */\n this.add = function(element) {\n that.addSource(element);\n that.addTarget(element);\n };\n\n /**\n * Remove a source element from this synchronizer\n *\n * @param {HTMLElement} element - The element to be removed\n * @returns {void}\n */\n this.removeSource = function(element) {\n // Find the index of this element\n const index = sourceElements.indexOf(element);\n\n if (index === -1) {\n return;\n }\n\n // Remove this element from the array\n sourceElements.splice(index, 1);\n\n // Stop listening for the event\n event.split(' ').forEach(oneEvent => {\n element.removeEventListener(oneEvent, onEvent);\n });\n\n // Update the initial distances between elements\n that.getDistances();\n\n // Update everyone listening for events\n fireEvent(element);\n that.updateDisableHandlers();\n };\n\n /**\n * Remove a target element from this synchronizer\n *\n * @param {HTMLElement} element - The element to be removed\n * @returns {void}\n */\n this.removeTarget = function(element) {\n // Find the index of this element\n const index = targetElements.indexOf(element);\n\n if (index === -1) {\n return;\n }\n\n // Remove this element from the array\n targetElements.splice(index, 1);\n\n // Update the initial distances between elements\n that.getDistances();\n\n // Invoke the handler for the removed target\n eventHandler(that, element, element, 0);\n that.updateDisableHandlers();\n };\n\n /**\n * Remove an element from this synchronizer as both a target and source\n *\n * @param {HTMLElement} element - The element to be removed\n * @returns {void}\n */\n this.remove = function(element) {\n that.removeTarget(element);\n that.removeSource(element);\n };\n\n /**\n * Get the array of source elements\n *\n * @returns {HTMLElement[]}\n */\n this.getSourceElements = function() {\n return sourceElements;\n };\n\n /**\n * Get the array of target elements\n *\n * @returns {HTMLElement[]}\n */\n this.getTargetElements = function() {\n return targetElements;\n };\n\n /**\n * Display an image while halting synchronization\n *\n * @param {HTMLElement} element - The element containing the image\n * @param {Object} image - The cornerstone image object\n * @param {Object} viewport - The cornerstone viewport object\n * @returns {void}\n */\n this.displayImage = function(element, image, viewport) {\n ignoreFiredEvents = true;\n cornerstone.displayImage(element, image, viewport);\n ignoreFiredEvents = false;\n };\n\n /**\n * Update a viewport while halting synchronization\n *\n * @param {HTMLElement} element - The target element\n * @param {Object} viewport - The new cornerstone viewport object\n * @returns {void}\n */\n this.setViewport = function(element, viewport) {\n ignoreFiredEvents = true;\n cornerstone.setViewport(element, viewport);\n ignoreFiredEvents = false;\n };\n\n /**\n * Remove an element from the synchronizer based on an event from that element\n *\n * @private\n * @param {Event} e - The event whose element will be removed\n * @returns {void}\n */\n function disableHandler(e) {\n const element = e.detail.element;\n\n that.remove(element);\n clearToolOptionsByElement(element);\n }\n\n /**\n * Add an event listener to each element that can remove it from the synchronizer\n * @returns {void}\n */\n this.updateDisableHandlers = function() {\n const elements = unique(sourceElements.concat(targetElements));\n\n elements.forEach(function(element) {\n element.removeEventListener(\n external.cornerstone.EVENTS.ELEMENT_DISABLED,\n disableHandler\n );\n element.addEventListener(\n external.cornerstone.EVENTS.ELEMENT_DISABLED,\n disableHandler\n );\n });\n };\n\n /**\n * Remove all elements from this synchronizer\n * @returns {void}\n */\n this.destroy = function() {\n const elements = unique(sourceElements.concat(targetElements));\n\n elements.forEach(function(element) {\n that.remove(element);\n });\n };\n}\n\nexport default Synchronizer;\n","import external from '../externalModules.js';\nimport { getToolState } from '../stateManagement/toolState.js';\nimport loadHandlerManager from '../stateManagement/loadHandlerManager.js';\nimport clip from '../util/clip.js';\n\n/**\n * Propogate scrolling actions from the source element to the target element.\n * @export\n * @public\n * @method\n * @name stackScrollSynchronizer\n *\n * @param {Object} synchronizer - The Synchronizer instance that attaches this\n * handler to an event\n * @param {HTMLElement} sourceElement - The source element for the scroll event\n * @param {HTMLElement} targetElement - The target element\n * @param {Object} eventData - The data object from the triggering event\n * @returns {void}\n */\nexport default function(synchronizer, sourceElement, targetElement, eventData) {\n // If the target and source are the same, stop\n if (sourceElement === targetElement) {\n return;\n }\n\n // If there is no event, or direction is 0, stop\n if (!eventData || !eventData.direction) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n // Get the stack of the target viewport\n const stackToolDataSource = getToolState(targetElement, 'stack');\n const stackData = stackToolDataSource.data[0];\n\n // Get the new index for the stack\n let newImageIdIndex = stackData.currentImageIdIndex + eventData.direction;\n\n // Ensure the index does not exceed the bounds of the stack\n newImageIdIndex = clip(newImageIdIndex, 0, stackData.imageIds.length - 1);\n\n // If the index has not changed, stop here\n if (stackData.currentImageIdIndex === newImageIdIndex) {\n return;\n }\n\n const startLoadingHandler = loadHandlerManager.getStartLoadHandler(\n targetElement\n );\n const endLoadingHandler = loadHandlerManager.getEndLoadHandler(targetElement);\n const errorLoadingHandler = loadHandlerManager.getErrorLoadingHandler(\n targetElement\n );\n\n stackData.currentImageIdIndex = newImageIdIndex;\n const newImageId = stackData.imageIds[newImageIdIndex];\n\n if (startLoadingHandler) {\n startLoadingHandler(targetElement);\n }\n\n let loader;\n\n if (stackData.preventCache === true) {\n loader = cornerstone.loadImage(newImageId);\n } else {\n loader = cornerstone.loadAndCacheImage(newImageId);\n }\n\n loader.then(\n function(image) {\n const viewport = cornerstone.getViewport(targetElement);\n\n if (stackData.currentImageIdIndex !== newImageIdIndex) {\n return;\n }\n\n synchronizer.displayImage(targetElement, image, viewport);\n if (endLoadingHandler) {\n endLoadingHandler(targetElement, image);\n }\n },\n function(error) {\n const imageId = stackData.imageIds[newImageIdIndex];\n\n if (errorLoadingHandler) {\n errorLoadingHandler(targetElement, imageId, error);\n }\n }\n );\n}\n","import external from '../externalModules.js';\nimport { getToolState } from '../stateManagement/toolState.js';\nimport loadHandlerManager from '../stateManagement/loadHandlerManager.js';\nimport convertToVector3 from '../util/convertToVector3.js';\n\n/**\n * Synchronize the target stack to the image closest to the source image's position\n * @export\n * @public\n * @method\n * @name stackImagePositionSynchronizer\n *\n * @param {Object} synchronizer - The Synchronizer instance that attaches this\n * handler to an event\n * @param {HTMLElement} sourceElement - The source element for the image position\n * @param {HTMLElement} targetElement - The target element\n * @returns {void}\n */\nexport default function(synchronizer, sourceElement, targetElement) {\n // Ignore the case where the source and target are the same enabled element\n if (targetElement === sourceElement) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n const sourceStackData = getToolState(sourceElement, 'stack').data[0];\n const sourceImageId =\n sourceStackData.imageIds[sourceStackData.currentImageIdIndex];\n const sourceImagePlane = cornerstone.metaData.get(\n 'imagePlaneModule',\n sourceImageId\n );\n\n if (\n sourceImagePlane === undefined ||\n sourceImagePlane.imagePositionPatient === undefined\n ) {\n // Console.log('No position found for image ' + sourceImage.imageId);\n\n return;\n }\n\n const sourceImagePosition = convertToVector3(\n sourceImagePlane.imagePositionPatient\n );\n const stackToolDataSource = getToolState(targetElement, 'stack');\n const stackData = stackToolDataSource.data[0];\n\n let minDistance = Number.MAX_VALUE;\n let newImageIdIndex = -1;\n\n stackData.imageIds.forEach((imageId, index) => {\n const imagePlane = cornerstone.metaData.get('imagePlaneModule', imageId);\n\n if (\n imagePlane === undefined ||\n imagePlane.imagePositionPatient === undefined\n ) {\n // Console.log('No position found for image ' + imageId);\n\n return;\n }\n\n const imagePosition = convertToVector3(imagePlane.imagePositionPatient);\n const distance = imagePosition.distanceToSquared(sourceImagePosition);\n // Console.log(index + '=' + distance);\n\n if (distance < minDistance) {\n minDistance = distance;\n newImageIdIndex = index;\n }\n });\n\n if (newImageIdIndex === stackData.currentImageIdIndex) {\n return;\n }\n\n const startLoadingHandler = loadHandlerManager.getStartLoadHandler(\n targetElement\n );\n const endLoadingHandler = loadHandlerManager.getEndLoadHandler(targetElement);\n const errorLoadingHandler = loadHandlerManager.getErrorLoadingHandler(\n targetElement\n );\n\n stackData.currentImageIdIndex = newImageIdIndex;\n const newImageId = stackData.imageIds[newImageIdIndex];\n\n if (startLoadingHandler) {\n startLoadingHandler(targetElement);\n }\n\n if (newImageIdIndex !== -1) {\n let loader;\n\n if (stackData.preventCache === true) {\n loader = cornerstone.loadImage(newImageId);\n } else {\n loader = cornerstone.loadAndCacheImage(newImageId);\n }\n\n loader.then(\n function(image) {\n const viewport = cornerstone.getViewport(targetElement);\n\n if (stackData.currentImageIdIndex !== newImageIdIndex) {\n return;\n }\n\n synchronizer.displayImage(targetElement, image, viewport);\n if (endLoadingHandler) {\n endLoadingHandler(targetElement, image);\n }\n },\n function(error) {\n const imageId = stackData.imageIds[newImageIdIndex];\n\n if (errorLoadingHandler) {\n errorLoadingHandler(targetElement, imageId, error);\n }\n }\n );\n }\n}\n","import external from '../externalModules.js';\nimport { getToolState } from '../stateManagement/toolState.js';\nimport loadHandlerManager from '../stateManagement/loadHandlerManager.js';\nimport convertToVector3 from '../util/convertToVector3.js';\n\n// In the future we will want to have a way to manually register links sets of the same orientation (e.g. an axial link set from a prior with an axial link set of a current). The user could do this by scrolling the two stacks to a similar location and then doing a user action (e.g. right click link) at which point the system will capture the delta between the image position (patient) of both stacks and use that to sync them. This offset will need to be adjustable.\n\n/**\n * Calculate a position in space that is offset from the source image's position,\n * and synchronize the target stack to the image that is closest to that position.\n * @export\n * @public\n * @method\n * @name stackImagePositionOffsetSynchronizer\n *\n * @param {Object} synchronizer - The Synchronizer instance that attaches this\n * handler to an event\n * @param {HTMLElement} sourceElement - The source element\n * @param {HTMLElement} targetElement - The target element\n * @param {Object} eventData - The data object from the triggering event\n * @param {Object} positionDifference - An object with { x, y, z } values that will be\n * added to the source image's coordinates\n * @returns {void}\n */\nexport default function(\n synchronizer,\n sourceElement,\n targetElement,\n eventData,\n positionDifference\n) {\n // Ignore the case where the source and target are the same enabled element\n if (targetElement === sourceElement) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n const sourceStackData = getToolState(sourceElement, 'stack').data[0];\n const sourceImageId =\n sourceStackData.imageIds[sourceStackData.currentImageIdIndex];\n const sourceImagePlane = cornerstone.metaData.get(\n 'imagePlaneModule',\n sourceImageId\n );\n\n if (\n sourceImagePlane === undefined ||\n sourceImagePlane.imagePositionPatient === undefined\n ) {\n return;\n }\n\n const sourceImagePosition = convertToVector3(\n sourceImagePlane.imagePositionPatient\n );\n\n const stackToolDataSource = getToolState(targetElement, 'stack');\n const stackData = stackToolDataSource.data[0];\n\n let minDistance = Number.MAX_VALUE;\n let newImageIdIndex = -1;\n\n if (!positionDifference) {\n return;\n }\n\n const finalPosition = sourceImagePosition.clone().add(positionDifference);\n\n stackData.imageIds.forEach(function(imageId, index) {\n const imagePlane = cornerstone.metaData.get('imagePlaneModule', imageId);\n\n if (\n imagePlane === undefined ||\n imagePlane.imagePositionPatient === undefined\n ) {\n return;\n }\n\n const imagePosition = convertToVector3(imagePlane.imagePositionPatient);\n const distance = finalPosition.distanceToSquared(imagePosition);\n\n if (distance < minDistance) {\n minDistance = distance;\n newImageIdIndex = index;\n }\n });\n\n if (\n newImageIdIndex === stackData.currentImageIdIndex ||\n newImageIdIndex === -1\n ) {\n return;\n }\n\n const startLoadingHandler = loadHandlerManager.getStartLoadHandler(\n targetElement\n );\n const endLoadingHandler = loadHandlerManager.getEndLoadHandler(targetElement);\n const errorLoadingHandler = loadHandlerManager.getErrorLoadingHandler(\n targetElement\n );\n\n stackData.currentImageIdIndex = newImageIdIndex;\n const newImageId = stackData.imageIds[newImageIdIndex];\n\n if (startLoadingHandler) {\n startLoadingHandler(targetElement);\n }\n\n let loader;\n\n if (stackData.preventCache === true) {\n loader = cornerstone.loadImage(newImageId);\n } else {\n loader = cornerstone.loadAndCacheImage(newImageId);\n }\n\n loader.then(\n function(image) {\n const viewport = cornerstone.getViewport(targetElement);\n\n if (stackData.currentImageIdIndex !== newImageIdIndex) {\n return;\n }\n\n synchronizer.displayImage(targetElement, image, viewport);\n if (endLoadingHandler) {\n endLoadingHandler(targetElement, image);\n }\n },\n function(error) {\n const imageId = stackData.imageIds[newImageIdIndex];\n\n if (errorLoadingHandler) {\n errorLoadingHandler(targetElement, imageId, error);\n }\n }\n );\n}\n","import external from '../externalModules.js';\nimport { getToolState } from '../stateManagement/toolState.js';\nimport loadHandlerManager from '../stateManagement/loadHandlerManager.js';\nimport clip from '../util/clip.js';\n\n/**\n * Synchronize the target stack to the index closest to the source stack's index\n * @export\n * @public\n * @method\n * @name stackImageIndexSynchronizer\n *\n * @param {Object} synchronizer - The Synchronizer instance that attaches this\n * handler to an event\n * @param {HTMLElement} sourceElement - The source element for the index value\n * @param {HTMLElement} targetElement - The target element\n * @returns {void}\n */\nexport default function(synchronizer, sourceElement, targetElement) {\n // Ignore the case where the source and target are the same enabled element\n if (targetElement === sourceElement) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n const sourceStackToolDataSource = getToolState(sourceElement, 'stack');\n const sourceStackData = sourceStackToolDataSource.data[0];\n const targetStackToolDataSource = getToolState(targetElement, 'stack');\n const targetStackData = targetStackToolDataSource.data[0];\n\n let newImageIdIndex = sourceStackData.currentImageIdIndex;\n\n // Clamp the index\n newImageIdIndex = clip(\n newImageIdIndex,\n 0,\n targetStackData.imageIds.length - 1\n );\n\n // Do nothing if the index has not changed\n if (newImageIdIndex === targetStackData.currentImageIdIndex) {\n return;\n }\n\n const startLoadingHandler = loadHandlerManager.getStartLoadHandler(\n targetElement\n );\n const endLoadingHandler = loadHandlerManager.getEndLoadHandler(targetElement);\n const errorLoadingHandler = loadHandlerManager.getErrorLoadingHandler(\n targetElement\n );\n\n if (startLoadingHandler) {\n startLoadingHandler(targetElement);\n }\n\n let loader;\n\n if (targetStackData.preventCache === true) {\n loader = cornerstone.loadImage(targetStackData.imageIds[newImageIdIndex]);\n } else {\n loader = cornerstone.loadAndCacheImage(\n targetStackData.imageIds[newImageIdIndex]\n );\n }\n\n loader.then(\n function(image) {\n const viewport = cornerstone.getViewport(targetElement);\n\n targetStackData.currentImageIdIndex = newImageIdIndex;\n synchronizer.displayImage(targetElement, image, viewport);\n if (endLoadingHandler) {\n endLoadingHandler(targetElement, image);\n }\n },\n function(error) {\n const imageId = targetStackData.imageIds[newImageIdIndex];\n\n if (errorLoadingHandler) {\n errorLoadingHandler(targetElement, imageId, error);\n }\n }\n );\n}\n","import external from '../externalModules.js';\n\n/**\n * Synchronize the target zoom and pan to match the source\n * @export\n * @public\n * @method\n * @name panZoomSynchronizer\n *\n * @param {Object} synchronizer - The Synchronizer instance that attaches this\n * handler to an event\n * @param {HTMLElement} sourceElement - The source element for the zoom and pan values\n * @param {HTMLElement} targetElement - The target element\n * @returns {void}\n */\nexport default function(synchronizer, sourceElement, targetElement) {\n // Ignore the case where the source and target are the same enabled element\n if (targetElement === sourceElement) {\n return;\n }\n\n const cornerstone = external.cornerstone;\n // Get the source and target viewports\n const sourceViewport = cornerstone.getViewport(sourceElement);\n const targetViewport = cornerstone.getViewport(targetElement);\n\n // Do nothing if the scale and translation are the same\n if (\n targetViewport.scale === sourceViewport.scale &&\n targetViewport.translation.x === sourceViewport.translation.x &&\n targetViewport.translation.y === sourceViewport.translation.y\n ) {\n return;\n }\n\n // Scale and/or translation are different, sync them\n targetViewport.scale = sourceViewport.scale;\n targetViewport.translation.x = sourceViewport.translation.x;\n targetViewport.translation.y = sourceViewport.translation.y;\n synchronizer.setViewport(targetElement, targetViewport);\n}\n","import { lib } from './lib.js';\n\n/**\n * Imports functionality from cornerstoneTools for use in external packages/plugins.\n * @param {string} uri the import path for the entity to import.\n * @returns {Class|Object|Function} The entity requested.\n */\nexport default function(uri) {\n return lib[uri];\n}\n","/**\n * Root\n * @namespace CornerstoneTools\n */\n\n/**\n * Drawing API to assist in consistent annotation creation\n * @namespace Drawing\n */\n\n/**\n * Event dispatchers listen for events from `cornerstone` and `enabledElements`. Dispatchers\n * choose which tool(s) get to handle the event by looking at callbacks, priority, and other factors.\n * @private\n * @namespace EventDispatchers\n */\n\n/**\n * Event listeners normalize events emitted by `cornerstone` and `enabledElements`. The listeners\n * then re-emit events prefixed with `cornerstonetools`. For example, `mousemove` becomes `cornerstonetoolsmousemove`.\n * Most of these events are caught by an `eventDispatcher`, and used to shape tool behavior.\n * @private\n * @namespace EventListeners\n */\n\n/**\n * Manipulators describe a tool's `handle` behavior. Leveraging a small set of manipulators\n * allows us to create a consistent experience when interacting with tools via their handles.\n * @namespace Manipulators\n */\n\n/**\n * Mixins are \"tool beahviors\" that can be added to a tool via its mixin\n * array configuration property\n * @namespace Mixins\n */\n\n/**\n * StateManagement\n * @namespace StateManagement\n */\n\n/**\n * Sync\n * @namespace Synchronization\n */\n\n/**\n * Third party\n * @namespace ThirdParty\n */\n\n/**\n * Tools\n * @namespace Tools\n */\n\n/**\n * Tools that extend the {@link #Tools.Base.BaseAnnotationTool|`BaseAnnotationTool`}\n * @namespace Tools.Annotation\n */\n\n/**\n * The parent (abstract) classes that all tools derive from.\n * @namespace Tools.Base\n */\n\n/**\n * Tools that extend the {@link #Tools.Base.BaseBrushTool|`BaseBrushTool`}\n * @namespace Tools.Brush\n */\n\n/**\n * Util\n * @namespace Util\n */\n\nimport {\n AngleTool,\n ArrowAnnotateTool,\n BidirectionalTool,\n CircleRoiTool,\n CobbAngleTool,\n EllipticalRoiTool,\n FreehandRoiTool,\n LengthTool,\n ProbeTool,\n RectangleRoiTool,\n TextMarkerTool,\n} from './tools/annotation/index.js';\nimport {\n BrushTool,\n SphericalBrushTool,\n FreehandScissorsTool,\n RectangleScissorsTool,\n CircleScissorsTool,\n CorrectionScissorsTool,\n} from './tools/segmentation/index.js';\nimport {\n CrosshairsTool,\n DoubleTapFitToWindowTool,\n DragProbeTool,\n EraserTool,\n FreehandRoiSculptorTool,\n MagnifyTool,\n OrientationMarkersTool,\n PanMultiTouchTool,\n PanTool,\n ReferenceLinesTool,\n RotateTool,\n RotateTouchTool,\n ScaleOverlayTool,\n StackScrollMouseWheelTool,\n StackScrollMultiTouchTool,\n StackScrollTool,\n WwwcRegionTool,\n WwwcTool,\n ZoomMouseWheelTool,\n ZoomTool,\n ZoomTouchPinchTool,\n} from './tools/index.js';\n\nimport { default as init } from './init.js';\n\n// ~~~~~~ STACK TOOLS ~~~~~ //\nimport { default as stackPrefetch } from './stackTools/stackPrefetch.js';\nimport { default as stackRenderers } from './stackTools/stackRenderers.js';\nimport { playClip, stopClip } from './stackTools/playClip.js';\n\n// ~~~~~~ STATE MANAGEMENT ~~~~~ //\nimport { default as store } from './store/index.js';\nimport { getModule } from './store/index.js';\n\nimport { default as getToolForElement } from './store/getToolForElement.js';\nimport { addTool, addToolForElement } from './store/addTool.js';\nimport { removeTool, removeToolForElement } from './store/removeTool.js';\nimport {\n setToolOptions,\n setToolOptionsForElement,\n} from './store/setToolOptions.js';\nimport {\n setToolActive,\n setToolActiveForElement,\n setToolEnabled,\n setToolEnabledForElement,\n setToolDisabled,\n setToolDisabledForElement,\n setToolPassive,\n setToolPassiveForElement,\n} from './store/setToolMode.js';\nimport isToolActiveForElement from './store/isToolActiveForElement';\nimport {\n addToolState,\n getToolState,\n removeToolState,\n clearToolState,\n setElementToolStateManager,\n getElementToolStateManager,\n} from './stateManagement/toolState.js';\nimport { default as textStyle } from './stateManagement/textStyle.js';\nimport { default as toolStyle } from './stateManagement/toolStyle.js';\nimport { default as toolColors } from './stateManagement/toolColors.js';\nimport { default as toolCoordinates } from './stateManagement/toolCoordinates.js';\nimport {\n stackSpecificStateManager,\n newStackSpecificToolStateManager,\n addStackStateManager,\n} from './stateManagement/stackSpecificStateManager.js';\nimport { default as loadHandlerManager } from './stateManagement/loadHandlerManager.js';\nimport {\n newImageIdSpecificToolStateManager,\n globalImageIdSpecificToolStateManager,\n} from './stateManagement/imageIdSpecificStateManager.js';\nimport {\n newFrameOfReferenceSpecificToolStateManager,\n globalFrameOfReferenceSpecificToolStateManager,\n} from './stateManagement/frameOfReferenceStateManager.js';\nimport { forceEnabledElementResize } from './eventListeners/windowResizeHandler.js';\n\n// ~~~~~~ ORIENTATION ~~~~~ //\nimport { default as orientation } from './orientation/index.js';\n\n// ~~~~~~ CANVAS EXPORT ~~~~~ //\nimport { default as SaveAs } from './util/SaveAs.js';\nimport {\n enable as enableLogger,\n disable as disableLogger,\n} from './util/logger.js';\n\n// ~~~~~~ THIRD PARTY SUPPORT ~~~~~ //\nimport { default as register } from './thirdParty/register.js';\nimport { default as registerSome } from './thirdParty/registerSome.js';\n\n// ~~~~~~ SYNCHRONIZERS ~~~~~ //\nimport { default as wwwcSynchronizer } from './synchronization/wwwcSynchronizer.js';\nimport { default as updateImageSynchronizer } from './synchronization/updateImageSynchronizer.js';\nimport { default as Synchronizer } from './synchronization/Synchronizer.js';\nimport { default as stackScrollSynchronizer } from './synchronization/stackScrollSynchronizer.js';\nimport { default as stackImagePositionSynchronizer } from './synchronization/stackImagePositionSynchronizer.js';\nimport { default as stackImagePositionOffsetSynchronizer } from './synchronization/stackImagePositionOffsetSynchronizer.js';\nimport { default as stackImageIndexSynchronizer } from './synchronization/stackImageIndexSynchronizer.js';\nimport { default as panZoomSynchronizer } from './synchronization/panZoomSynchronizer.js';\n\n// ~~~~~~ REQUEST POOL MANAGER ~~~~~ //\nimport { default as requestPoolManager } from './requestPool/requestPoolManager.js';\n\nimport { default as external } from './externalModules.js';\nimport { default as EVENTS } from './events.js';\nimport { default as version } from './version.js';\n\nimport importInternal from './importInternal.js';\n\nconst cornerstoneTools = {\n // ~~~ TOOLS\n // ~ Annotation Tools\n AngleTool,\n ArrowAnnotateTool,\n BidirectionalTool,\n CircleRoiTool,\n CobbAngleTool,\n EllipticalRoiTool,\n FreehandRoiTool,\n LengthTool,\n ProbeTool,\n RectangleRoiTool,\n TextMarkerTool,\n // ~ Segmentation Tools\n BrushTool,\n SphericalBrushTool,\n RectangleScissorsTool,\n FreehandScissorsTool,\n CircleScissorsTool,\n CorrectionScissorsTool,\n // ~ Tools\n CrosshairsTool,\n DoubleTapFitToWindowTool,\n DragProbeTool,\n EraserTool,\n FreehandRoiSculptorTool,\n MagnifyTool,\n OrientationMarkersTool,\n PanMultiTouchTool,\n PanTool,\n ReferenceLinesTool,\n RotateTool,\n RotateTouchTool,\n ScaleOverlayTool,\n StackScrollMouseWheelTool,\n StackScrollMultiTouchTool,\n StackScrollTool,\n WwwcRegionTool,\n WwwcTool,\n ZoomMouseWheelTool,\n ZoomTool,\n ZoomTouchPinchTool,\n init,\n stackPrefetch,\n stackRenderers,\n playClip,\n stopClip,\n store,\n getModule,\n getToolForElement,\n addTool,\n addToolForElement,\n removeTool,\n removeToolForElement,\n setToolOptions,\n setToolOptionsForElement,\n isToolActiveForElement,\n setToolActive,\n setToolActiveForElement,\n setToolEnabled,\n setToolEnabledForElement,\n setToolDisabled,\n setToolDisabledForElement,\n setToolPassive,\n setToolPassiveForElement,\n addToolState,\n getToolState,\n removeToolState,\n clearToolState,\n setElementToolStateManager,\n getElementToolStateManager,\n textStyle,\n toolStyle,\n toolColors,\n toolCoordinates,\n stackSpecificStateManager,\n newStackSpecificToolStateManager,\n addStackStateManager,\n loadHandlerManager,\n newImageIdSpecificToolStateManager,\n globalImageIdSpecificToolStateManager,\n newFrameOfReferenceSpecificToolStateManager,\n globalFrameOfReferenceSpecificToolStateManager,\n forceEnabledElementResize,\n orientation,\n SaveAs,\n enableLogger,\n disableLogger,\n importInternal,\n import: importInternal,\n register,\n registerSome,\n wwwcSynchronizer,\n updateImageSynchronizer,\n Synchronizer,\n stackScrollSynchronizer,\n stackImagePositionSynchronizer,\n stackImagePositionOffsetSynchronizer,\n stackImageIndexSynchronizer,\n panZoomSynchronizer,\n requestPoolManager,\n external,\n EVENTS,\n version,\n};\n\n// Named Exports\nexport {\n // ~~~ TOOLS\n // ~ Annotation Tools\n AngleTool,\n ArrowAnnotateTool,\n BidirectionalTool,\n CircleRoiTool,\n CobbAngleTool,\n EllipticalRoiTool,\n FreehandRoiTool,\n LengthTool,\n ProbeTool,\n RectangleRoiTool,\n TextMarkerTool,\n // ~ Segmentation Tools\n BrushTool,\n SphericalBrushTool,\n RectangleScissorsTool,\n FreehandScissorsTool,\n CircleScissorsTool,\n CorrectionScissorsTool,\n // ~ Tools\n CrosshairsTool,\n DoubleTapFitToWindowTool,\n DragProbeTool,\n EraserTool,\n FreehandRoiSculptorTool,\n MagnifyTool,\n OrientationMarkersTool,\n PanMultiTouchTool,\n PanTool,\n ReferenceLinesTool,\n RotateTool,\n RotateTouchTool,\n ScaleOverlayTool,\n StackScrollMouseWheelTool,\n StackScrollMultiTouchTool,\n StackScrollTool,\n WwwcRegionTool,\n WwwcTool,\n ZoomMouseWheelTool,\n ZoomTool,\n ZoomTouchPinchTool,\n init,\n stackPrefetch,\n stackRenderers,\n playClip,\n stopClip,\n store,\n getModule,\n getToolForElement,\n addTool,\n addToolForElement,\n removeTool,\n removeToolForElement,\n setToolOptions,\n setToolOptionsForElement,\n isToolActiveForElement,\n setToolActive,\n setToolActiveForElement,\n setToolEnabled,\n setToolEnabledForElement,\n setToolDisabled,\n setToolDisabledForElement,\n setToolPassive,\n setToolPassiveForElement,\n addToolState,\n getToolState,\n removeToolState,\n clearToolState,\n setElementToolStateManager,\n getElementToolStateManager,\n textStyle,\n toolStyle,\n toolColors,\n toolCoordinates,\n stackSpecificStateManager,\n newStackSpecificToolStateManager,\n addStackStateManager,\n loadHandlerManager,\n newImageIdSpecificToolStateManager,\n globalImageIdSpecificToolStateManager,\n newFrameOfReferenceSpecificToolStateManager,\n globalFrameOfReferenceSpecificToolStateManager,\n forceEnabledElementResize,\n orientation,\n SaveAs,\n enableLogger,\n disableLogger,\n register,\n registerSome,\n wwwcSynchronizer,\n updateImageSynchronizer,\n Synchronizer,\n stackScrollSynchronizer,\n stackImagePositionSynchronizer,\n stackImagePositionOffsetSynchronizer,\n stackImageIndexSynchronizer,\n panZoomSynchronizer,\n requestPoolManager,\n importInternal,\n external,\n EVENTS,\n version,\n};\n\nexport { default as import } from './importInternal.js';\n\nexport default cornerstoneTools;\n","export default '4.6.0';\n"],"sourceRoot":""} |