ami-cjs.js
Version:
<p align="center"> <img src="https://cloud.githubusercontent.com/assets/214063/23213764/78ade038-f90c-11e6-8208-4fcade5f3832.png" width="60%"> </p>
754 lines (635 loc) • 22.8 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _core = require('../core/core.intersections');
var _core2 = _interopRequireDefault(_core);
var _core3 = require('../core/core.validators');
var _core4 = _interopRequireDefault(_core3);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/**
* Orthographic camera from THREE.JS with some extra convenience
* functionalities.
*
* @example
* //
* //
*
* @module cameras/orthographic
*/
var CamerasOrthographic = function (_THREE$OrthographicCa) {
_inherits(CamerasOrthographic, _THREE$OrthographicCa);
function CamerasOrthographic(left, right, top, bottom, near, far) {
_classCallCheck(this, CamerasOrthographic);
var _this = _possibleConstructorReturn(this, (CamerasOrthographic.__proto__ || Object.getPrototypeOf(CamerasOrthographic)).call(this, left, right, top, bottom, near, far));
_this._front = null;
_this._back = null;
_this._directions = [new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 0, 1)];
_this._directionsLabel = ['A', 'P', // TOP/BOTTOM
'L', 'R', // LEFT/RIGHT
'I', 'S'];
_this._orientation = 'default';
_this._convention = 'radio';
_this._stackOrientation = 0;
_this._right = null;
_this._up = null;
_this._direction = null;
_this._controls = null;
_this._box = null;
_this._canvas = {
width: null,
height: null
};
_this._fromFront = true;
_this._angle = 0;
return _this;
}
/**
* Initialize orthographic camera variables
*/
_createClass(CamerasOrthographic, [{
key: 'init',
value: function init(xCosine, yCosine, zCosine, controls, box, canvas) {
// DEPRECATED
console.warn('cameras.orthographic.init(...) is deprecated.\n Use .cosines, .controls, .box and .canvas instead.');
//
if (!(_core4.default.vector3(xCosine) && _core4.default.vector3(yCosine) && _core4.default.vector3(zCosine) && _core4.default.box(box) && controls)) {
window.console.log('Invalid input provided.');
return false;
}
this._right = xCosine;
this._up = this._adjustTopDirection(xCosine, yCosine);
this._direction = new THREE.Vector3().crossVectors(this._right, this._up);
this._controls = controls;
this._box = box;
this._canvas = canvas;
var ray = {
position: this._box.center,
direction: this._direction
};
var intersections = this._orderIntersections(_core2.default.rayBox(ray, this._box), this._direction);
this._front = intersections[0];
this._back = intersections[1];
// set default values
this.up.set(this._up.x, this._up.y, this._up.z);
this._updateCanvas();
this._updatePositionAndTarget(this._front, this._back);
this._updateMatrices();
this._updateDirections();
}
}, {
key: 'update',
value: function update() {
// http://www.grahamwideman.com/gw/brain/orientation/orientterms.htm
// do magics depending on orientation and convention
// also needs a default mode
if (this._orientation === 'default') {
switch (this._getMaxIndex(this._directions[2])) {
case 0:
this._orientation = 'sagittal';
break;
case 1:
this._orientation = 'coronal';
break;
case 2:
this._orientation = 'axial';
break;
default:
this._orientation = 'free';
break;
}
}
if (this._orientation === 'free') {
this._right = this._directions[0];
this._up = this._directions[1];
this._direction = this._directions[2];
} else {
var leftIndex = this.leftDirection();
var leftDirection = this._directions[leftIndex];
var posteriorIndex = this.posteriorDirection();
var posteriorDirection = this._directions[posteriorIndex];
var superiorIndex = this.superiorDirection();
var superiorDirection = this._directions[superiorIndex];
if (this._convention === 'radio') {
switch (this._orientation) {
case 'axial':
// up vector is 'anterior'
if (posteriorDirection.y > 0) {
posteriorDirection.negate();
}
// looking towards superior
if (superiorDirection.z < 0) {
superiorDirection.negate();
}
//
this._right = leftDirection; // does not matter right/left
this._up = posteriorDirection;
this._direction = superiorDirection;
break;
case 'coronal':
// up vector is 'superior'
if (superiorDirection.z < 0) {
superiorDirection.negate();
}
// looking towards posterior
if (posteriorDirection.y < 0) {
posteriorDirection.negate();
}
//
this._right = leftDirection; // does not matter right/left
this._up = superiorDirection;
this._direction = posteriorDirection;
break;
case 'sagittal':
// up vector is 'superior'
if (superiorDirection.z < 0) {
superiorDirection.negate();
}
// looking towards right
if (leftDirection.x > 0) {
leftDirection.negate();
}
//
this._right = posteriorDirection; // does not matter right/left
this._up = superiorDirection;
this._direction = leftDirection;
break;
default:
console.warn('"' + this._orientation + '" orientation is not valid.\n (choices: axial, coronal, sagittal)');
break;
}
} else if (this._convention === 'neuro') {
switch (this._orientation) {
case 'axial':
// up vector is 'anterior'
if (posteriorDirection.y > 0) {
posteriorDirection.negate();
}
// looking towards inferior
if (superiorDirection.z > 0) {
superiorDirection.negate();
}
//
this._right = leftDirection; // does not matter right/left
this._up = posteriorDirection;
this._direction = superiorDirection;
break;
case 'coronal':
// up vector is 'superior'
if (superiorDirection.z < 0) {
superiorDirection.negate();
}
// looking towards anterior
if (posteriorDirection.y > 0) {
posteriorDirection.negate();
}
//
this._right = leftDirection; // does not matter right/left
this._up = superiorDirection;
this._direction = posteriorDirection;
break;
case 'sagittal':
// up vector is 'superior'
if (superiorDirection.z < 0) {
superiorDirection.negate();
}
// looking towards right
if (leftDirection.x > 0) {
leftDirection.negate();
}
//
this._right = posteriorDirection; // does not matter right/left
this._up = superiorDirection;
this._direction = leftDirection;
break;
default:
console.warn('"' + this._orientation + '" orientation is not valid.\n (choices: axial, coronal, sagittal)');
break;
}
} else {
console.warn(this._convention + ' is not valid (choices: radio, neuro)');
}
}
// that is what determines left/right
var ray = {
position: this._box.center,
direction: this._direction
};
var intersections = this._orderIntersections(_core2.default.rayBox(ray, this._box), this._direction);
this._front = intersections[0];
this._back = intersections[1];
// set default values
this.up.set(this._up.x, this._up.y, this._up.z);
this._updateCanvas();
this._updatePositionAndTarget(this._front, this._back);
this._updateMatrices();
this._updateDirections();
}
}, {
key: 'leftDirection',
value: function leftDirection() {
return this._findMaxIndex(this._directions, 0);
}
}, {
key: 'posteriorDirection',
value: function posteriorDirection() {
return this._findMaxIndex(this._directions, 1);
}
}, {
key: 'superiorDirection',
value: function superiorDirection() {
return this._findMaxIndex(this._directions, 2);
}
/**
* Invert rows in the current slice.
* Inverting rows in 2 steps:
* * Flip the "up" vector
* * Look at the slice from the other side
*/
}, {
key: 'invertRows',
value: function invertRows() {
// flip "up" vector
// we flip up first because invertColumns update projectio matrices
this.up.multiplyScalar(-1);
this.invertColumns();
this._updateDirections();
}
/**
* Invert rows in the current slice.
* Inverting rows in 1 step:
* * Look at the slice from the other side
*/
}, {
key: 'invertColumns',
value: function invertColumns() {
this.center();
// rotate 180 degrees around the up vector...
var oppositePosition = this._oppositePosition(this.position);
// update posistion and target
// clone is needed because this.position is overwritten in method
this._updatePositionAndTarget(oppositePosition, this.position.clone());
this._updateMatrices();
this._fromFront = !this._fromFront;
this._angle %= 360;
this._angle = 360 - this._angle;
this._updateDirections();
}
/**
* Center slice in the camera FOV.
* It also updates the controllers properly.
* We can center a camera from the front or from the back.
*/
}, {
key: 'center',
value: function center() {
if (this._fromFront) {
this._updatePositionAndTarget(this._front, this._back);
} else {
this._updatePositionAndTarget(this._back, this._front);
}
this._updateMatrices();
this._updateDirections();
}
/**
* Pi/2 rotation around the zCosine axis.
* Clock-wise rotation from the user point of view.
*/
}, {
key: 'rotate',
value: function rotate() {
var angle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
this.center();
var computedAngle = 90;
var clockwise = 1;
if (!this._fromFront) {
clockwise = -1;
}
if (angle === null) {
computedAngle *= -clockwise;
this._angle += 90;
} else {
computedAngle = 360 - clockwise * (angle - this._angle);
this._angle = angle;
}
this._angle %= 360;
// Rotate the up vector around the "zCosine"
var rotation = new THREE.Matrix4().makeRotationAxis(this._direction, computedAngle * Math.PI / 180);
this.up.applyMatrix4(rotation);
this._updateMatrices();
this._updateDirections();
}
// dimensions[0] // width
// dimensions[1] // height
// direction= 0 width, 1 height, 2 best
// factor
}, {
key: 'fitBox',
value: function fitBox() {
var direction = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var factor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1.5;
//
// if (!(dimensions && dimensions.length >= 2)) {
// window.console.log('Invalid dimensions container.');
// window.console.log(dimensions);
// return false;
// }
//
var zoom = 1;
// update zoom
switch (direction) {
case 0:
zoom = factor * this._computeZoom(this._canvas.width, this._right);
break;
case 1:
zoom = factor * this._computeZoom(this._canvas.height, this._up);
break;
case 2:
zoom = factor * Math.min(this._computeZoom(this._canvas.width, this._right), this._computeZoom(this._canvas.height, this._up));
break;
default:
break;
}
if (!zoom) {
return false;
}
this.zoom = zoom;
this.center();
}
}, {
key: '_adjustTopDirection',
value: function _adjustTopDirection(horizontalDirection, verticalDirection) {
var vMaxIndex = this._getMaxIndex(verticalDirection);
// should handle vMax index === 0
if (vMaxIndex === 2 && verticalDirection.getComponent(vMaxIndex) < 0 || vMaxIndex === 1 && verticalDirection.getComponent(vMaxIndex) > 0 || vMaxIndex === 0 && verticalDirection.getComponent(vMaxIndex) > 0) {
verticalDirection.negate();
}
return verticalDirection;
}
}, {
key: '_getMaxIndex',
value: function _getMaxIndex(vector) {
// init with X value
var maxValue = Math.abs(vector.x);
var index = 0;
if (Math.abs(vector.y) > maxValue) {
maxValue = Math.abs(vector.y);
index = 1;
}
if (Math.abs(vector.z) > maxValue) {
index = 2;
}
return index;
}
}, {
key: '_findMaxIndex',
value: function _findMaxIndex(directions, target) {
// get index of the most superior direction
var maxIndices = this._getMaxIndices(directions);
for (var i = 0; i < maxIndices.length; i++) {
if (maxIndices[i] === target) {
return i;
}
}
}
}, {
key: '_getMaxIndices',
value: function _getMaxIndices(directions) {
var indices = [];
indices.push(this._getMaxIndex(directions[0]));
indices.push(this._getMaxIndex(directions[1]));
indices.push(this._getMaxIndex(directions[2]));
return indices;
}
}, {
key: '_orderIntersections',
value: function _orderIntersections(intersections, direction) {
var ordered = intersections[0].dot(direction) < intersections[1].dot(direction);
if (!ordered) {
return [intersections[1], intersections[0]];
}
return intersections;
}
}, {
key: '_updateCanvas',
value: function _updateCanvas() {
var camFactor = 2;
this.left = -this._canvas.width / camFactor;
this.right = this._canvas.width / camFactor;
this.top = this._canvas.height / camFactor;
this.bottom = -this._canvas.height / camFactor;
this._updateMatrices();
this.controls.handleResize();
}
}, {
key: '_oppositePosition',
value: function _oppositePosition(position) {
var oppositePosition = position.clone();
// center world postion around box center
oppositePosition.sub(this._box.center);
// rotate
var rotation = new THREE.Matrix4().makeRotationAxis(this.up, Math.PI);
oppositePosition.applyMatrix4(rotation);
// translate back to world position
oppositePosition.add(this._box.center);
return oppositePosition;
}
}, {
key: '_computeZoom',
value: function _computeZoom(dimension, direction) {
if (!(dimension && dimension > 0)) {
window.console.log('Invalid dimension provided.');
window.console.log(dimension);
return false;
}
// ray
var ray = {
position: this._box.center.clone(),
direction: direction
};
var intersections = _core2.default.rayBox(ray, this._box);
if (intersections.length < 2) {
window.console.log('Can not adjust the camera ( < 2 intersections).');
window.console.log(ray);
window.console.log(this._box);
return false;
}
return dimension / intersections[0].distanceTo(intersections[1]);
}
}, {
key: '_updatePositionAndTarget',
value: function _updatePositionAndTarget(position, target) {
// position
this.position.set(position.x, position.y, position.z);
// targets
this.lookAt(target.x, target.y, target.z);
this._controls.target.set(target.x, target.y, target.z);
}
}, {
key: '_updateMatrices',
value: function _updateMatrices() {
this._controls.update();
// THEN camera
this.updateProjectionMatrix();
this.updateMatrixWorld();
}
}, {
key: '_updateLabels',
value: function _updateLabels() {
this._directionsLabel = [this._vector2Label(this._up), this._vector2Label(this._up.clone().negate()), this._vector2Label(this._right), this._vector2Label(this._right.clone().negate()), this._vector2Label(this._direction), this._vector2Label(this._direction.clone().negate())];
}
}, {
key: '_vector2Label',
value: function _vector2Label(direction) {
var index = this._getMaxIndex(direction);
// set vector max value to 1
var scaledDirection = direction.clone().divideScalar(Math.abs(direction.getComponent(index)));
var delta = 0.2;
var label = '';
// loop through components of the vector
for (var i = 0; i < 3; i++) {
if (i === 0) {
if (scaledDirection.getComponent(i) + delta >= 1) {
label += 'L';
} else if (scaledDirection.getComponent(i) - delta <= -1) {
label += 'R';
}
}
if (i === 1) {
if (scaledDirection.getComponent(i) + delta >= 1) {
label += 'P';
} else if (scaledDirection.getComponent(i) - delta <= -1) {
label += 'A';
}
}
if (i === 2) {
if (scaledDirection.getComponent(i) + delta >= 1) {
label += 'S';
} else if (scaledDirection.getComponent(i) - delta <= -1) {
label += 'I';
}
}
}
return label;
}
}, {
key: '_updateDirections',
value: function _updateDirections() {
// up is correct
this._up = this.up.clone();
// direction
var pLocal = new THREE.Vector3(0, 0, -1);
var pWorld = pLocal.applyMatrix4(this.matrixWorld);
this._direction = pWorld.sub(this.position).normalize();
// right
this._right = new THREE.Vector3().crossVectors(this._direction, this.up);
// update labels accordingly
this._updateLabels();
}
}, {
key: 'controls',
set: function set(controls) {
this._controls = controls;
},
get: function get() {
return this._controls;
}
}, {
key: 'box',
set: function set(box) {
this._box = box;
},
get: function get() {
return this._box;
}
}, {
key: 'canvas',
set: function set(canvas) {
this._canvas = canvas;
this._updateCanvas();
},
get: function get() {
return this._canvas;
}
}, {
key: 'angle',
set: function set(angle) {
this.rotate(angle);
},
get: function get() {
return this._angle;
}
}, {
key: 'directions',
set: function set(directions) {
this._directions = directions;
},
get: function get() {
return this._directions;
}
}, {
key: 'convention',
set: function set(convention) {
this._convention = convention;
},
get: function get() {
return this._convention;
}
}, {
key: 'orientation',
set: function set(orientation) {
this._orientation = orientation;
},
get: function get() {
return this._orientation;
}
}, {
key: 'directionsLabel',
set: function set(directionsLabel) {
this._directionsLabel = directionsLabel;
},
get: function get() {
return this._directionsLabel;
}
}, {
key: 'stackOrientation',
set: function set(stackOrientation) {
this._stackOrientation = stackOrientation;
if (this._stackOrientation === 0) {
this._orientation = 'default';
} else {
var maxIndex = this._getMaxIndex(this._directions[(this._stackOrientation + 2) % 3]);
if (maxIndex === 0) {
this._orientation = 'sagittal';
} else if (maxIndex === 1) {
this._orientation = 'coronal';
} else if (maxIndex === 2) {
this._orientation = 'axial';
}
}
},
get: function get() {
//
if (this._orientation === 'default') {
this._stackOrientation = 0;
} else {
var maxIndex = this._getMaxIndex(this._direction);
if (maxIndex === this._getMaxIndex(this._directions[2])) {
this._stackOrientation = 0;
} else if (maxIndex === this._getMaxIndex(this._directions[0])) {
this._stackOrientation = 1;
} else if (maxIndex === this._getMaxIndex(this._directions[1])) {
this._stackOrientation = 2;
}
}
return this._stackOrientation;
}
}]);
return CamerasOrthographic;
}(THREE.OrthographicCamera);
exports.default = CamerasOrthographic;
module.exports = exports['default'];