feat(react-measurements): Add measurement table - WIP
This commit is contained in:
parent
e1f1d9b630
commit
84e2f86a76
@ -110,6 +110,7 @@
|
||||
"ohif-dicom-html-extension": "^0.0.2",
|
||||
"ohif-dicom-microscopy-extension": "^0.0.5",
|
||||
"ohif-dicom-pdf-extension": "^0.0.5",
|
||||
"moment": "^2.24.0",
|
||||
"oidc-client": "^1.6.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-bootstrap-modal": "^4.2.0",
|
||||
|
||||
@ -5,6 +5,7 @@ body,
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
|
||||
@ -19,11 +19,11 @@ import {
|
||||
reducer as oidcReducer
|
||||
} from 'redux-oidc';
|
||||
import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
|
||||
import './App.css';
|
||||
|
||||
const { ExtensionManager } = OHIF.extensions;
|
||||
|
||||
//import Icons from "./images/icons.svg"
|
||||
|
||||
const Icons = '/icons.svg';
|
||||
|
||||
const { reducers, localStorage } = OHIF.redux;
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { MeasurementTable } from 'react-viewerbase';
|
||||
import moment from 'moment';
|
||||
|
||||
function convertTimepointsToTableData(timepoints) {
|
||||
if (!timepoints || !timepoints.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
label: 'Study date:',
|
||||
date: moment(timepoints[0].latestDate).format('DD-MMM-YY')
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
function convertMeasurementsToTableData(measurements) {
|
||||
const tableData = [
|
||||
{
|
||||
groupName: 'Measurements',
|
||||
measurements: []
|
||||
}
|
||||
];
|
||||
|
||||
if (!measurements || !measurements.length) {
|
||||
return tableData;
|
||||
}
|
||||
|
||||
// TODO: Add measurements into tableData
|
||||
|
||||
return tableData;
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const { timepoints, measurements } = state;
|
||||
return {
|
||||
timepoints: convertTimepointsToTableData(timepoints.timepoints),
|
||||
measurementCollection: convertMeasurementsToTableData(measurements)
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedMeasurementTable = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(MeasurementTable);
|
||||
|
||||
export default ConnectedMeasurementTable;
|
||||
@ -2,89 +2,107 @@ import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
|
||||
import ViewerMain from './ViewerMain.js';
|
||||
import ConnectedMeasurementTable from './ConnectedMeasurementTable';
|
||||
import './FlexboxLayout.css';
|
||||
|
||||
class FlexboxLayout extends Component {
|
||||
static propTypes = {
|
||||
studies: PropTypes.array.isRequired,
|
||||
leftSidebarOpen: PropTypes.bool.isRequired,
|
||||
rightSidebarOpen: PropTypes.bool.isRequired,
|
||||
};
|
||||
static propTypes = {
|
||||
studies: PropTypes.array.isRequired,
|
||||
leftSidebarOpen: PropTypes.bool.isRequired,
|
||||
rightSidebarOpen: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
state = {
|
||||
studiesForBrowser: []
|
||||
};
|
||||
state = {
|
||||
studiesForBrowser: []
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const studiesForBrowser = this.getStudiesForBrowser();
|
||||
componentDidMount() {
|
||||
const studiesForBrowser = this.getStudiesForBrowser();
|
||||
|
||||
this.setState({
|
||||
studiesForBrowser
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
studiesForBrowser
|
||||
});
|
||||
}
|
||||
|
||||
getStudiesForBrowser = () => {
|
||||
const { studies } = this.props;
|
||||
getStudiesForBrowser = () => {
|
||||
const { studies } = this.props;
|
||||
|
||||
// TODO[react]:
|
||||
// - Add sorting of display sets
|
||||
// - Add useMiddleSeriesInstanceAsThumbnail
|
||||
// - Add showStackLoadingProgressBar option
|
||||
return studies.map((study) => {
|
||||
const { studyInstanceUid } = study;
|
||||
// TODO[react]:
|
||||
// - Add sorting of display sets
|
||||
// - Add useMiddleSeriesInstanceAsThumbnail
|
||||
// - Add showStackLoadingProgressBar option
|
||||
return studies.map(study => {
|
||||
const { studyInstanceUid } = study;
|
||||
|
||||
const thumbnails = study.displaySets.map((displaySet) => {
|
||||
const { displaySetInstanceUid, seriesDescription, seriesNumber, instanceNumber, numImageFrames } = displaySet;
|
||||
const thumbnails = study.displaySets.map(displaySet => {
|
||||
const {
|
||||
displaySetInstanceUid,
|
||||
seriesDescription,
|
||||
seriesNumber,
|
||||
instanceNumber,
|
||||
numImageFrames
|
||||
} = displaySet;
|
||||
|
||||
let imageId;
|
||||
|
||||
let imageId;
|
||||
|
||||
if (displaySet.images && displaySet.images.length) {
|
||||
imageId = displaySet.images[0].getImageId();
|
||||
}
|
||||
|
||||
return {
|
||||
imageId,
|
||||
displaySetInstanceUid,
|
||||
seriesDescription,
|
||||
seriesNumber,
|
||||
instanceNumber,
|
||||
numImageFrames,
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
studyInstanceUid,
|
||||
thumbnails
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
let mainContentClassName = "main-content"
|
||||
if (this.props.leftSidebarOpen) {
|
||||
mainContentClassName += ' sidebar-left-open';
|
||||
if (displaySet.images && displaySet.images.length) {
|
||||
imageId = displaySet.images[0].getImageId();
|
||||
}
|
||||
|
||||
if (this.props.rightSidebarOpen) {
|
||||
mainContentClassName += ' sidebar-right-open';
|
||||
}
|
||||
return {
|
||||
imageId,
|
||||
displaySetInstanceUid,
|
||||
seriesDescription,
|
||||
seriesNumber,
|
||||
instanceNumber,
|
||||
numImageFrames
|
||||
};
|
||||
});
|
||||
|
||||
// TODO[react]: Add measurementLightTable
|
||||
return (
|
||||
<div className="FlexboxLayout">
|
||||
<div className={this.props.leftSidebarOpen ? "sidebar-menu sidebar-left sidebar-open" : "sidebar-menu sidebar-left"}>
|
||||
<ConnectedStudyBrowser studies={this.state.studiesForBrowser}/>
|
||||
</div>
|
||||
<div className={mainContentClassName}>
|
||||
<ViewerMain studies={this.props.studies}/>
|
||||
</div>
|
||||
{/* <div className={this.props.rightSidebarOpen ? "sidebar-menu sidebar-right sidebar-open" : "sidebar-menu sidebar-right"}>
|
||||
{{> measurementLightTable (clone this)}}
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
return {
|
||||
studyInstanceUid,
|
||||
thumbnails
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
let mainContentClassName = 'main-content';
|
||||
if (this.props.leftSidebarOpen) {
|
||||
mainContentClassName += ' sidebar-left-open';
|
||||
}
|
||||
|
||||
if (this.props.rightSidebarOpen) {
|
||||
mainContentClassName += ' sidebar-right-open';
|
||||
}
|
||||
|
||||
// TODO[react]: Add measurementLightTable
|
||||
return (
|
||||
<div className="FlexboxLayout">
|
||||
<div
|
||||
className={
|
||||
this.props.leftSidebarOpen
|
||||
? 'sidebar-menu sidebar-left sidebar-open'
|
||||
: 'sidebar-menu sidebar-left'
|
||||
}
|
||||
>
|
||||
<ConnectedStudyBrowser studies={this.state.studiesForBrowser} />
|
||||
</div>
|
||||
<div className={mainContentClassName}>
|
||||
<ViewerMain studies={this.props.studies} />
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
this.props.rightSidebarOpen
|
||||
? 'sidebar-menu sidebar-right sidebar-open'
|
||||
: 'sidebar-menu sidebar-right'
|
||||
}
|
||||
>
|
||||
<ConnectedMeasurementTable />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default FlexboxLayout;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { Component } from "react";
|
||||
import React, { Component } from 'react';
|
||||
import ConnectedToolbarSection from './ConnectedToolbarSection';
|
||||
import ConnectedLayoutButton from './ConnectedLayoutButton';
|
||||
import ConnectedCineDialog from './ConnectedCineDialog.js';
|
||||
@ -10,68 +10,99 @@ import './ToolbarRow.css';
|
||||
const Icons = '/icons.svg';
|
||||
|
||||
class ToolbarRow extends Component {
|
||||
state = {
|
||||
cineDialogOpen: false
|
||||
state = {
|
||||
cineDialogOpen: false
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
leftSidebarOpen: PropTypes.bool.isRequired,
|
||||
rightSidebarOpen: PropTypes.bool.isRequired,
|
||||
setLeftSidebarOpen: PropTypes.func,
|
||||
setRightSidebarOpen: PropTypes.func
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
leftSidebarOpen: false,
|
||||
rightSidebarOpen: false
|
||||
};
|
||||
|
||||
onLeftSidebarValueChanged = value => {
|
||||
this.props.setLeftSidebarOpen(!!value);
|
||||
};
|
||||
|
||||
onRightSidebarValueChanged = value => {
|
||||
this.props.setRightSidebarOpen(!!value);
|
||||
};
|
||||
|
||||
onClickCineToolbarButton = () => {
|
||||
this.setState({
|
||||
cineDialogOpen: !this.state.cineDialogOpen
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const leftSidebarToggle = [
|
||||
{
|
||||
value: 'studies',
|
||||
svgLink: `${Icons}#icon-studies`,
|
||||
svgWidth: 15,
|
||||
svgHeight: 13,
|
||||
bottomLabel: 'Series'
|
||||
}
|
||||
];
|
||||
|
||||
const rightSidebarToggle = [
|
||||
{
|
||||
value: 'measurements',
|
||||
svgLink: `${Icons}#icon-measurements-lesions`,
|
||||
svgWidth: 15,
|
||||
svgHeight: 13,
|
||||
bottomLabel: 'Measurements'
|
||||
}
|
||||
];
|
||||
|
||||
const leftSidebarValue = this.props.leftSidebarOpen
|
||||
? leftSidebarToggle[0].value
|
||||
: null;
|
||||
|
||||
const rightSidebarValue = this.props.rightSidebarOpen
|
||||
? rightSidebarToggle[0].value
|
||||
: null;
|
||||
|
||||
const cineDialogContainerStyle = {
|
||||
display: this.state.cineDialogOpen ? 'inline-block' : 'none'
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
leftSidebarOpen: PropTypes.bool.isRequired,
|
||||
rightSidebarOpen: PropTypes.bool.isRequired,
|
||||
setLeftSidebarOpen: PropTypes.func,
|
||||
setRightSidebarOpen: PropTypes.func
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
leftSidebarOpen: false,
|
||||
rightSidebarOpen: false
|
||||
};
|
||||
|
||||
onLeftSidebarValueChanged = (value) => {
|
||||
this.props.setLeftSidebarOpen(!!value);
|
||||
}
|
||||
|
||||
onClickCineToolbarButton = () => {
|
||||
this.setState({
|
||||
cineDialogOpen: !this.state.cineDialogOpen
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const leftSidebarToggle = [{
|
||||
value: 'studies',
|
||||
svgLink: `${Icons}#icon-studies`,
|
||||
svgWidth: 15,
|
||||
svgHeight: 13,
|
||||
bottomLabel: 'Series',
|
||||
}];
|
||||
|
||||
const leftSidebarValue = this.props.leftSidebarOpen ? leftSidebarToggle[0].value : null;
|
||||
|
||||
const cineDialogContainerStyle = {
|
||||
display: this.state.cineDialogOpen ? 'inline-block' : 'none'
|
||||
}
|
||||
|
||||
return (<div className="ToolbarRow">
|
||||
<div className="pull-left m-t-1 p-y-1" style={{ padding: '10px' }}>
|
||||
<RoundedButtonGroup options={leftSidebarToggle} value={leftSidebarValue} onValueChanged={this.onLeftSidebarValueChanged}/>
|
||||
</div>
|
||||
<ConnectedToolbarSection/>
|
||||
<ConnectedLayoutButton/>
|
||||
<ToolbarButton
|
||||
active={this.state.cineDialogOpen}
|
||||
onClick={this.onClickCineToolbarButton}
|
||||
text={'CINE'}
|
||||
iconClasses={'fa fa-youtube'}
|
||||
/>
|
||||
<div className='CineDialogContainer' style={cineDialogContainerStyle}>
|
||||
<ConnectedCineDialog/>
|
||||
</div>
|
||||
<div className="pull-right m-t-1 rm-x-1">
|
||||
{/* > roundedButtonGroup rightSidebarToggleButtonData */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="ToolbarRow">
|
||||
<div className="pull-left m-t-1 p-y-1" style={{ padding: '10px' }}>
|
||||
<RoundedButtonGroup
|
||||
options={leftSidebarToggle}
|
||||
value={leftSidebarValue}
|
||||
onValueChanged={this.onLeftSidebarValueChanged}
|
||||
/>
|
||||
</div>
|
||||
<ConnectedToolbarSection />
|
||||
<ConnectedLayoutButton />
|
||||
<ToolbarButton
|
||||
active={this.state.cineDialogOpen}
|
||||
onClick={this.onClickCineToolbarButton}
|
||||
text={'CINE'}
|
||||
iconClasses={'fa fa-youtube'}
|
||||
/>
|
||||
<div className="CineDialogContainer" style={cineDialogContainerStyle}>
|
||||
<ConnectedCineDialog />
|
||||
</div>
|
||||
<div className="pull-right m-t-1 rm-x-1" style={{ marginLeft: 'auto' }}>
|
||||
<RoundedButtonGroup
|
||||
options={rightSidebarToggle}
|
||||
value={rightSidebarValue}
|
||||
onValueChanged={this.onRightSidebarValueChanged}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ToolbarRow;
|
||||
|
||||
@ -3,12 +3,15 @@ import PropTypes from 'prop-types';
|
||||
//import OHIF from 'ohif-core';
|
||||
//import { CineDialog } from 'react-viewerbase';
|
||||
|
||||
import OHIF from 'ohif-core';
|
||||
import moment from 'moment';
|
||||
import WhiteLabellingContext from '../WhiteLabellingContext.js';
|
||||
import ConnectedHeader from './ConnectedHeader.js';
|
||||
import ConnectedFlexboxLayout from './ConnectedFlexboxLayout.js';
|
||||
import ConnectedToolbarRow from './ConnectedToolbarRow.js';
|
||||
import ConnectedStudyLoadingMonitor from './ConnectedStudyLoadingMonitor.js';
|
||||
import StudyPrefetcher from '../components/StudyPrefetcher.js';
|
||||
import measurementTools from '../measurementTools';
|
||||
import './Viewer.css';
|
||||
/**
|
||||
* Inits OHIF Hanging Protocol's onReady.
|
||||
@ -51,6 +54,117 @@ class Viewer extends Component {
|
||||
studies: PropTypes.array
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const retrieveMeasurements = (patientId, timepointIds) => {
|
||||
OHIF.log.info('retrieveMeasurements');
|
||||
// TODO: Retrieve the measurements from the latest available SR
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const storeMeasurements = (measurementData, timepointIds) => {
|
||||
OHIF.log.info('storeMeasurements');
|
||||
// TODO: Store the measurements into a new SR sent to the active server
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const retrieveTimepoints = filter => {
|
||||
OHIF.log.info('retrieveTimepoints');
|
||||
|
||||
// Get the earliest and latest study date
|
||||
let earliestDate = new Date().toISOString();
|
||||
let latestDate = new Date().toISOString();
|
||||
if (props.studies) {
|
||||
latestDate = new Date('1000-01-01').toISOString();
|
||||
props.studies.forEach(study => {
|
||||
const studyDate = moment(study.studyDate, 'YYYYMMDD').toISOString();
|
||||
if (studyDate < earliestDate) {
|
||||
earliestDate = studyDate;
|
||||
}
|
||||
if (studyDate > latestDate) {
|
||||
latestDate = studyDate;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Return a generic timepoint
|
||||
return Promise.resolve([
|
||||
{
|
||||
timepointType: 'baseline',
|
||||
timepointId: 'TimepointId',
|
||||
studyInstanceUids: props.studyInstanceUids,
|
||||
patientId: filter.patientId,
|
||||
earliestDate,
|
||||
latestDate,
|
||||
isLocked: false
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
const storeTimepoints = timepointData => {
|
||||
OHIF.log.info('storeTimepoints');
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const updateTimepoint = (timepointData, query) => {
|
||||
OHIF.log.info('updateTimepoint');
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const removeTimepoint = timepointId => {
|
||||
OHIF.log.info('removeTimepoint');
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const disassociateStudy = (timepointIds, studyInstanceUid) => {
|
||||
OHIF.log.info('disassociateStudy');
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
OHIF.measurements.MeasurementApi.setConfiguration({
|
||||
measurementTools,
|
||||
dataExchange: {
|
||||
retrieve: retrieveMeasurements,
|
||||
store: storeMeasurements
|
||||
}
|
||||
});
|
||||
|
||||
OHIF.measurements.TimepointApi.setConfiguration({
|
||||
dataExchange: {
|
||||
retrieve: retrieveTimepoints,
|
||||
store: storeTimepoints,
|
||||
remove: removeTimepoint,
|
||||
update: updateTimepoint,
|
||||
disassociate: disassociateStudy
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { studies } = this.props;
|
||||
const { TimepointApi, MeasurementApi } = OHIF.measurements;
|
||||
|
||||
// TODO: Get the Redux store from somewhere else
|
||||
const { store } = window;
|
||||
|
||||
const timepointApi = new TimepointApi(store, 'TimepointId');
|
||||
const measurementApi = new MeasurementApi(store, timepointApi);
|
||||
const apis = {
|
||||
timepointApi,
|
||||
measurementApi
|
||||
};
|
||||
|
||||
Object.assign(OHIF.viewer, apis);
|
||||
|
||||
const patientId = studies[0] && studies[0].patientId;
|
||||
timepointApi.retrieveTimepoints({ patientId });
|
||||
|
||||
// TODO: Retrieve measurements and sync them with tool data
|
||||
// measurementApi.retrieveMeasurements(patientId, [currentTimepointId]);
|
||||
// measurementApi.syncMeasurementsAndToolData();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
const displayFunction = data => {
|
||||
return data.text || '';
|
||||
};
|
||||
|
||||
export default {
|
||||
id: 'arrowAnnotate',
|
||||
name: 'ArrowAnnotate',
|
||||
toolGroup: 'allTools',
|
||||
cornerstoneToolType: 'arrowAnnotate',
|
||||
options: {
|
||||
measurementTable: {
|
||||
displayFunction
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,22 @@
|
||||
const displayFunction = data => {
|
||||
let meanValue = '';
|
||||
if (data.meanStdDev && data.meanStdDev.mean) {
|
||||
meanValue = data.meanStdDev.mean.toFixed(2) + ' HU';
|
||||
}
|
||||
return meanValue;
|
||||
// let meanValue = data.meanStdDev && data.meanStdDev.mean || 0;
|
||||
// return numberWithCommas(meanValue).toFixed(2) + ' HU';
|
||||
//return data.meanStdDev.mean.toFixed(2);
|
||||
};
|
||||
|
||||
export default {
|
||||
id: 'ellipticalRoi',
|
||||
name: 'Ellipse',
|
||||
toolGroup: 'allTools',
|
||||
cornerstoneToolType: 'ellipticalRoi',
|
||||
options: {
|
||||
measurementTable: {
|
||||
displayFunction
|
||||
}
|
||||
}
|
||||
};
|
||||
21
Packages-react/ohif-viewer/src/measurementTools/index.js
Normal file
21
Packages-react/ohif-viewer/src/measurementTools/index.js
Normal file
@ -0,0 +1,21 @@
|
||||
import length from './length';
|
||||
import ellipticalRoi from './ellipticalRoi';
|
||||
import rectangleRoi from './rectangleRoi';
|
||||
import simpleAngle from './simpleAngle';
|
||||
import arrowAnnotate from './arrowAnnotate';
|
||||
|
||||
const trackedTools = [
|
||||
length,
|
||||
ellipticalRoi,
|
||||
rectangleRoi,
|
||||
simpleAngle,
|
||||
arrowAnnotate
|
||||
];
|
||||
|
||||
export default [
|
||||
{
|
||||
id: 'allTools',
|
||||
name: 'Measurements',
|
||||
childTools: trackedTools
|
||||
}
|
||||
];
|
||||
19
Packages-react/ohif-viewer/src/measurementTools/length.js
Normal file
19
Packages-react/ohif-viewer/src/measurementTools/length.js
Normal file
@ -0,0 +1,19 @@
|
||||
const displayFunction = data => {
|
||||
let lengthValue = '';
|
||||
if (data.length) {
|
||||
lengthValue = data.length.toFixed(2) + ' mm';
|
||||
}
|
||||
return lengthValue;
|
||||
};
|
||||
|
||||
export default {
|
||||
id: 'length',
|
||||
name: 'Length',
|
||||
toolGroup: 'allTools',
|
||||
cornerstoneToolType: 'length',
|
||||
options: {
|
||||
measurementTable: {
|
||||
displayFunction
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,19 @@
|
||||
const displayFunction = data => {
|
||||
let meanValue = '';
|
||||
if (data.meanStdDev && data.meanStdDev.mean) {
|
||||
meanValue = data.meanStdDev.mean.toFixed(2) + ' HU';
|
||||
}
|
||||
return meanValue;
|
||||
};
|
||||
|
||||
export default {
|
||||
id: 'rectangleRoi',
|
||||
name: 'Rectangle',
|
||||
toolGroup: 'allTools',
|
||||
cornerstoneToolType: 'rectangleRoi',
|
||||
options: {
|
||||
measurementTable: {
|
||||
displayFunction
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,19 @@
|
||||
const displayFunction = data => {
|
||||
let text = '';
|
||||
if (data.rAngle) {
|
||||
text = data.rAngle.toFixed(2) + String.fromCharCode(parseInt('00B0', 16));
|
||||
}
|
||||
return text;
|
||||
};
|
||||
|
||||
export default {
|
||||
id: 'simpleAngle',
|
||||
name: 'SimpleAngle',
|
||||
toolGroup: 'allTools',
|
||||
cornerstoneToolType: 'simpleAngle',
|
||||
options: {
|
||||
measurementTable: {
|
||||
displayFunction
|
||||
}
|
||||
}
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user