UNPKG

molstar

Version:

A comprehensive macromolecular library.

213 lines (212 loc) 9.85 kB
/** * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { UUID } from '../../mol-util'; import { OrderedSet } from '../../mol-data/int'; import { Geometry } from '../../mol-geo/geometry/geometry'; import { Mat4, Vec3 } from '../../mol-math/linear-algebra'; import { Sphere3D } from '../../mol-math/geometry'; import { CentroidHelper } from '../../mol-math/geometry/centroid-helper'; import { ShapeGroupSizeTheme } from '../../mol-theme/size/shape-group'; import { ShapeGroupColorTheme } from '../../mol-theme/color/shape-group'; import { createTransform as _createTransform } from '../../mol-geo/geometry/transform-data'; import { createRenderObject as _createRenderObject, getNextMaterialId } from '../../mol-gl/render-object'; import { LocationIterator } from '../../mol-geo/util/location-iterator'; export var Shape; (function (Shape) { function create(name, sourceData, geometry, getColor, getSize, getLabel, transforms) { return { id: UUID.create22(), name: name, sourceData: sourceData, geometry: geometry, transforms: transforms || [Mat4.identity()], get groupCount() { return Geometry.getGroupCount(geometry); }, getColor: getColor, getSize: getSize, getLabel: getLabel }; } Shape.create = create; function getTheme(shape) { return { color: ShapeGroupColorTheme({ shape: shape }, {}), size: ShapeGroupSizeTheme({ shape: shape }, {}) }; } Shape.getTheme = getTheme; function groupIterator(shape) { var instanceCount = shape.transforms.length; var location = ShapeGroup.Location(shape); var getLocation = function (groupIndex, instanceIndex) { location.group = groupIndex; location.instance = instanceIndex; return location; }; return LocationIterator(shape.groupCount, instanceCount, 1, getLocation); } Shape.groupIterator = groupIterator; function createTransform(transforms, transformData) { var transformArray = transformData && transformData.aTransform.ref.value.length >= transforms.length * 16 ? transformData.aTransform.ref.value : new Float32Array(transforms.length * 16); for (var i = 0, il = transforms.length; i < il; ++i) { Mat4.toArray(transforms[i], transformArray, i * 16); } return _createTransform(transformArray, transforms.length, transformData); } Shape.createTransform = createTransform; function createRenderObject(shape, props) { props; var theme = Shape.getTheme(shape); var utils = Geometry.getUtils(shape.geometry); var materialId = getNextMaterialId(); var locationIt = groupIterator(shape); var transform = Shape.createTransform(shape.transforms); var values = utils.createValues(shape.geometry, transform, locationIt, theme, props); var state = utils.createRenderableState(props); return _createRenderObject(shape.geometry.kind, values, state, materialId); } Shape.createRenderObject = createRenderObject; function Loci(shape) { return { kind: 'shape-loci', shape: shape }; } Shape.Loci = Loci; function isLoci(x) { return !!x && x.kind === 'shape-loci'; } Shape.isLoci = isLoci; function areLociEqual(a, b) { return a.shape === b.shape; } Shape.areLociEqual = areLociEqual; function isLociEmpty(loci) { return loci.shape.groupCount === 0; } Shape.isLociEmpty = isLociEmpty; })(Shape || (Shape = {})); export var ShapeGroup; (function (ShapeGroup) { function Location(shape, group, instance) { if (group === void 0) { group = 0; } if (instance === void 0) { instance = 0; } return { kind: 'group-location', shape: shape, group: group, instance: instance }; } ShapeGroup.Location = Location; function isLocation(x) { return !!x && x.kind === 'group-location'; } ShapeGroup.isLocation = isLocation; function Loci(shape, groups) { return { kind: 'group-loci', shape: shape, groups: groups }; } ShapeGroup.Loci = Loci; function isLoci(x) { return !!x && x.kind === 'group-loci'; } ShapeGroup.isLoci = isLoci; function areLociEqual(a, b) { if (a.shape !== b.shape) return false; if (a.groups.length !== b.groups.length) return false; for (var i = 0, il = a.groups.length; i < il; ++i) { var _a = a.groups[i], idsA = _a.ids, instanceA = _a.instance; var _b = b.groups[i], idsB = _b.ids, instanceB = _b.instance; if (instanceA !== instanceB) return false; if (!OrderedSet.areEqual(idsA, idsB)) return false; } return true; } ShapeGroup.areLociEqual = areLociEqual; function isLociEmpty(loci) { return size(loci) === 0 ? true : false; } ShapeGroup.isLociEmpty = isLociEmpty; function size(loci) { var size = 0; for (var _i = 0, _a = loci.groups; _i < _a.length; _i++) { var group = _a[_i]; size += OrderedSet.size(group.ids); } return size; } ShapeGroup.size = size; var sphereHelper = new CentroidHelper(), tmpPos = Vec3.zero(); function sphereHelperInclude(groups, mapping, positions, transforms) { var indices = mapping.indices, offsets = mapping.offsets; var _loop_1 = function (ids, instance) { OrderedSet.forEach(ids, function (v) { for (var i = offsets[v], il = offsets[v + 1]; i < il; ++i) { Vec3.fromArray(tmpPos, positions, indices[i] * 3); Vec3.transformMat4(tmpPos, tmpPos, transforms[instance]); sphereHelper.includeStep(tmpPos); } }); }; for (var _i = 0, groups_1 = groups; _i < groups_1.length; _i++) { var _a = groups_1[_i], ids = _a.ids, instance = _a.instance; _loop_1(ids, instance); } } function sphereHelperRadius(groups, mapping, positions, transforms) { var indices = mapping.indices, offsets = mapping.offsets; var _loop_2 = function (ids, instance) { OrderedSet.forEach(ids, function (v) { for (var i = offsets[v], il = offsets[v + 1]; i < il; ++i) { Vec3.fromArray(tmpPos, positions, indices[i] * 3); Vec3.transformMat4(tmpPos, tmpPos, transforms[instance]); sphereHelper.radiusStep(tmpPos); } }); }; for (var _i = 0, groups_2 = groups; _i < groups_2.length; _i++) { var _a = groups_2[_i], ids = _a.ids, instance = _a.instance; _loop_2(ids, instance); } } function getBoundingSphere(loci, boundingSphere) { if (!boundingSphere) boundingSphere = Sphere3D(); sphereHelper.reset(); var padding = 0; var _a = loci.shape, geometry = _a.geometry, transforms = _a.transforms; if (geometry.kind === 'mesh' || geometry.kind === 'points') { var positions = geometry.kind === 'mesh' ? geometry.vertexBuffer.ref.value : geometry.centerBuffer.ref.value; sphereHelperInclude(loci.groups, geometry.groupMapping, positions, transforms); sphereHelper.finishedIncludeStep(); sphereHelperRadius(loci.groups, geometry.groupMapping, positions, transforms); } else if (geometry.kind === 'lines') { var start = geometry.startBuffer.ref.value; var end = geometry.endBuffer.ref.value; sphereHelperInclude(loci.groups, geometry.groupMapping, start, transforms); sphereHelperInclude(loci.groups, geometry.groupMapping, end, transforms); sphereHelper.finishedIncludeStep(); sphereHelperRadius(loci.groups, geometry.groupMapping, start, transforms); sphereHelperRadius(loci.groups, geometry.groupMapping, end, transforms); } else if (geometry.kind === 'spheres' || geometry.kind === 'text') { var positions = geometry.centerBuffer.ref.value; sphereHelperInclude(loci.groups, geometry.groupMapping, positions, transforms); sphereHelper.finishedIncludeStep(); sphereHelperRadius(loci.groups, geometry.groupMapping, positions, transforms); var _loop_3 = function (ids, instance) { OrderedSet.forEach(ids, function (v) { var value = loci.shape.getSize(v, instance); if (padding < value) padding = value; }); }; for (var _i = 0, _b = loci.groups; _i < _b.length; _i++) { var _c = _b[_i], ids = _c.ids, instance = _c.instance; _loop_3(ids, instance); } } else { // use whole shape bounding-sphere for other geometry kinds return Sphere3D.copy(boundingSphere, geometry.boundingSphere); } Vec3.copy(boundingSphere.center, sphereHelper.center); boundingSphere.radius = Math.sqrt(sphereHelper.radiusSq); Sphere3D.expand(boundingSphere, boundingSphere, padding); return boundingSphere; } ShapeGroup.getBoundingSphere = getBoundingSphere; })(ShapeGroup || (ShapeGroup = {}));