@@ -14,6 +14,7 @@ import publish from "./eventPublisher";
1414import ScaleLine from 'ol/control/ScaleLine' ;
1515import Select from 'ol/interaction/Select' ;
1616import Static from 'ol/source/ImageStatic' ;
17+ import Overlay from 'ol/Overlay' ;
1718import TileLayer from 'ol/layer/Tile' ;
1819import TileImage from 'ol/source/TileImage' ;
1920import TileGrid from 'ol/tilegrid/TileGrid' ;
@@ -34,9 +35,9 @@ import { toStringXY, rotate } from 'ol/coordinate';
3435import { VLWholeSlideMicroscopyImage , getFrameMapping } from './metadata.js' ;
3536import { ROI } from './roi.js' ;
3637import {
37- generateUID ,
38- mapPixelCoordToSlideCoord ,
39- mapSlideCoordToPixelCoord
38+ generateUID ,
39+ mapPixelCoordToSlideCoord ,
40+ mapSlideCoordToPixelCoord
4041} from './utils.js' ;
4142import {
4243 Point ,
@@ -47,8 +48,7 @@ import {
4748 Ellipse
4849} from './scoord3d.js' ;
4950
50- import DICOMwebClient from 'dicomweb-client/build/dicomweb-client.js'
51-
51+ import * as DICOMwebClient from 'dicomweb-client' ;
5252
5353/** Extracts value of Pixel Spacing attribute from metadata.
5454 *
@@ -173,7 +173,7 @@ function _getRotation(metadata) {
173173 */
174174function _geometry2Scoord3d ( geometry , pyramid ) {
175175 console . info ( 'map coordinates from pixel matrix to slide coordinate system' )
176- const frameOfReferenceUID = pyramid [ pyramid . length - 1 ] . FrameOfReferenceUID ;
176+ const frameOfReferenceUID = pyramid [ pyramid . length - 1 ] . FrameOfReferenceUID ;
177177 const type = geometry . getType ( ) ;
178178 if ( type === 'Point' ) {
179179 let coordinates = geometry . getCoordinates ( ) ;
@@ -213,7 +213,7 @@ function _geometry2Scoord3d(geometry, pyramid) {
213213 [ center [ 0 ] , center [ 1 ] + radius , 0 ] ,
214214 ] ;
215215 coordinates = coordinates . map ( c => {
216- return _geometryCoordinates2scoord3dCoordinates ( c , pyramid ) ;
216+ return _geometryCoordinates2scoord3dCoordinates ( c , pyramid ) ;
217217 } )
218218
219219 // const metadata = pyramid[pyramid.length-1];
@@ -250,7 +250,7 @@ function _scoord3d2Geometry(scoord3d, pyramid) {
250250 return _scoord3dCoordinates2geometryCoordinates ( d , pyramid ) ;
251251 } ) ;
252252 return new LineStringGeometry ( coordinates ) ;
253- } else if ( type === 'POLYGON' ) {
253+ } else if ( type === 'POLYGON' ) {
254254 const coordinates = data . map ( d => {
255255 return _scoord3dCoordinates2geometryCoordinates ( d , pyramid ) ;
256256 } ) ;
@@ -276,7 +276,7 @@ function _scoord3d2Geometry(scoord3d, pyramid) {
276276 return _scoord3dCoordinates2geometryCoordinates ( d , pyramid ) ;
277277 } ) ;
278278 // to flat coordinates
279- coordinates = [ ...coordinates [ 0 ] . slice ( 0 , 2 ) , ...coordinates [ 1 ] . slice ( 0 , 2 ) ] ;
279+ coordinates = [ ...coordinates [ 0 ] . slice ( 0 , 2 ) , ...coordinates [ 1 ] . slice ( 0 , 2 ) ] ;
280280
281281 // flat coordinates in combination with opt_layout and no opt_radius are also accepted
282282 // and internaly it calculates the Radius
@@ -304,11 +304,11 @@ function _scoord3dCoordinates2geometryCoordinates(coordinates, pyramid) {
304304 */
305305function _coordinateFormatGeometry2Scoord3d ( coordinates , pyramid ) {
306306 let transform = false ;
307- if ( ! Array . isArray ( coordinates [ 0 ] ) ) {
307+ if ( ! Array . isArray ( coordinates [ 0 ] ) ) {
308308 coordinates = [ coordinates ] ;
309309 transform = true ;
310310 }
311- const metadata = pyramid [ pyramid . length - 1 ] ;
311+ const metadata = pyramid [ pyramid . length - 1 ] ;
312312 const origin = metadata . TotalPixelMatrixOriginSequence [ 0 ] ;
313313 const orientation = metadata . ImageOrientationSlide ;
314314 const spacing = _getPixelSpacing ( metadata ) ;
@@ -344,11 +344,11 @@ function _coordinateFormatGeometry2Scoord3d(coordinates, pyramid) {
344344 */
345345function _coordinateFormatScoord3d2Geometry ( coordinates , pyramid ) {
346346 let transform = false ;
347- if ( ! Array . isArray ( coordinates [ 0 ] ) ) {
347+ if ( ! Array . isArray ( coordinates [ 0 ] ) ) {
348348 coordinates = [ coordinates ] ;
349349 transform = true ;
350350 }
351- const metadata = pyramid [ pyramid . length - 1 ] ;
351+ const metadata = pyramid [ pyramid . length - 1 ] ;
352352 const orientation = metadata . ImageOrientationSlide ;
353353 const spacing = _getPixelSpacing ( metadata ) ;
354354 const origin = metadata . TotalPixelMatrixOriginSequence [ 0 ] ;
@@ -357,7 +357,7 @@ function _coordinateFormatScoord3d2Geometry(coordinates, pyramid) {
357357 Number ( origin . YOffsetInSlideCoordinateSystem ) ,
358358 ] ;
359359
360- coordinates = coordinates . map ( c => {
360+ coordinates = coordinates . map ( c => {
361361 const slideCoord = [ c [ 0 ] , c [ 1 ] ] ;
362362 const pixelCoord = mapSlideCoordToPixelCoord ( {
363363 offset,
@@ -381,7 +381,7 @@ function _coordinateFormatScoord3d2Geometry(coordinates, pyramid) {
381381 * @returns {ROI } Region of interest
382382 * @private
383383 */
384- function _getROIFromFeature ( feature , pyramid ) {
384+ function _getROIFromFeature ( feature , pyramid ) {
385385 let roi = { }
386386 if ( feature !== undefined ) {
387387 const geometry = feature . getGeometry ( ) ;
@@ -391,7 +391,7 @@ function _getROIFromFeature(feature, pyramid){
391391 const geometryName = feature . getGeometryName ( ) ;
392392 delete properties [ geometryName ] ;
393393 const uid = feature . getId ( ) ;
394- roi = new ROI ( { scoord3d, properties, uid} ) ;
394+ roi = new ROI ( { scoord3d, properties, uid } ) ;
395395 }
396396 return roi ;
397397}
@@ -452,7 +452,7 @@ class VolumeImageViewer {
452452 this [ _segmentations ] = { } ;
453453
454454 // Collection of Openlayers "Feature" instances
455- this [ _features ] = new Collection ( [ ] , { unique : true } ) ;
455+ this [ _features ] = new Collection ( [ ] , { unique : true } ) ;
456456 // Add unique identifier to each created "Feature" instance
457457 this [ _features ] . on ( 'add' , ( e ) => {
458458 // The ID may have already been set when drawn. However, features could
@@ -469,7 +469,7 @@ class VolumeImageViewer {
469469 */
470470 this [ _metadata ] = [ ] ;
471471 options . metadata . forEach ( m => {
472- const image = new VLWholeSlideMicroscopyImage ( { metadata : m } ) ;
472+ const image = new VLWholeSlideMicroscopyImage ( { metadata : m } ) ;
473473 if ( image . ImageType [ 2 ] === 'VOLUME' ) {
474474 this [ _metadata ] . push ( image ) ;
475475 }
@@ -503,9 +503,9 @@ class VolumeImageViewer {
503503 let index = null ;
504504 for ( let j = 0 ; j < this [ _pyramidMetadata ] . length ; j ++ ) {
505505 if (
506- ( this [ _pyramidMetadata ] [ j ] . TotalPixelMatrixColumns === cols ) &&
507- ( this [ _pyramidMetadata ] [ j ] . TotalPixelMatrixRows === rows )
508- ) {
506+ ( this [ _pyramidMetadata ] [ j ] . TotalPixelMatrixColumns === cols ) &&
507+ ( this [ _pyramidMetadata ] [ j ] . TotalPixelMatrixRows === rows )
508+ ) {
509509 alreadyExists = true ;
510510 index = j ;
511511 }
@@ -617,7 +617,7 @@ class VolumeImageViewer {
617617 const path = pyramidFrameMappings [ z ] [ index ] ;
618618 if ( path === undefined ) {
619619 console . warn ( "tile " + index + " not found at level " + z ) ;
620- return ( null ) ;
620+ return ( null ) ;
621621 }
622622 let url = options . client . wadoURL +
623623 "/studies/" + pyramid [ z ] . StudyInstanceUID +
@@ -626,7 +626,7 @@ class VolumeImageViewer {
626626 if ( options . retrieveRendered ) {
627627 url = url + '/rendered' ;
628628 }
629- return ( url ) ;
629+ return ( url ) ;
630630 }
631631
632632 /*
@@ -653,7 +653,7 @@ class VolumeImageViewer {
653653 }
654654 } ;
655655 options . client . retrieveInstanceFramesRendered ( retrieveOptions ) . then ( ( renderedFrame ) => {
656- const blob = new Blob ( [ renderedFrame ] , { type : mediaType } ) ;
656+ const blob = new Blob ( [ renderedFrame ] , { type : mediaType } ) ;
657657 img . src = window . URL . createObjectURL ( blob ) ;
658658 } ) ;
659659 } else {
@@ -665,10 +665,10 @@ class VolumeImageViewer {
665665 seriesInstanceUID,
666666 sopInstanceUID,
667667 frameNumbers,
668- mediaTypes : [ { mediaType, transferSyntaxUID : '1.2.840.10008.1.2.4.50' } ]
668+ mediaTypes : [ { mediaType, transferSyntaxUID : '1.2.840.10008.1.2.4.50' } ]
669669 } ;
670670 options . client . retrieveInstanceFrames ( retrieveOptions ) . then ( ( rawFrames ) => {
671- const blob = new Blob ( rawFrames , { type : mediaType } ) ;
671+ const blob = new Blob ( rawFrames , { type : mediaType } ) ;
672672 img . src = window . URL . createObjectURL ( blob ) ;
673673 } ) ;
674674 }
@@ -706,7 +706,7 @@ class VolumeImageViewer {
706706 /** DICOM Pixel Spacing has millimeter unit while the projection has
707707 * has meter unit.
708708 */
709- const spacing = _getPixelSpacing ( pyramid [ nLevels - 1 ] ) [ 0 ] / 10 ** 3 ;
709+ const spacing = _getPixelSpacing ( pyramid [ nLevels - 1 ] ) [ 0 ] / 10 ** 3 ;
710710 return pixelRes * spacing ;
711711 }
712712 } ) ;
@@ -817,6 +817,7 @@ class VolumeImageViewer {
817817 controls : [ ] ,
818818 keyboardEventTarget : document ,
819819 } ) ;
820+
820821 this [ _map ] . addInteraction ( new MouseWheelZoom ( ) ) ;
821822
822823 for ( let control in this [ _controls ] ) {
@@ -826,15 +827,15 @@ class VolumeImageViewer {
826827 }
827828
828829 /** Resizes the viewer to fit the viewport. */
829- resize ( ) {
830+ resize ( ) {
830831 this [ _map ] . updateSize ( ) ;
831832 }
832833
833834 /** Gets the size of the viewport.
834835 *
835836 * @type {number[] }
836837 */
837- get size ( ) {
838+ get size ( ) {
838839 return this [ _map ] . getSize ( ) ;
839840 }
840841
@@ -895,9 +896,9 @@ class VolumeImageViewer {
895896 const layout = geometry . getLayout ( ) ;
896897 const coordinates = geometry . getCoordinates ( ) ;
897898 const firstPoint = coordinates [ 0 ] [ 0 ] ;
898- const lastPoint = coordinates [ 0 ] [ coordinates [ 0 ] . length - 1 ] ;
899+ const lastPoint = coordinates [ 0 ] [ coordinates [ 0 ] . length - 1 ] ;
899900 if ( firstPoint [ 0 ] !== lastPoint [ 0 ] || firstPoint [ 1 ] !== lastPoint [ 1 ] ) {
900- coordinates [ 0 ] [ coordinates [ 0 ] . length - 1 ] = firstPoint ;
901+ coordinates [ 0 ] [ coordinates [ 0 ] . length - 1 ] = firstPoint ;
901902 geometry . setCoordinates ( coordinates , layout ) ;
902903 e . feature . setGeometry ( geometry ) ;
903904 }
@@ -961,7 +962,7 @@ class VolumeImageViewer {
961962 console . error ( `unsupported geometry type "${ options . geometryType } "` )
962963 }
963964
964- const defaultDrawOptions = { source : this [ _drawingSource ] } ;
965+ const defaultDrawOptions = { source : this [ _drawingSource ] } ;
965966 const customDrawOptions = customOptionsMapping [ options . geometryType ] ;
966967 if ( 'style' in options ) {
967968 customDrawOptions . style = options . style ;
@@ -1002,7 +1003,7 @@ class VolumeImageViewer {
10021003 *
10031004 * @param {Object } options - Selection options.
10041005 */
1005- activateSelectInteraction ( options = { } ) {
1006+ activateSelectInteraction ( options = { } ) {
10061007 this . deactivateSelectInteraction ( ) ;
10071008 console . info ( 'activate "select" interaction' )
10081009 this [ _interactions ] . select = new Select ( {
@@ -1039,7 +1040,7 @@ class VolumeImageViewer {
10391040 *
10401041 * @param {Object } options - Modification options.
10411042 */
1042- activateModifyInteraction ( options = { } ) {
1043+ activateModifyInteraction ( options = { } ) {
10431044 this . deactivateModifyInteraction ( ) ;
10441045 console . info ( 'activate "modify" interaction' )
10451046 this [ _interactions ] . modify = new Modify ( {
@@ -1073,7 +1074,7 @@ class VolumeImageViewer {
10731074 console . info ( 'get all ROIs' )
10741075 let rois = [ ] ;
10751076 this [ _features ] . forEach ( ( item ) => {
1076- rois . push ( this . getROI ( item . getId ( ) ) ) ;
1077+ rois . push ( this . getROI ( item . getId ( ) ) ) ;
10771078 } ) ;
10781079 return rois ;
10791080 }
@@ -1120,6 +1121,16 @@ class VolumeImageViewer {
11201121 this [ _features ] . push ( feature ) ;
11211122 }
11221123
1124+ /** Adds a new viewport overlay.
1125+ *
1126+ * @param {object } options Overlay options
1127+ * @param {object } options.element The custom overlay html element
1128+ * @param {object } options.className Class to style the OpenLayer's overlay container
1129+ */
1130+ addViewportOverlay ( { element, className } ) {
1131+ this [ _map ] . addOverlay ( new Overlay ( { element, className } ) ) ;
1132+ }
1133+
11231134 /** Removes an individual regions of interest.
11241135 *
11251136 * @param {string } uid - Unique identifier of the region of interest
@@ -1227,7 +1238,7 @@ class _NonVolumeImageViewer {
12271238 }
12281239 } ;
12291240 options . client . retrieveInstanceRendered ( retrieveOptions ) . then ( ( thumbnail ) => {
1230- const blob = new Blob ( [ thumbnail ] , { type : mediaType } ) ;
1241+ const blob = new Blob ( [ thumbnail ] , { type : mediaType } ) ;
12311242 image . getImage ( ) . src = window . URL . createObjectURL ( blob ) ;
12321243 } ) ;
12331244 }
@@ -1241,7 +1252,7 @@ class _NonVolumeImageViewer {
12411252 * has meter unit.
12421253 */
12431254 const mmSpacing = _getPixelSpacing ( this [ _metadata ] ) [ 0 ] ;
1244- const spacing = ( mmSpacing / resizeFactor ) / 10 ** 3 ;
1255+ const spacing = ( mmSpacing / resizeFactor ) / 10 ** 3 ;
12451256 return pixelRes * spacing ;
12461257 }
12471258 } ) ;
@@ -1304,15 +1315,15 @@ class _NonVolumeImageViewer {
13041315 }
13051316
13061317 /** Resizes the viewer to fit the viewport. */
1307- resize ( ) {
1318+ resize ( ) {
13081319 this [ _map ] . updateSize ( ) ;
13091320 }
13101321
13111322 /** Gets the size of the viewport.
13121323 *
13131324 * @type {number[] }
13141325 */
1315- get size ( ) {
1326+ get size ( ) {
13161327 return this [ _map ] . getSize ( ) ;
13171328 }
13181329
0 commit comments