StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
StackGenVis/frontend/node_modules/orbit-camera-controller/orbit.js

393 lines
8.3 KiB

'use strict'
module.exports = createOrbitController
var filterVector = require('filtered-vector')
var lookAt = require('gl-mat4/lookAt')
var mat4FromQuat = require('gl-mat4/fromQuat')
var invert44 = require('gl-mat4/invert')
var quatFromFrame = require('./lib/quatFromFrame')
function len3(x,y,z) {
return Math.sqrt(Math.pow(x,2) + Math.pow(y,2) + Math.pow(z,2))
}
function len4(w,x,y,z) {
return Math.sqrt(Math.pow(w,2) + Math.pow(x,2) + Math.pow(y,2) + Math.pow(z,2))
}
function normalize4(out, a) {
var ax = a[0]
var ay = a[1]
var az = a[2]
var aw = a[3]
var al = len4(ax, ay, az, aw)
if(al > 1e-6) {
out[0] = ax/al
out[1] = ay/al
out[2] = az/al
out[3] = aw/al
} else {
out[0] = out[1] = out[2] = 0.0
out[3] = 1.0
}
}
function OrbitCameraController(initQuat, initCenter, initRadius) {
this.radius = filterVector([initRadius])
this.center = filterVector(initCenter)
this.rotation = filterVector(initQuat)
this.computedRadius = this.radius.curve(0)
this.computedCenter = this.center.curve(0)
this.computedRotation = this.rotation.curve(0)
this.computedUp = [0.1,0,0]
this.computedEye = [0.1,0,0]
this.computedMatrix = [0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
this.recalcMatrix(0)
}
var proto = OrbitCameraController.prototype
proto.lastT = function() {
return Math.max(
this.radius.lastT(),
this.center.lastT(),
this.rotation.lastT())
}
proto.recalcMatrix = function(t) {
this.radius.curve(t)
this.center.curve(t)
this.rotation.curve(t)
var quat = this.computedRotation
normalize4(quat, quat)
var mat = this.computedMatrix
mat4FromQuat(mat, quat)
var center = this.computedCenter
var eye = this.computedEye
var up = this.computedUp
var radius = Math.exp(this.computedRadius[0])
eye[0] = center[0] + radius * mat[2]
eye[1] = center[1] + radius * mat[6]
eye[2] = center[2] + radius * mat[10]
up[0] = mat[1]
up[1] = mat[5]
up[2] = mat[9]
for(var i=0; i<3; ++i) {
var rr = 0.0
for(var j=0; j<3; ++j) {
rr += mat[i+4*j] * eye[j]
}
mat[12+i] = -rr
}
}
proto.getMatrix = function(t, result) {
this.recalcMatrix(t)
var m = this.computedMatrix
if(result) {
for(var i=0; i<16; ++i) {
result[i] = m[i]
}
return result
}
return m
}
proto.idle = function(t) {
this.center.idle(t)
this.radius.idle(t)
this.rotation.idle(t)
}
proto.flush = function(t) {
this.center.flush(t)
this.radius.flush(t)
this.rotation.flush(t)
}
proto.pan = function(t, dx, dy, dz) {
dx = dx || 0.0
dy = dy || 0.0
dz = dz || 0.0
this.recalcMatrix(t)
var mat = this.computedMatrix
var ux = mat[1]
var uy = mat[5]
var uz = mat[9]
var ul = len3(ux, uy, uz)
ux /= ul
uy /= ul
uz /= ul
var rx = mat[0]
var ry = mat[4]
var rz = mat[8]
var ru = rx * ux + ry * uy + rz * uz
rx -= ux * ru
ry -= uy * ru
rz -= uz * ru
var rl = len3(rx, ry, rz)
rx /= rl
ry /= rl
rz /= rl
var fx = mat[2]
var fy = mat[6]
var fz = mat[10]
var fu = fx * ux + fy * uy + fz * uz
var fr = fx * rx + fy * ry + fz * rz
fx -= fu * ux + fr * rx
fy -= fu * uy + fr * ry
fz -= fu * uz + fr * rz
var fl = len3(fx, fy, fz)
fx /= fl
fy /= fl
fz /= fl
var vx = rx * dx + ux * dy
var vy = ry * dx + uy * dy
var vz = rz * dx + uz * dy
this.center.move(t, vx, vy, vz)
//Update z-component of radius
var radius = Math.exp(this.computedRadius[0])
radius = Math.max(1e-4, radius + dz)
this.radius.set(t, Math.log(radius))
}
proto.rotate = function(t, dx, dy, dz) {
this.recalcMatrix(t)
dx = dx||0.0
dy = dy||0.0
var mat = this.computedMatrix
var rx = mat[0]
var ry = mat[4]
var rz = mat[8]
var ux = mat[1]
var uy = mat[5]
var uz = mat[9]
var fx = mat[2]
var fy = mat[6]
var fz = mat[10]
var qx = dx * rx + dy * ux
var qy = dx * ry + dy * uy
var qz = dx * rz + dy * uz
var bx = -(fy * qz - fz * qy)
var by = -(fz * qx - fx * qz)
var bz = -(fx * qy - fy * qx)
var bw = Math.sqrt(Math.max(0.0, 1.0 - Math.pow(bx,2) - Math.pow(by,2) - Math.pow(bz,2)))
var bl = len4(bx, by, bz, bw)
if(bl > 1e-6) {
bx /= bl
by /= bl
bz /= bl
bw /= bl
} else {
bx = by = bz = 0.0
bw = 1.0
}
var rotation = this.computedRotation
var ax = rotation[0]
var ay = rotation[1]
var az = rotation[2]
var aw = rotation[3]
var cx = ax*bw + aw*bx + ay*bz - az*by
var cy = ay*bw + aw*by + az*bx - ax*bz
var cz = az*bw + aw*bz + ax*by - ay*bx
var cw = aw*bw - ax*bx - ay*by - az*bz
//Apply roll
if(dz) {
bx = fx
by = fy
bz = fz
var s = Math.sin(dz) / len3(bx, by, bz)
bx *= s
by *= s
bz *= s
bw = Math.cos(dx)
cx = cx*bw + cw*bx + cy*bz - cz*by
cy = cy*bw + cw*by + cz*bx - cx*bz
cz = cz*bw + cw*bz + cx*by - cy*bx
cw = cw*bw - cx*bx - cy*by - cz*bz
}
var cl = len4(cx, cy, cz, cw)
if(cl > 1e-6) {
cx /= cl
cy /= cl
cz /= cl
cw /= cl
} else {
cx = cy = cz = 0.0
cw = 1.0
}
this.rotation.set(t, cx, cy, cz, cw)
}
proto.lookAt = function(t, eye, center, up) {
this.recalcMatrix(t)
center = center || this.computedCenter
eye = eye || this.computedEye
up = up || this.computedUp
var mat = this.computedMatrix
lookAt(mat, eye, center, up)
var rotation = this.computedRotation
quatFromFrame(rotation,
mat[0], mat[1], mat[2],
mat[4], mat[5], mat[6],
mat[8], mat[9], mat[10])
normalize4(rotation, rotation)
this.rotation.set(t, rotation[0], rotation[1], rotation[2], rotation[3])
var fl = 0.0
for(var i=0; i<3; ++i) {
fl += Math.pow(center[i] - eye[i], 2)
}
this.radius.set(t, 0.5 * Math.log(Math.max(fl, 1e-6)))
this.center.set(t, center[0], center[1], center[2])
}
proto.translate = function(t, dx, dy, dz) {
this.center.move(t,
dx||0.0,
dy||0.0,
dz||0.0)
}
proto.setMatrix = function(t, matrix) {
var rotation = this.computedRotation
quatFromFrame(rotation,
matrix[0], matrix[1], matrix[2],
matrix[4], matrix[5], matrix[6],
matrix[8], matrix[9], matrix[10])
normalize4(rotation, rotation)
this.rotation.set(t, rotation[0], rotation[1], rotation[2], rotation[3])
var mat = this.computedMatrix
invert44(mat, matrix)
var w = mat[15]
if(Math.abs(w) > 1e-6) {
var cx = mat[12]/w
var cy = mat[13]/w
var cz = mat[14]/w
this.recalcMatrix(t)
var r = Math.exp(this.computedRadius[0])
this.center.set(t, cx-mat[2]*r, cy-mat[6]*r, cz-mat[10]*r)
this.radius.idle(t)
} else {
this.center.idle(t)
this.radius.idle(t)
}
}
proto.setDistance = function(t, d) {
if(d > 0) {
this.radius.set(t, Math.log(d))
}
}
proto.setDistanceLimits = function(lo, hi) {
if(lo > 0) {
lo = Math.log(lo)
} else {
lo = -Infinity
}
if(hi > 0) {
hi = Math.log(hi)
} else {
hi = Infinity
}
hi = Math.max(hi, lo)
this.radius.bounds[0][0] = lo
this.radius.bounds[1][0] = hi
}
proto.getDistanceLimits = function(out) {
var bounds = this.radius.bounds
if(out) {
out[0] = Math.exp(bounds[0][0])
out[1] = Math.exp(bounds[1][0])
return out
}
return [ Math.exp(bounds[0][0]), Math.exp(bounds[1][0]) ]
}
proto.toJSON = function() {
this.recalcMatrix(this.lastT())
return {
center: this.computedCenter.slice(),
rotation: this.computedRotation.slice(),
distance: Math.log(this.computedRadius[0]),
zoomMin: this.radius.bounds[0][0],
zoomMax: this.radius.bounds[1][0]
}
}
proto.fromJSON = function(options) {
var t = this.lastT()
var c = options.center
if(c) {
this.center.set(t, c[0], c[1], c[2])
}
var r = options.rotation
if(r) {
this.rotation.set(t, r[0], r[1], r[2], r[3])
}
var d = options.distance
if(d && d > 0) {
this.radius.set(t, Math.log(d))
}
this.setDistanceLimits(options.zoomMin, options.zoomMax)
}
function createOrbitController(options) {
options = options || {}
var center = options.center || [0,0,0]
var rotation = options.rotation || [0,0,0,1]
var radius = options.radius || 1.0
center = [].slice.call(center, 0, 3)
rotation = [].slice.call(rotation, 0, 4)
normalize4(rotation, rotation)
var result = new OrbitCameraController(
rotation,
center,
Math.log(radius))
result.setDistanceLimits(options.zoomMin, options.zoomMax)
if('eye' in options || 'up' in options) {
result.lookAt(0, options.eye, options.center, options.up)
}
return result
}