UNPKG

molstar

Version:

A comprehensive macromolecular library.

281 lines (280 loc) 13.1 kB
"use strict"; /** * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.Sphere3D = void 0; var tslib_1 = require("tslib"); var linear_algebra_1 = require("../../linear-algebra"); var int_1 = require("../../../mol-data/int"); var axes3d_1 = require("./axes3d"); var principal_axes_1 = require("../../linear-algebra/matrix/principal-axes"); function Sphere3D() { return Sphere3D.zero(); } exports.Sphere3D = Sphere3D; (function (Sphere3D) { function hasExtrema(sphere) { return sphere.extrema !== undefined; } Sphere3D.hasExtrema = hasExtrema; function create(center, radius) { return { center: center, radius: radius }; } Sphere3D.create = create; function zero() { return { center: (0, linear_algebra_1.Vec3)(), radius: 0 }; } Sphere3D.zero = zero; function clone(a) { var out = create(linear_algebra_1.Vec3.clone(a.center), a.radius); if (hasExtrema(a)) out.extrema = a.extrema.map(function (e) { return linear_algebra_1.Vec3.clone(e); }); return out; } Sphere3D.clone = clone; function set(out, center, radius) { linear_algebra_1.Vec3.copy(out.center, center); out.radius = radius; return out; } Sphere3D.set = set; function copy(out, a) { linear_algebra_1.Vec3.copy(out.center, a.center); out.radius = a.radius; if (hasExtrema(a)) setExtrema(out, a.extrema.map(function (e) { return linear_algebra_1.Vec3.clone(e); })); return out; } Sphere3D.copy = copy; /** Note that `extrema` must not be reused elsewhere */ function setExtrema(out, extrema) { var _a; if (out.extrema !== undefined) { out.extrema.length = 0; (_a = out.extrema).push.apply(_a, extrema); } else { out.extrema = extrema; } return out; } Sphere3D.setExtrema = setExtrema; function computeBounding(data) { var x = data.x, y = data.y, z = data.z, indices = data.indices; var cx = 0, cy = 0, cz = 0; var radiusSq = 0; var size = int_1.OrderedSet.size(indices); for (var t = 0; t < size; t++) { var i = int_1.OrderedSet.getAt(indices, t); cx += x[i]; cy += y[i]; cz += z[i]; } if (size > 0) { cx /= size; cy /= size; cz /= size; } for (var t = 0; t < size; t++) { var i = int_1.OrderedSet.getAt(indices, t); var dx = x[i] - cx, dy = y[i] - cy, dz = z[i] - cz; var d = dx * dx + dy * dy + dz * dz; if (d > radiusSq) radiusSq = d; } return { center: linear_algebra_1.Vec3.create(cx, cy, cz), radius: Math.sqrt(radiusSq) }; } Sphere3D.computeBounding = computeBounding; /** Transform sphere with a Mat4 */ function transform(out, sphere, m) { linear_algebra_1.Vec3.transformMat4(out.center, sphere.center, m); out.radius = sphere.radius * linear_algebra_1.Mat4.getMaxScaleOnAxis(m); if (hasExtrema(sphere)) { setExtrema(out, sphere.extrema.map(function (e) { return linear_algebra_1.Vec3.transformMat4((0, linear_algebra_1.Vec3)(), e, m); })); } return out; } Sphere3D.transform = transform; /** Translate sphere by Vec3 */ function translate(out, sphere, v) { linear_algebra_1.Vec3.add(out.center, sphere.center, v); if (hasExtrema(sphere)) { setExtrema(out, sphere.extrema.map(function (e) { return linear_algebra_1.Vec3.add((0, linear_algebra_1.Vec3)(), e, v); })); } return out; } Sphere3D.translate = translate; function toArray(s, out, offset) { linear_algebra_1.Vec3.toArray(s.center, out, offset); out[offset + 3] = s.radius; } Sphere3D.toArray = toArray; function fromArray(out, array, offset) { linear_algebra_1.Vec3.fromArray(out.center, array, offset); out.radius = array[offset + 3]; return out; } Sphere3D.fromArray = fromArray; function fromBox3D(out, box) { linear_algebra_1.Vec3.scale(out.center, linear_algebra_1.Vec3.add(out.center, box.max, box.min), 0.5); out.radius = linear_algebra_1.Vec3.distance(out.center, box.max); Sphere3D.setExtrema(out, [ linear_algebra_1.Vec3.create(box.min[0], box.min[1], box.min[2]), linear_algebra_1.Vec3.create(box.max[0], box.max[1], box.max[2]), linear_algebra_1.Vec3.create(box.max[0], box.min[1], box.min[2]), linear_algebra_1.Vec3.create(box.min[0], box.max[1], box.max[2]), linear_algebra_1.Vec3.create(box.min[0], box.min[1], box.max[2]), linear_algebra_1.Vec3.create(box.max[0], box.min[1], box.max[2]), linear_algebra_1.Vec3.create(box.max[0], box.max[1], box.min[2]), linear_algebra_1.Vec3.create(box.min[0], box.max[1], box.min[2]), ]); return out; } Sphere3D.fromBox3D = fromBox3D; function fromAxes3D(out, axes) { linear_algebra_1.Vec3.copy(out.center, axes.origin); out.radius = Math.max(linear_algebra_1.Vec3.magnitude(axes.dirA), linear_algebra_1.Vec3.magnitude(axes.dirB), linear_algebra_1.Vec3.magnitude(axes.dirC)); return out; } Sphere3D.fromAxes3D = fromAxes3D; var tmpCenter = (0, linear_algebra_1.Vec3)(); /** Get a tight sphere around a transformed box */ function fromDimensionsAndTransform(out, dimensions, transform) { var x = dimensions[0], y = dimensions[1], z = dimensions[2]; var cpA = linear_algebra_1.Vec3.create(0, 0, 0); linear_algebra_1.Vec3.transformMat4(cpA, cpA, transform); var cpB = linear_algebra_1.Vec3.create(x, y, z); linear_algebra_1.Vec3.transformMat4(cpB, cpB, transform); var cpC = linear_algebra_1.Vec3.create(x, 0, 0); linear_algebra_1.Vec3.transformMat4(cpC, cpC, transform); var cpD = linear_algebra_1.Vec3.create(0, y, z); linear_algebra_1.Vec3.transformMat4(cpD, cpD, transform); var cpE = linear_algebra_1.Vec3.create(0, 0, z); linear_algebra_1.Vec3.transformMat4(cpE, cpE, transform); var cpF = linear_algebra_1.Vec3.create(x, 0, z); linear_algebra_1.Vec3.transformMat4(cpF, cpF, transform); var cpG = linear_algebra_1.Vec3.create(x, y, 0); linear_algebra_1.Vec3.transformMat4(cpG, cpG, transform); var cpH = linear_algebra_1.Vec3.create(0, y, 0); linear_algebra_1.Vec3.transformMat4(cpH, cpH, transform); linear_algebra_1.Vec3.add(tmpCenter, cpA, cpB); linear_algebra_1.Vec3.scale(tmpCenter, tmpCenter, 0.5); var d = Math.max(linear_algebra_1.Vec3.distance(cpA, cpB), linear_algebra_1.Vec3.distance(cpC, cpD)); Sphere3D.set(out, tmpCenter, d / 2); Sphere3D.setExtrema(out, [cpA, cpB, cpC, cpD, cpE, cpF, cpG, cpH]); return out; } Sphere3D.fromDimensionsAndTransform = fromDimensionsAndTransform; var tmpAddVec3 = (0, linear_algebra_1.Vec3)(); function addVec3(out, s, v) { var d = linear_algebra_1.Vec3.distance(s.center, v); if (d < s.radius) return Sphere3D.copy(out, s); linear_algebra_1.Vec3.sub(tmpAddVec3, s.center, v); linear_algebra_1.Vec3.sub(tmpAddVec3, s.center, tmpAddVec3); linear_algebra_1.Vec3.setMagnitude(tmpAddVec3, tmpAddVec3, s.radius); linear_algebra_1.Vec3.scale(out.center, linear_algebra_1.Vec3.add(tmpAddVec3, tmpAddVec3, v), 0.5); out.radius = linear_algebra_1.Vec3.distance(out.center, v); return out; } Sphere3D.addVec3 = addVec3; /** Expand sphere radius by another sphere */ function expandBySphere(out, sphere, by) { linear_algebra_1.Vec3.copy(out.center, sphere.center); out.radius = Math.max(sphere.radius, linear_algebra_1.Vec3.distance(sphere.center, by.center) + by.radius); if (hasExtrema(sphere) && hasExtrema(by)) { setExtrema(out, tslib_1.__spreadArray(tslib_1.__spreadArray([], sphere.extrema.map(function (e) { return linear_algebra_1.Vec3.clone(e); }), true), by.extrema.map(function (e) { return linear_algebra_1.Vec3.clone(e); }), true)); } return out; } Sphere3D.expandBySphere = expandBySphere; var tmpDir = (0, linear_algebra_1.Vec3)(); /** Expand sphere radius by delta */ function expand(out, sphere, delta) { var _a, _b; linear_algebra_1.Vec3.copy(out.center, sphere.center); out.radius = sphere.radius + delta; if (sphere.radius < 1e-12 || ((_b = (_a = sphere.extrema) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) <= 1) { out.extrema = void 0; return out; } if (hasExtrema(sphere)) { var positions = new Float32Array(sphere.extrema.length * 3); for (var i = 0; i < sphere.extrema.length; i++) { linear_algebra_1.Vec3.toArray(sphere.extrema[i], positions, i * 3); } var axes_1 = principal_axes_1.PrincipalAxes.calculateMomentsAxes(positions); axes3d_1.Axes3D.scale(axes_1, axes3d_1.Axes3D.normalize(axes_1, axes_1), delta); setExtrema(out, sphere.extrema.map(function (e) { linear_algebra_1.Vec3.normalize(tmpDir, linear_algebra_1.Vec3.sub(tmpDir, e, sphere.center)); var o = linear_algebra_1.Vec3.clone(e); var sA = linear_algebra_1.Vec3.dot(tmpDir, axes_1.dirA) < 0 ? -1 : 1; linear_algebra_1.Vec3.scaleAndAdd(o, o, axes_1.dirA, sA); var sB = linear_algebra_1.Vec3.dot(tmpDir, axes_1.dirB) < 0 ? -1 : 1; linear_algebra_1.Vec3.scaleAndAdd(o, o, axes_1.dirB, sB); var sC = linear_algebra_1.Vec3.dot(tmpDir, axes_1.dirC) < 0 ? -1 : 1; linear_algebra_1.Vec3.scaleAndAdd(o, o, axes_1.dirC, sC); if (linear_algebra_1.Vec3.distance(out.center, o) > out.radius) { if (sphere.extrema.length >= 14) { // 14 extrema with coarse boundary helper linear_algebra_1.Vec3.normalize(tmpDir, linear_algebra_1.Vec3.sub(tmpDir, o, sphere.center)); } linear_algebra_1.Vec3.scaleAndAdd(o, out.center, tmpDir, out.radius); } return o; })); } return out; } Sphere3D.expand = expand; /** * Returns whether or not the spheres have exactly the same center and radius (when compared with ===) */ function exactEquals(a, b) { return a.radius === b.radius && linear_algebra_1.Vec3.exactEquals(a.center, b.center); } Sphere3D.exactEquals = exactEquals; /** * Returns whether or not the spheres have approximately the same center and radius. */ function equals(a, b) { var ar = a.radius; var br = b.radius; return (Math.abs(ar - br) <= linear_algebra_1.EPSILON * Math.max(1.0, Math.abs(ar), Math.abs(br)) && linear_algebra_1.Vec3.equals(a.center, b.center)); } Sphere3D.equals = equals; /** * Check if `a` includes `b`, use `extrema` of `b` when available */ function includes(a, b) { if (hasExtrema(b)) { for (var _i = 0, _a = b.extrema; _i < _a.length; _i++) { var e = _a[_i]; if (linear_algebra_1.Vec3.distance(a.center, e) > a.radius) return false; } return true; } else { return linear_algebra_1.Vec3.distance(a.center, b.center) + b.radius <= a.radius; } } Sphere3D.includes = includes; /** Check if `a` and `b` are overlapping */ function overlaps(a, b) { return linear_algebra_1.Vec3.distance(a.center, b.center) <= a.radius + b.radius; } Sphere3D.overlaps = overlaps; /** Get the signed distance of `a` and `b` */ function distance(a, b) { return linear_algebra_1.Vec3.distance(a.center, b.center) - a.radius + b.radius; } Sphere3D.distance = distance; /** Get the distance of v from sphere. If negative, v is inside sphere */ function distanceToVec(sphere, v) { var center = sphere.center, radius = sphere.radius; return linear_algebra_1.Vec3.distance(v, center) - radius; } Sphere3D.distanceToVec = distanceToVec; })(Sphere3D || (Sphere3D = {})); exports.Sphere3D = Sphere3D;