ohif-viewer/Packages/cornerstone/client/cornerstoneMath.js

1779 lines
43 KiB
JavaScript

/*! cornerstoneMath - v0.1.2 - 2015-08-31 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstoneMath */
// Begin Source: src/vector3.js
// Based on THREE.JS
var cornerstoneMath = (function (cornerstoneMath) {
"use strict";
if(cornerstoneMath === undefined) {
cornerstoneMath = {};
}
cornerstoneMath.Vector3 = function ( x, y, z ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
};
cornerstoneMath.Vector3.prototype = {
constructor: cornerstoneMath.Vector3,
set: function ( x, y, z ) {
this.x = x;
this.y = y;
this.z = z;
return this;
},
setX: function ( x ) {
this.x = x;
return this;
},
setY: function ( y ) {
this.y = y;
return this;
},
setZ: function ( z ) {
this.z = z;
return this;
},
setComponent: function ( index, value ) {
switch ( index ) {
case 0: this.x = value; break;
case 1: this.y = value; break;
case 2: this.z = value; break;
default: throw new Error( "index is out of range: " + index );
}
},
getComponent: function ( index ) {
switch ( index ) {
case 0: return this.x;
case 1: return this.y;
case 2: return this.z;
default: throw new Error( "index is out of range: " + index );
}
},
copy: function ( v ) {
this.x = v.x;
this.y = v.y;
this.z = v.z;
return this;
},
add: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'DEPRECATED: Vector3\'s .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
return this.addVectors( v, w );
}
this.x += v.x;
this.y += v.y;
this.z += v.z;
return this;
},
addScalar: function ( s ) {
this.x += s;
this.y += s;
this.z += s;
return this;
},
addVectors: function ( a, b ) {
this.x = a.x + b.x;
this.y = a.y + b.y;
this.z = a.z + b.z;
return this;
},
sub: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'DEPRECATED: Vector3\'s .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
return this.subVectors( v, w );
}
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
return this;
},
subVectors: function ( a, b ) {
this.x = a.x - b.x;
this.y = a.y - b.y;
this.z = a.z - b.z;
return this;
},
multiply: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'DEPRECATED: Vector3\'s .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
return this.multiplyVectors( v, w );
}
this.x *= v.x;
this.y *= v.y;
this.z *= v.z;
return this;
},
multiplyScalar: function ( scalar ) {
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
return this;
},
multiplyVectors: function ( a, b ) {
this.x = a.x * b.x;
this.y = a.y * b.y;
this.z = a.z * b.z;
return this;
},
applyAxisAngle: function () {
var quaternion;
return function ( axis, angle ) {
if ( quaternion === undefined ) quaternion = new cornerstoneMath.Quaternion();
this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
return this;
};
}(),
applyMatrix3: function ( m ) {
var x = this.x;
var y = this.y;
var z = this.z;
var e = m.elements;
this.x = e[0] * x + e[3] * y + e[6] * z;
this.y = e[1] * x + e[4] * y + e[7] * z;
this.z = e[2] * x + e[5] * y + e[8] * z;
return this;
},
applyMatrix4: function ( m ) {
// input: THREE.Matrix4 affine matrix
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
this.x = e[0] * x + e[4] * y + e[8] * z + e[12];
this.y = e[1] * x + e[5] * y + e[9] * z + e[13];
this.z = e[2] * x + e[6] * y + e[10] * z + e[14];
return this;
},
applyProjection: function ( m ) {
// input: THREE.Matrix4 projection matrix
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
var d = 1 / ( e[3] * x + e[7] * y + e[11] * z + e[15] ); // perspective divide
this.x = ( e[0] * x + e[4] * y + e[8] * z + e[12] ) * d;
this.y = ( e[1] * x + e[5] * y + e[9] * z + e[13] ) * d;
this.z = ( e[2] * x + e[6] * y + e[10] * z + e[14] ) * d;
return this;
},
applyQuaternion: function ( q ) {
var x = this.x;
var y = this.y;
var z = this.z;
var qx = q.x;
var qy = q.y;
var qz = q.z;
var qw = q.w;
// calculate quat * vector
var ix = qw * x + qy * z - qz * y;
var iy = qw * y + qz * x - qx * z;
var iz = qw * z + qx * y - qy * x;
var iw = -qx * x - qy * y - qz * z;
// calculate result * inverse quat
this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
return this;
},
transformDirection: function ( m ) {
// input: THREE.Matrix4 affine matrix
// vector interpreted as a direction
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
this.x = e[0] * x + e[4] * y + e[8] * z;
this.y = e[1] * x + e[5] * y + e[9] * z;
this.z = e[2] * x + e[6] * y + e[10] * z;
this.normalize();
return this;
},
divide: function ( v ) {
this.x /= v.x;
this.y /= v.y;
this.z /= v.z;
return this;
},
divideScalar: function ( scalar ) {
if ( scalar !== 0 ) {
var invScalar = 1 / scalar;
this.x *= invScalar;
this.y *= invScalar;
this.z *= invScalar;
} else {
this.x = 0;
this.y = 0;
this.z = 0;
}
return this;
},
min: function ( v ) {
if ( this.x > v.x ) {
this.x = v.x;
}
if ( this.y > v.y ) {
this.y = v.y;
}
if ( this.z > v.z ) {
this.z = v.z;
}
return this;
},
max: function ( v ) {
if ( this.x < v.x ) {
this.x = v.x;
}
if ( this.y < v.y ) {
this.y = v.y;
}
if ( this.z < v.z ) {
this.z = v.z;
}
return this;
},
clamp: function ( min, max ) {
// This function assumes min < max, if this assumption isn't true it will not operate correctly
if ( this.x < min.x ) {
this.x = min.x;
} else if ( this.x > max.x ) {
this.x = max.x;
}
if ( this.y < min.y ) {
this.y = min.y;
} else if ( this.y > max.y ) {
this.y = max.y;
}
if ( this.z < min.z ) {
this.z = min.z;
} else if ( this.z > max.z ) {
this.z = max.z;
}
return this;
},
clampScalar: ( function () {
var min, max;
return function ( minVal, maxVal ) {
if ( min === undefined ) {
min = new cornerstoneMath.Vector3();
max = new cornerstoneMath.Vector3();
}
min.set( minVal, minVal, minVal );
max.set( maxVal, maxVal, maxVal );
return this.clamp( min, max );
};
} )(),
floor: function () {
this.x = Math.floor( this.x );
this.y = Math.floor( this.y );
this.z = Math.floor( this.z );
return this;
},
ceil: function () {
this.x = Math.ceil( this.x );
this.y = Math.ceil( this.y );
this.z = Math.ceil( this.z );
return this;
},
round: function () {
this.x = Math.round( this.x );
this.y = Math.round( this.y );
this.z = Math.round( this.z );
return this;
},
roundToZero: function () {
this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
return this;
},
negate: function () {
return this.multiplyScalar( - 1 );
},
dot: function ( v ) {
return this.x * v.x + this.y * v.y + this.z * v.z;
},
lengthSq: function () {
return this.x * this.x + this.y * this.y + this.z * this.z;
},
length: function () {
return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
},
lengthManhattan: function () {
return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
},
normalize: function () {
return this.divideScalar( this.length() );
},
setLength: function ( l ) {
var oldLength = this.length();
if ( oldLength !== 0 && l !== oldLength ) {
this.multiplyScalar( l / oldLength );
}
return this;
},
lerp: function ( v, alpha ) {
this.x += ( v.x - this.x ) * alpha;
this.y += ( v.y - this.y ) * alpha;
this.z += ( v.z - this.z ) * alpha;
return this;
},
cross: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'DEPRECATED: Vector3\'s .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
return this.crossVectors( v, w );
}
var x = this.x, y = this.y, z = this.z;
this.x = y * v.z - z * v.y;
this.y = z * v.x - x * v.z;
this.z = x * v.y - y * v.x;
return this;
},
crossVectors: function ( a, b ) {
var ax = a.x, ay = a.y, az = a.z;
var bx = b.x, by = b.y, bz = b.z;
this.x = ay * bz - az * by;
this.y = az * bx - ax * bz;
this.z = ax * by - ay * bx;
return this;
},
projectOnVector: function () {
var v1, dot;
return function ( vector ) {
if ( v1 === undefined ) v1 = new cornerstoneMath.Vector3();
v1.copy( vector ).normalize();
dot = this.dot( v1 );
return this.copy( v1 ).multiplyScalar( dot );
};
}(),
projectOnPlane: function () {
var v1;
return function ( planeNormal ) {
if ( v1 === undefined ) v1 = new cornerstoneMath.Vector3();
v1.copy( this ).projectOnVector( planeNormal );
return this.sub( v1 );
};
}(),
reflect: function () {
// reflect incident vector off plane orthogonal to normal
// normal is assumed to have unit length
var v1;
return function ( normal ) {
if ( v1 === undefined ) v1 = new cornerstoneMath.Vector3();
return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
};
}(),
angleTo: function ( v ) {
var theta = this.dot( v ) / ( this.length() * v.length() );
// clamp, to handle numerical problems
return Math.acos( cornerstoneMath.clamp( theta, -1, 1 ) );
},
distanceTo: function ( v ) {
return Math.sqrt( this.distanceToSquared( v ) );
},
distanceToSquared: function ( v ) {
var dx = this.x - v.x;
var dy = this.y - v.y;
var dz = this.z - v.z;
return dx * dx + dy * dy + dz * dz;
},
setEulerFromRotationMatrix: function ( m, order ) {
console.error( "REMOVED: Vector3\'s setEulerFromRotationMatrix has been removed in favor of Euler.setFromRotationMatrix(), please update your code.");
},
setEulerFromQuaternion: function ( q, order ) {
console.error( "REMOVED: Vector3\'s setEulerFromQuaternion: has been removed in favor of Euler.setFromQuaternion(), please update your code.");
},
getPositionFromMatrix: function ( m ) {
console.warn( "DEPRECATED: Vector3\'s .getPositionFromMatrix() has been renamed to .setFromMatrixPosition(). Please update your code." );
return this.setFromMatrixPosition( m );
},
getScaleFromMatrix: function ( m ) {
console.warn( "DEPRECATED: Vector3\'s .getScaleFromMatrix() has been renamed to .setFromMatrixScale(). Please update your code." );
return this.setFromMatrixScale( m );
},
getColumnFromMatrix: function ( index, matrix ) {
console.warn( "DEPRECATED: Vector3\'s .getColumnFromMatrix() has been renamed to .setFromMatrixColumn(). Please update your code." );
return this.setFromMatrixColumn( index, matrix );
},
setFromMatrixPosition: function ( m ) {
this.x = m.elements[ 12 ];
this.y = m.elements[ 13 ];
this.z = m.elements[ 14 ];
return this;
},
setFromMatrixScale: function ( m ) {
var sx = this.set( m.elements[ 0 ], m.elements[ 1 ], m.elements[ 2 ] ).length();
var sy = this.set( m.elements[ 4 ], m.elements[ 5 ], m.elements[ 6 ] ).length();
var sz = this.set( m.elements[ 8 ], m.elements[ 9 ], m.elements[ 10 ] ).length();
this.x = sx;
this.y = sy;
this.z = sz;
return this;
},
setFromMatrixColumn: function ( index, matrix ) {
var offset = index * 4;
var me = matrix.elements;
this.x = me[ offset ];
this.y = me[ offset + 1 ];
this.z = me[ offset + 2 ];
return this;
},
equals: function ( v ) {
return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
},
fromArray: function ( array ) {
this.x = array[ 0 ];
this.y = array[ 1 ];
this.z = array[ 2 ];
return this;
},
toArray: function () {
return [ this.x, this.y, this.z ];
},
clone: function () {
return new cornerstoneMath.Vector3( this.x, this.y, this.z );
}
};
return cornerstoneMath;
}(cornerstoneMath));
// End Source; src/vector3.js
// Begin Source: src/Line3.js
// Copied from THREE.JS
/**
* @author bhouston / http://exocortex.com
*/
var cornerstoneMath = (function (cornerstoneMath) {
"use strict";
if (cornerstoneMath === undefined) {
cornerstoneMath = {};
}
cornerstoneMath.Line3 = function ( start, end ) {
this.start = ( start !== undefined ) ? start : new cornerstoneMath.Vector3();
this.end = ( end !== undefined ) ? end : new cornerstoneMath.Vector3();
};
cornerstoneMath.Line3.prototype = {
constructor: cornerstoneMath.Line3,
set: function ( start, end ) {
this.start.copy( start );
this.end.copy( end );
return this;
},
copy: function ( line ) {
this.start.copy( line.start );
this.end.copy( line.end );
return this;
},
center: function ( optionalTarget ) {
var result = optionalTarget || new cornerstoneMath.Vector3();
return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
},
delta: function ( optionalTarget ) {
var result = optionalTarget || new cornerstoneMath.Vector3();
return result.subVectors( this.end, this.start );
},
distanceSq: function () {
return this.start.distanceToSquared( this.end );
},
distance: function () {
return this.start.distanceTo( this.end );
},
at: function ( t, optionalTarget ) {
var result = optionalTarget || new cornerstoneMath.Vector3();
return this.delta( result ).multiplyScalar( t ).add( this.start );
},
closestPointToPointParameter: function () {
var startP = new cornerstoneMath.Vector3();
var startEnd = new cornerstoneMath.Vector3();
return function ( point, clampToLine ) {
startP.subVectors( point, this.start );
startEnd.subVectors( this.end, this.start );
var startEnd2 = startEnd.dot( startEnd );
var startEnd_startP = startEnd.dot( startP );
var t = startEnd_startP / startEnd2;
if ( clampToLine ) {
t = cornerstoneMath.Math.clamp( t, 0, 1 );
}
return t;
};
}(),
closestPointToPoint: function ( point, clampToLine, optionalTarget ) {
var t = this.closestPointToPointParameter( point, clampToLine );
var result = optionalTarget || new cornerstoneMath.Vector3();
return this.delta( result ).multiplyScalar( t ).add( this.start );
},
applyMatrix4: function ( matrix ) {
this.start.applyMatrix4( matrix );
this.end.applyMatrix4( matrix );
return this;
},
equals: function ( line ) {
return line.start.equals( this.start ) && line.end.equals( this.end );
},
clone: function () {
return new cornerstoneMath.Line3().copy( this );
},
intersectLine: function ( line ) {
// http://stackoverflow.com/questions/2316490/the-algorithm-to-find-the-point-of-intersection-of-two-3d-line-segment/10288710#10288710
var da = this.end.clone().sub(this.start);
var db = line.end.clone().sub(line.start);
var dc = line.start.clone().sub(this.start);
var daCrossDb = da.clone().cross(db);
var dcCrossDb = dc.clone().cross(db);
if (dc.dot(da) === 0){
// Lines are not coplanar, stop here
return;
}
var s = dcCrossDb.dot(daCrossDb) / daCrossDb.lengthSq();
// Make sure we have an intersection
if (s > 1.0 || isNaN(s)) {
return;
}
var intersection = this.start.clone().add(da.clone().multiplyScalar(s));
var distanceTest = intersection.clone().sub(line.start).lengthSq() + intersection.clone().sub(line.end).lengthSq();
if (distanceTest <= line.distanceSq()) {
return intersection;
}
return;
}
};
return cornerstoneMath;
}(cornerstoneMath));
// End Source; src/Line3.js
// Begin Source: src/lineSegment.js
var cornerstoneMath = (function (cornerstoneMath) {
"use strict";
if(cornerstoneMath === undefined) {
cornerstoneMath = {};
}
// based on http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
function sqr(x)
{
return x * x;
}
function dist2(v, w) {
return sqr(v.x - w.x) + sqr(v.y - w.y);
}
function distanceToPointSquared(lineSegment, point)
{
var l2 = dist2(lineSegment.start, lineSegment.end);
if(l2 === 0) {
return dist2(point, lineSegment.start);
}
var t = ((point.x - lineSegment.start.x) * (lineSegment.end.x - lineSegment.start.x) +
(point.y - lineSegment.start.y) * (lineSegment.end.y - lineSegment.start.y)) / l2;
if(t < 0) {
return dist2(point, lineSegment.start);
}
if(t > 1) {
return dist2(point, lineSegment.end);
}
var pt = {
x : lineSegment.start.x + t * (lineSegment.end.x - lineSegment.start.x),
y : lineSegment.start.y + t * (lineSegment.end.y - lineSegment.start.y)
};
return dist2(point, pt);
}
function distanceToPoint(lineSegment, point)
{
return Math.sqrt(distanceToPointSquared(lineSegment, point));
}
// module exports
cornerstoneMath.lineSegment =
{
distanceToPoint : distanceToPoint
};
return cornerstoneMath;
}(cornerstoneMath));
// End Source; src/lineSegment.js
// Begin Source: src/math.js
// Based on THREE.JS
var cornerstoneMath = (function (cornerstoneMath) {
"use strict";
if (cornerstoneMath === undefined) {
cornerstoneMath = {};
}
function clamp(x,a,b) {
return ( x < a ) ? a : ( ( x > b ) ? b : x );
}
function degToRad(degrees) {
var degreeToRadiansFactor = Math.PI / 180;
return degrees * degreeToRadiansFactor;
}
function radToDeg(radians) {
var radianToDegreesFactor = 180 / Math.PI;
return radians * radianToDegreesFactor;
}
cornerstoneMath.clamp = clamp;
cornerstoneMath.degToRad = degToRad;
cornerstoneMath.radToDeg = radToDeg;
return cornerstoneMath;
}(cornerstoneMath));
// End Source; src/math.js
// Begin Source: src/matrix4.js
// Based on THREE.JS
var cornerstoneMath = (function (cornerstoneMath) {
"use strict";
if(cornerstoneMath === undefined) {
cornerstoneMath = {};
}
cornerstoneMath.Matrix4 = function Matrix4(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 )
{
this.elements = new Float32Array( 16 );
// TODO: if n11 is undefined, then just set to identity, otherwise copy all other values into matrix
// we should not support semi specification of Matrix4, it is just weird.
var te = this.elements;
te[0] = ( n11 !== undefined ) ? n11 : 1; te[4] = n12 || 0; te[8] = n13 || 0; te[12] = n14 || 0;
te[1] = n21 || 0; te[5] = ( n22 !== undefined ) ? n22 : 1; te[9] = n23 || 0; te[13] = n24 || 0;
te[2] = n31 || 0; te[6] = n32 || 0; te[10] = ( n33 !== undefined ) ? n33 : 1; te[14] = n34 || 0;
te[3] = n41 || 0; te[7] = n42 || 0; te[11] = n43 || 0; te[15] = ( n44 !== undefined ) ? n44 : 1;
};
cornerstoneMath.Matrix4.prototype.makeRotationFromQuaternion = function(q) {
var te = this.elements;
var x = q.x, y = q.y, z = q.z, w = q.w;
var x2 = x + x, y2 = y + y, z2 = z + z;
var xx = x * x2, xy = x * y2, xz = x * z2;
var yy = y * y2, yz = y * z2, zz = z * z2;
var wx = w * x2, wy = w * y2, wz = w * z2;
te[0] = 1 - ( yy + zz );
te[4] = xy - wz;
te[8] = xz + wy;
te[1] = xy + wz;
te[5] = 1 - ( xx + zz );
te[9] = yz - wx;
te[2] = xz - wy;
te[6] = yz + wx;
te[10] = 1 - ( xx + yy );
// last column
te[3] = 0;
te[7] = 0;
te[11] = 0;
// bottom row
te[12] = 0;
te[13] = 0;
te[14] = 0;
te[15] = 1;
return this;
};
cornerstoneMath.Matrix4.prototype.multiplyMatrices = function(a, b)
{
var ae = a.elements;
var be = b.elements;
var te = this.elements;
var a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12];
var a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13];
var a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14];
var a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15];
var b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12];
var b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13];
var b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14];
var b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15];
te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
return this;
};
cornerstoneMath.Matrix4.prototype.multiply = function(m, n )
{
if (n !== undefined) {
console.warn('DEPRECATED: Matrix4\'s .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.');
return this.multiplyMatrices(m, n);
}
return this.multiplyMatrices(this, m);
};
cornerstoneMath.Matrix4.prototype.getInverse = function ( m, throwOnInvertible ) {
// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
var te = this.elements;
var me = m.elements;
var n11 = me[0], n12 = me[4], n13 = me[8], n14 = me[12];
var n21 = me[1], n22 = me[5], n23 = me[9], n24 = me[13];
var n31 = me[2], n32 = me[6], n33 = me[10], n34 = me[14];
var n41 = me[3], n42 = me[7], n43 = me[11], n44 = me[15];
te[0] = n23*n34*n42 - n24*n33*n42 + n24*n32*n43 - n22*n34*n43 - n23*n32*n44 + n22*n33*n44;
te[4] = n14*n33*n42 - n13*n34*n42 - n14*n32*n43 + n12*n34*n43 + n13*n32*n44 - n12*n33*n44;
te[8] = n13*n24*n42 - n14*n23*n42 + n14*n22*n43 - n12*n24*n43 - n13*n22*n44 + n12*n23*n44;
te[12] = n14*n23*n32 - n13*n24*n32 - n14*n22*n33 + n12*n24*n33 + n13*n22*n34 - n12*n23*n34;
te[1] = n24*n33*n41 - n23*n34*n41 - n24*n31*n43 + n21*n34*n43 + n23*n31*n44 - n21*n33*n44;
te[5] = n13*n34*n41 - n14*n33*n41 + n14*n31*n43 - n11*n34*n43 - n13*n31*n44 + n11*n33*n44;
te[9] = n14*n23*n41 - n13*n24*n41 - n14*n21*n43 + n11*n24*n43 + n13*n21*n44 - n11*n23*n44;
te[13] = n13*n24*n31 - n14*n23*n31 + n14*n21*n33 - n11*n24*n33 - n13*n21*n34 + n11*n23*n34;
te[2] = n22*n34*n41 - n24*n32*n41 + n24*n31*n42 - n21*n34*n42 - n22*n31*n44 + n21*n32*n44;
te[6] = n14*n32*n41 - n12*n34*n41 - n14*n31*n42 + n11*n34*n42 + n12*n31*n44 - n11*n32*n44;
te[10] = n12*n24*n41 - n14*n22*n41 + n14*n21*n42 - n11*n24*n42 - n12*n21*n44 + n11*n22*n44;
te[14] = n14*n22*n31 - n12*n24*n31 - n14*n21*n32 + n11*n24*n32 + n12*n21*n34 - n11*n22*n34;
te[3] = n23*n32*n41 - n22*n33*n41 - n23*n31*n42 + n21*n33*n42 + n22*n31*n43 - n21*n32*n43;
te[7] = n12*n33*n41 - n13*n32*n41 + n13*n31*n42 - n11*n33*n42 - n12*n31*n43 + n11*n32*n43;
te[11] = n13*n22*n41 - n12*n23*n41 - n13*n21*n42 + n11*n23*n42 + n12*n21*n43 - n11*n22*n43;
te[15] = n12*n23*n31 - n13*n22*n31 + n13*n21*n32 - n11*n23*n32 - n12*n21*n33 + n11*n22*n33;
var det = n11 * te[ 0 ] + n21 * te[ 4 ] + n31 * te[ 8 ] + n41 * te[ 12 ];
if ( det === 0 ) {
var msg = "Matrix4.getInverse(): can't invert matrix, determinant is 0";
if ( throwOnInvertible || false ) {
throw new Error( msg );
} else {
console.warn( msg );
}
this.identity();
return this;
}
this.multiplyScalar( 1 / det );
return this;
};
cornerstoneMath.Matrix4.prototype.applyToVector3Array = function() {
var v1 = new cornerstoneMath.Vector3();
return function ( array, offset, length ) {
if ( offset === undefined ) offset = 0;
if ( length === undefined ) length = array.length;
for ( var i = 0, j = offset, il; i < length; i += 3, j += 3 ) {
v1.x = array[ j ];
v1.y = array[ j + 1 ];
v1.z = array[ j + 2 ];
v1.applyMatrix4( this );
array[ j ] = v1.x;
array[ j + 1 ] = v1.y;
array[ j + 2 ] = v1.z;
}
return array;
};
};
cornerstoneMath.Matrix4.prototype.makeTranslation = function ( x, y, z ) {
this.set(
1, 0, 0, x,
0, 1, 0, y,
0, 0, 1, z,
0, 0, 0, 1
);
return this;
};
cornerstoneMath.Matrix4.prototype.multiplyScalar = function ( s ) {
var te = this.elements;
te[0] *= s; te[4] *= s; te[8] *= s; te[12] *= s;
te[1] *= s; te[5] *= s; te[9] *= s; te[13] *= s;
te[2] *= s; te[6] *= s; te[10] *= s; te[14] *= s;
te[3] *= s; te[7] *= s; te[11] *= s; te[15] *= s;
return this;
};
cornerstoneMath.Matrix4.prototype.set = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
var te = this.elements;
te[0] = n11; te[4] = n12; te[8] = n13; te[12] = n14;
te[1] = n21; te[5] = n22; te[9] = n23; te[13] = n24;
te[2] = n31; te[6] = n32; te[10] = n33; te[14] = n34;
te[3] = n41; te[7] = n42; te[11] = n43; te[15] = n44;
return this;
};
cornerstoneMath.Matrix4.prototype.makeScale = function ( x, y, z ) {
this.set(
x, 0, 0, 0,
0, y, 0, 0,
0, 0, z, 0,
0, 0, 0, 1
);
return this;
};
return cornerstoneMath;
}(cornerstoneMath));
// End Source; src/matrix4.js
// Begin Source: src/plane.js
// Copied from Three.JS
/**
* @author bhouston / http://exocortex.com
*/
var cornerstoneMath = (function (cornerstoneMath) {
"use strict";
if (cornerstoneMath === undefined) {
cornerstoneMath = {};
}
cornerstoneMath.Plane = function ( normal, constant ) {
this.normal = ( normal !== undefined ) ? normal : new cornerstoneMath.Vector3( 1, 0, 0 );
this.constant = ( constant !== undefined ) ? constant : 0;
};
cornerstoneMath.Plane.prototype = {
constructor: cornerstoneMath.Plane,
set: function ( normal, constant ) {
this.normal.copy( normal );
this.constant = constant;
return this;
},
setComponents: function ( x, y, z, w ) {
this.normal.set( x, y, z );
this.constant = w;
return this;
},
setFromNormalAndCoplanarPoint: function ( normal, point ) {
this.normal.copy( normal );
this.constant = - point.dot( this.normal ); // must be this.normal, not normal, as this.normal is normalized
return this;
},
setFromCoplanarPoints: function () {
var v1 = new cornerstoneMath.Vector3();
var v2 = new cornerstoneMath.Vector3();
return function ( a, b, c ) {
var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
this.setFromNormalAndCoplanarPoint( normal, a );
return this;
};
}(),
copy: function ( plane ) {
this.normal.copy( plane.normal );
this.constant = plane.constant;
return this;
},
normalize: function () {
// Note: will lead to a divide by zero if the plane is invalid.
var inverseNormalLength = 1.0 / this.normal.length();
this.normal.multiplyScalar( inverseNormalLength );
this.constant *= inverseNormalLength;
return this;
},
negate: function () {
this.constant *= - 1;
this.normal.negate();
return this;
},
distanceToPoint: function ( point ) {
return this.normal.dot( point ) + this.constant;
},
distanceToSphere: function ( sphere ) {
return this.distanceToPoint( sphere.center ) - sphere.radius;
},
projectPoint: function ( point, optionalTarget ) {
return this.orthoPoint( point, optionalTarget ).sub( point ).negate();
},
orthoPoint: function ( point, optionalTarget ) {
var perpendicularMagnitude = this.distanceToPoint( point );
var result = optionalTarget || new cornerstoneMath.Vector3();
return result.copy( this.normal ).multiplyScalar( perpendicularMagnitude );
},
isIntersectionLine: function ( line ) {
// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
var startSign = this.distanceToPoint( line.start );
var endSign = this.distanceToPoint( line.end );
return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
},
intersectLine: function () {
var v1 = new cornerstoneMath.Vector3();
return function ( line, optionalTarget ) {
var result = optionalTarget || new cornerstoneMath.Vector3();
var direction = line.delta( v1 );
var denominator = this.normal.dot( direction );
if ( denominator === 0 ) {
// line is coplanar, return origin
if ( this.distanceToPoint( line.start ) === 0 ) {
return result.copy( line.start );
}
// Unsure if this is the correct method to handle this case.
return undefined;
}
var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
if ( t < 0 || t > 1 ) {
return undefined;
}
return result.copy( direction ).multiplyScalar( t ).add( line.start );
};
}(),
intersectPlane: function (targetPlane) {
// Returns the intersection line between two planes
var direction = this.normal.clone().cross(targetPlane.normal);
var origin = new cornerstoneMath.Vector3();
var intersectionData = {
origin: origin,
direction: direction
};
// If the planes are parallel, return an empty vector for the
// intersection line
if (this.normal.clone().cross(targetPlane.normal).length < 1e-10) {
intersectionData.direction = new cornerstoneMath.Vector3();
return intersectionData;
}
var h1 = this.constant;
var h2 = targetPlane.constant;
var n1dotn2 = this.normal.clone().dot(targetPlane.normal);
var c1 = -(h1 - h2 * n1dotn2) / (1 - n1dotn2 * n1dotn2);
var c2 = -(h2 - h1 * n1dotn2) / (1 - n1dotn2 * n1dotn2);
intersectionData.origin = this.normal.clone().multiplyScalar(c1).add(targetPlane.normal.clone().multiplyScalar(c2));
return intersectionData;
},
coplanarPoint: function ( optionalTarget ) {
var result = optionalTarget || new cornerstoneMath.Vector3();
return result.copy( this.normal ).multiplyScalar( - this.constant );
},
translate: function ( offset ) {
this.constant = this.constant - offset.dot( this.normal );
return this;
},
equals: function ( plane ) {
return plane.normal.equals( this.normal ) && ( plane.constant == this.constant );
},
clone: function () {
return new cornerstoneMath.Plane().copy( this );
}
};
return cornerstoneMath;
}(cornerstoneMath));
// End Source; src/plane.js
// Begin Source: src/point.js
var cornerstoneMath = (function (cornerstoneMath) {
"use strict";
if(cornerstoneMath === undefined) {
cornerstoneMath = {};
}
function pageToPoint(e)
{
return {
x : e.pageX,
y : e.pageY
};
}
function subtract(lhs, rhs)
{
return {
x : lhs.x - rhs.x,
y : lhs.y - rhs.y
};
}
function copy(point)
{
return {
x : point.x,
y : point.y
};
}
function distance(from, to)
{
return Math.sqrt(distanceSquared(from, to));
}
function distanceSquared(from, to)
{
var delta = subtract(from, to);
return delta.x * delta.x + delta.y * delta.y;
}
function insideRect(point, rect)
{
if( point.x < rect.left ||
point.x > rect.left + rect.width ||
point.y < rect.top ||
point.y > rect.top + rect.height)
{
return false;
}
return true;
}
// module exports
cornerstoneMath.point =
{
subtract : subtract,
copy: copy,
pageToPoint: pageToPoint,
distance: distance,
distanceSquared: distanceSquared,
insideRect: insideRect
};
return cornerstoneMath;
}(cornerstoneMath));
// End Source; src/point.js
// Begin Source: src/quaternion.js
// Based on THREE.JS
var cornerstoneMath = (function (cornerstoneMath) {
"use strict";
if(cornerstoneMath === undefined) {
cornerstoneMath = {};
}
cornerstoneMath.Quaternion = function Quaternion(x, y, z, w)
{
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.w = ( w !== undefined ) ? w : 1;
};
cornerstoneMath.Quaternion.prototype.setFromAxisAngle = function(axis, angle)
{
var halfAngle = angle / 2, s = Math.sin( halfAngle );
this.x = axis.x * s;
this.y = axis.y * s;
this.z = axis.z * s;
this.w = Math.cos( halfAngle );
return this;
};
cornerstoneMath.Quaternion.prototype.multiplyQuaternions = function( a, b)
{
var qax = a.x, qay = a.y, qaz = a.z, qaw = a.w;
var qbx = b.x, qby = b.y, qbz = b.z, qbw = b.w;
this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
return this;
};
cornerstoneMath.Quaternion.prototype.setFromRotationMatrix = function(m)
{
var te = m.elements,
m11 = te[0], m12 = te[4], m13 = te[8],
m21 = te[1], m22 = te[5], m23 = te[9],
m31 = te[2], m32 = te[6], m33 = te[10],
trace = m11 + m22 + m33,
s;
if ( trace > 0 ) {
s = 0.5 / Math.sqrt( trace + 1.0 );
this.w = 0.25 / s;
this.x = ( m32 - m23 ) * s;
this.y = ( m13 - m31 ) * s;
this.z = ( m21 - m12 ) * s;
} else if ( m11 > m22 && m11 > m33 ) {
s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
this.w = (m32 - m23 ) / s;
this.x = 0.25 * s;
this.y = (m12 + m21 ) / s;
this.z = (m13 + m31 ) / s;
} else if ( m22 > m33 ) {
s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
this.w = (m13 - m31 ) / s;
this.x = (m12 + m21 ) / s;
this.y = 0.25 * s;
this.z = (m23 + m32 ) / s;
} else {
s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
this.w = ( m21 - m12 ) / s;
this.x = ( m13 + m31 ) / s;
this.y = ( m23 + m32 ) / s;
this.z = 0.25 * s;
}
return this;
};
return cornerstoneMath;
}(cornerstoneMath));
// End Source; src/quaternion.js
// Begin Source: src/rect.js
var cornerstoneMath = (function (cornerstoneMath) {
"use strict";
if(cornerstoneMath === undefined) {
cornerstoneMath = {};
}
function rectToLineSegments(rect)
{
var top = {
start : {
x :rect.left,
y :rect.top
},
end : {
x :rect.left + rect.width,
y :rect.top
}
};
var right = {
start : {
x :rect.left + rect.width,
y :rect.top
},
end : {
x :rect.left + rect.width,
y :rect.top + rect.height
}
};
var bottom = {
start : {
x :rect.left + rect.width,
y :rect.top + rect.height
},
end : {
x :rect.left,
y :rect.top + rect.height
}
};
var left = {
start : {
x :rect.left,
y :rect.top + rect.height
},
end : {
x :rect.left,
y :rect.top
}
};
var lineSegments = [top, right, bottom, left];
return lineSegments;
}
function pointNearLineSegment(point, lineSegment, maxDistance)
{
if(maxDistance === undefined) {
maxDistance = 5;
}
var distance = cornerstoneMath.lineSegment.distanceToPoint(lineSegment, point);
return (distance < maxDistance);
}
function distanceToPoint(rect, point)
{
var minDistance = 655535;
var lineSegments = rectToLineSegments(rect);
lineSegments.forEach(function(lineSegment) {
var distance = cornerstoneMath.lineSegment.distanceToPoint(lineSegment, point);
if(distance < minDistance) {
minDistance = distance;
}
});
return minDistance;
}
// module exports
cornerstoneMath.rect =
{
distanceToPoint : distanceToPoint
};
return cornerstoneMath;
}(cornerstoneMath));
// End Source; src/rect.js