/*! 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