// namespaces
var dwv = dwv || {};
dwv.ctrl = dwv.ctrl || {};
/**
* View controller.
*
* @param {dwv.image.View} view The associated view.
* @class
*/
dwv.ctrl.ViewController = function (view) {
// closure to self
var self = this;
// third dimension player ID (created by setInterval)
var playerID = null;
// setup the plane helper
var planeHelper = new dwv.image.PlaneHelper(
view.getImage().getGeometry().getSpacing(),
view.getOrientation()
);
/**
* Get the plane helper.
*
* @returns {object} The helper.
*/
this.getPlaneHelper = function () {
return planeHelper;
};
/**
* Initialise the controller.
*/
this.initialise = function () {
// set window/level to first preset
this.setWindowLevelPresetById(0);
// default position
this.setCurrentPosition2D(0, 0);
};
/**
* Get the window/level presets names.
*
* @returns {Array} The presets names.
*/
this.getWindowLevelPresetsNames = function () {
return view.getWindowPresetsNames();
};
/**
* Add window/level presets to the view.
*
* @param {object} presets A preset object.
* @returns {object} The list of presets.
*/
this.addWindowLevelPresets = function (presets) {
return view.addWindowPresets(presets);
};
/**
* Set the window level to the preset with the input name.
*
* @param {string} name The name of the preset to activate.
*/
this.setWindowLevelPreset = function (name) {
view.setWindowLevelPreset(name);
};
/**
* Set the window level to the preset with the input id.
*
* @param {number} id The id of the preset to activate.
*/
this.setWindowLevelPresetById = function (id) {
view.setWindowLevelPresetById(id);
};
/**
* Check if the controller is playing.
*
* @returns {boolean} True if the controler is playing.
*/
this.isPlaying = function () {
return (playerID !== null);
};
/**
* Get the current position.
*
* @returns {dwv.math.Point} The position.
*/
this.getCurrentPosition = function () {
return view.getCurrentPosition();
};
/**
* Get the current index.
*
* @returns {dwv.math.Index} The current index.
*/
this.getCurrentIndex = function () {
return view.getCurrentIndex();
};
/**
* Get the current oriented position.
*
* @returns {dwv.math.Point} The position.
*/
this.getCurrentOrientedPosition = function () {
var res = view.getCurrentPosition();
// values = orientation * orientedValues
// -> inv(orientation) * values = orientedValues
if (typeof view.getOrientation() !== 'undefined') {
res = view.getOrientation().getInverse().getAbs().multiplyVector3D(res);
}
return res;
};
/**
* Get the scroll index.
*
* @returns {number} The index.
*/
this.getScrollIndex = function () {
return view.getScrollIndex();
};
/**
* Get the current scroll index value.
*
* @returns {object} The value.
*/
this.getCurrentScrollIndexValue = function () {
return view.getCurrentIndex().get(view.getScrollIndex());
};
/**
* Get the current scroll position value.
*
* @returns {object} The value.
*/
this.getCurrentScrollPosition = function () {
var scrollIndex = view.getScrollIndex();
return view.getCurrentPosition().get(scrollIndex);
};
/**
* Generate display image data to be given to a canvas.
*
* @param {Array} array The array to fill in.
*/
this.generateImageData = function (array) {
view.generateImageData(array);
};
/**
* Set the associated image.
*
* @param {Image} img The associated image.
*/
this.setImage = function (img) {
view.setImage(img);
};
/**
* Get the current spacing.
*
* @returns {Array} The 2D spacing.
*/
this.get2DSpacing = function () {
var spacing = view.getImage().getGeometry().getSpacing();
return [spacing.get(0), spacing.get(1)];
};
/**
* Get some values from the associated image in a region.
*
* @param {dwv.math.Point2D} min Minimum point.
* @param {dwv.math.Point2D} max Maximum point.
* @returns {Array} A list of values.
*/
this.getImageRegionValues = function (min, max) {
var image = view.getImage();
var orientation = view.getOrientation();
var position = this.getCurrentIndex();
var rescaled = true;
// created oriented slice if needed
if (!dwv.math.isIdentityMat33(orientation)) {
// generate slice values
var sliceIter = dwv.image.getSliceIterator(
image,
position,
rescaled,
orientation
);
var sliceValues = dwv.image.getIteratorValues(sliceIter);
// oriented geometry
var orientedSize = image.getGeometry().getSize(orientation);
var sizeValues = orientedSize.getValues();
sizeValues[2] = 1;
var sliceSize = new dwv.image.Size(sizeValues);
var orientedSpacing = image.getGeometry().getSpacing(orientation);
var spacingValues = orientedSpacing.getValues();
spacingValues[2] = 1;
var sliceSpacing = new dwv.image.Spacing(spacingValues);
var sliceOrigin = new dwv.math.Point3D(0, 0, 0);
var sliceGeometry =
new dwv.image.Geometry(sliceOrigin, sliceSize, sliceSpacing);
// slice image
image = new dwv.image.Image(sliceGeometry, sliceValues);
// update position
position = new dwv.math.Index([0, 0, 0]);
rescaled = false;
}
// get region values
var iter = dwv.image.getRegionSliceIterator(
image, position, rescaled, min, max);
var values = [];
if (iter) {
values = dwv.image.getIteratorValues(iter);
}
return values;
};
/**
* Get some values from the associated image in variable regions.
*
* @param {Array} regions A list of regions.
* @returns {Array} A list of values.
*/
this.getImageVariableRegionValues = function (regions) {
var iter = dwv.image.getVariableRegionSliceIterator(
view.getImage(),
this.getCurrentIndex(),
true, regions
);
var values = [];
if (iter) {
values = dwv.image.getIteratorValues(iter);
}
return values;
};
/**
* Can the image values be quantified?
*
* @returns {boolean} True if possible.
*/
this.canQuantifyImage = function () {
return view.getImage().canQuantify();
};
/**
* Can window and level be applied to the data?
*
* @returns {boolean} True if possible.
*/
this.canWindowLevel = function () {
return view.getImage().canWindowLevel();
};
/**
* Can the data be scrolled?
*
* @returns {boolean} True if the data has either the third dimension
* or above greater than one.
*/
this.canScroll = function () {
return view.getImage().canScroll(view.getOrientation());
};
/**
* Get the image size.
*
* @returns {dwv.image.Size} The size.
*/
this.getImageSize = function () {
return view.getImage().getGeometry().getSize();
};
/**
* Set the current position.
*
* @param {dwv.math.Point} pos The position.
* @param {boolean} silent If true, does not fire a positionchange event.
* @returns {boolean} False if not in bounds.
*/
this.setCurrentPosition = function (pos, silent) {
return view.setCurrentPosition(pos, silent);
};
/**
* Set the current 2D (x,y) position.
*
* @param {number} x The column position.
* @param {number} y The row position.
* @returns {boolean} False if not in bounds.
*/
this.setCurrentPosition2D = function (x, y) {
return view.setCurrentPosition(
this.getPositionFromPlanePoint({x: x, y: y}));
};
/**
* Set the current index.
*
* @param {dwv.math.Index} index The index.
* @param {boolean} silent If true, does not fire a positionchange event.
* @returns {boolean} False if not in bounds.
*/
this.setCurrentIndex = function (index, silent) {
return view.setCurrentIndex(index, silent);
};
/**
* Get a 3D position from a plane 2D position.
*
* @param {dwv.math.Point2D} point2D The 2D position as {x,y}.
* @returns {dwv.math.Point} The 3D point.
*/
this.getPositionFromPlanePoint = function (point2D) {
// keep third direction
var k = this.getCurrentScrollIndexValue();
var planePoint = new dwv.math.Point3D(point2D.x, point2D.y, k);
// de-orient
var point = planeHelper.getDeOrientedVector3D(planePoint);
// ~indexToWorld to not loose precision
var geometry = view.getImage().getGeometry();
var point3D = geometry.pointToWorld(point);
// merge with current position to keep extra dimensions
return this.getCurrentPosition().mergeWith3D(point3D);
};
/**
* Get a plane 3D position from a plane 2D position: does not compensate
* for the image origin. Needed for setting the scale center...
*
* @param {dwv.math.Point2D} point2D The 2D position as {x,y}.
* @returns {dwv.math.Point3D} The 3D point.
*/
this.getPlanePositionFromPlanePoint = function (point2D) {
// keep third direction
var k = this.getCurrentScrollIndexValue();
var planePoint = new dwv.math.Point3D(point2D.x, point2D.y, k);
// de-orient
var point = planeHelper.getDeOrientedVector3D(planePoint);
// ~indexToWorld to not loose precision
var geometry = view.getImage().getGeometry();
var spacing = geometry.getSpacing();
return new dwv.math.Point3D(
point.getX() * spacing.get(0),
point.getY() * spacing.get(1),
point.getZ() * spacing.get(2));
};
/**
* Get a 3D offset from a plane one.
*
* @param {object} offset2D The plane offset as {x,y}.
* @returns {dwv.math.Vector3D} The 3D world offset.
*/
this.getOffset3DFromPlaneOffset = function (offset2D) {
return planeHelper.getOffset3DFromPlaneOffset(offset2D);
};
/**
* Increment the provided dimension.
*
* @param {number} dim The dimension to increment.
* @param {boolean} silent Do not send event.
* @returns {boolean} False if not in bounds.
*/
this.incrementIndex = function (dim, silent) {
return view.incrementIndex(dim, silent);
};
/**
* Decrement the provided dimension.
*
* @param {number} dim The dimension to increment.
* @param {boolean} silent Do not send event.
* @returns {boolean} False if not in bounds.
*/
this.decrementIndex = function (dim, silent) {
return view.decrementIndex(dim, silent);
};
/**
* Decrement the scroll dimension index.
*
* @param {boolean} silent Do not send event.
* @returns {boolean} False if not in bounds.
*/
this.decrementScrollIndex = function (silent) {
return view.decrementScrollIndex(silent);
};
/**
* Increment the scroll dimension index.
*
* @param {boolean} silent Do not send event.
* @returns {boolean} False if not in bounds.
*/
this.incrementScrollIndex = function (silent) {
return view.incrementScrollIndex(silent);
};
/**
* Scroll play: loop through all slices.
*/
this.play = function () {
// ensure data is scrollable: dim >= 3
if (!this.canScroll()) {
return;
}
if (playerID === null) {
var image = view.getImage();
var recommendedDisplayFrameRate =
image.getMeta().RecommendedDisplayFrameRate;
var milliseconds = view.getPlaybackMilliseconds(
recommendedDisplayFrameRate);
var size = image.getGeometry().getSize();
var canScroll3D = size.canScroll3D();
playerID = setInterval(function () {
var canDoMore = false;
if (canScroll3D) {
canDoMore = self.incrementScrollIndex();
} else {
canDoMore = self.incrementIndex(3);
}
// end of scroll, loop back
if (!canDoMore) {
var pos1 = self.getCurrentIndex();
var values = pos1.getValues();
var orientation = view.getOrientation();
if (canScroll3D) {
values[orientation.getThirdColMajorDirection()] = 0;
} else {
values[3] = 0;
}
var index = new dwv.math.Index(values);
var geometry = view.getImage().getGeometry();
self.setCurrentPosition(geometry.indexToWorld(index));
}
}, milliseconds);
} else {
this.stop();
}
};
/**
* Stop scroll playing.
*/
this.stop = function () {
if (playerID !== null) {
clearInterval(playerID);
playerID = null;
}
};
/**
* Get the window/level.
*
* @returns {object} The window center and width.
*/
this.getWindowLevel = function () {
return {
width: view.getCurrentWindowLut().getWindowLevel().getWidth(),
center: view.getCurrentWindowLut().getWindowLevel().getCenter()
};
};
/**
* Set the window/level.
*
* @param {number} wc The window center.
* @param {number} ww The window width.
*/
this.setWindowLevel = function (wc, ww) {
view.setWindowLevel(wc, ww);
};
/**
* Get the colour map.
*
* @returns {object} The colour map.
*/
this.getColourMap = function () {
return view.getColourMap();
};
/**
* Set the colour map.
*
* @param {object} colourMap The colour map.
*/
this.setColourMap = function (colourMap) {
view.setColourMap(colourMap);
};
/**
* Set the view per value alpha function.
*
* @param {Function} func The function.
*/
this.setViewAlphaFunction = function (func) {
view.setAlphaFunction(func);
};
/**
* Set the colour map from a name.
*
* @param {string} name The name of the colour map to set.
*/
this.setColourMapFromName = function (name) {
// check if we have it
if (!dwv.tool.colourMaps[name]) {
throw new Error('Unknown colour map: \'' + name + '\'');
}
// enable it
this.setColourMap(dwv.tool.colourMaps[name]);
};
}; // class ViewController