Skip to content
Snippets Groups Projects
Commit e7a0ba8d authored by Alexander Rose's avatar Alexander Rose
Browse files

wip, better boundary calculation, making use of transformations

parent 33d04f7e
No related branches found
No related tags found
No related merge requests found
...@@ -12,6 +12,13 @@ import { AssemblySymmetry } from 'mol-model-props/rcsb/symmetry'; ...@@ -12,6 +12,13 @@ import { AssemblySymmetry } from 'mol-model-props/rcsb/symmetry';
import { ShapeRepresentation, ShapeProps } from 'mol-geo/representation/shape'; import { ShapeRepresentation, ShapeProps } from 'mol-geo/representation/shape';
import { getAxesShape } from './assembly-symmetry'; import { getAxesShape } from './assembly-symmetry';
import Viewer from 'mol-view/viewer'; import Viewer from 'mol-view/viewer';
import { CarbohydrateRepresentation } from 'mol-geo/representation/structure/representation/carbohydrate';
import { MeshBuilder } from 'mol-geo/mesh/mesh-builder';
import { addSphere } from 'mol-geo/mesh/builder/sphere';
import { Shape } from 'mol-model/shape';
import { Color } from 'mol-util/color';
import { computeUnitBoundary } from 'mol-model/structure/structure/util/boundary';
import { addBoundingBox } from 'mol-geo/mesh/builder/bounding-box';
export interface StructureView { export interface StructureView {
readonly label: string readonly label: string
...@@ -21,7 +28,8 @@ export interface StructureView { ...@@ -21,7 +28,8 @@ export interface StructureView {
readonly cartoon: CartoonRepresentation readonly cartoon: CartoonRepresentation
readonly ballAndStick: BallAndStickRepresentation readonly ballAndStick: BallAndStickRepresentation
readonly axes: ShapeRepresentation<ShapeProps> readonly carbohydrate: CarbohydrateRepresentation
readonly symmetryAxes: ShapeRepresentation<ShapeProps>
readonly modelId: number readonly modelId: number
readonly assemblyId: string readonly assemblyId: string
...@@ -45,7 +53,9 @@ interface StructureViewProps { ...@@ -45,7 +53,9 @@ interface StructureViewProps {
export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>, props: StructureViewProps = {}): Promise<StructureView> { export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>, props: StructureViewProps = {}): Promise<StructureView> {
const cartoon = CartoonRepresentation() const cartoon = CartoonRepresentation()
const ballAndStick = BallAndStickRepresentation() const ballAndStick = BallAndStickRepresentation()
const axes = ShapeRepresentation() const carbohydrate = CarbohydrateRepresentation()
const symmetryAxes = ShapeRepresentation()
const polymerSphere = ShapeRepresentation()
let label: string let label: string
let model: Model | undefined let model: Model | undefined
...@@ -156,14 +166,46 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model> ...@@ -156,14 +166,46 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
useFog: false // TODO fog not working properly useFog: false // TODO fog not working properly
}, structure).run() }, structure).run()
await carbohydrate.createOrUpdate({
colorTheme: { name: 'carbohydrate-symbol' },
sizeTheme: { name: 'uniform', value: 1, factor: 1 },
useFog: false // TODO fog not working properly
}, structure).run()
viewer.center(structure.boundary.sphere.center) viewer.center(structure.boundary.sphere.center)
const mb = MeshBuilder.create()
mb.setGroup(0)
addSphere(mb, structure.boundary.sphere.center, structure.boundary.sphere.radius, 3)
addBoundingBox(mb, structure.boundary.box, 1, 2, 8)
for (let i = 0, il = structure.units.length; i < il; ++i) {
mb.setGroup(1)
const u = structure.units[i]
const ci = u.model.atomicHierarchy.chainAtomSegments.index[u.elements[0]]
const ek = u.model.atomicHierarchy.getEntityKey(ci)
if (u.model.entities.data.type.value(ek) === 'water') continue
const boundary = computeUnitBoundary(u)
addSphere(mb, boundary.sphere.center, boundary.sphere.radius, 3)
addBoundingBox(mb, boundary.box, 0.5, 2, 8)
}
const shape = Shape.create('boundary', mb.getMesh(), [Color(0xCC6633), Color(0x3366CC)], ['sphere boundary'])
await polymerSphere.createOrUpdate({
alpha: 0.5,
doubleSided: false,
depthMask: false,
useFog: false // TODO fog not working properly
}, shape).run()
} else { } else {
cartoon.destroy() cartoon.destroy()
ballAndStick.destroy() ballAndStick.destroy()
carbohydrate.destroy()
polymerSphere.destroy()
} }
viewer.add(cartoon) viewer.add(cartoon)
viewer.add(ballAndStick) viewer.add(ballAndStick)
viewer.add(carbohydrate)
viewer.add(polymerSphere)
} }
async function createSymmetryRepr() { async function createSymmetryRepr() {
...@@ -173,21 +215,21 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model> ...@@ -173,21 +215,21 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
const axesShape = getAxesShape(symmetryFeatureId, assemblySymmetry) const axesShape = getAxesShape(symmetryFeatureId, assemblySymmetry)
if (axesShape) { if (axesShape) {
// getClusterColorTheme(symmetryFeatureId, assemblySymmetry) // getClusterColorTheme(symmetryFeatureId, assemblySymmetry)
await axes.createOrUpdate({ await symmetryAxes.createOrUpdate({
colorTheme: { name: 'shape-group' }, colorTheme: { name: 'shape-group' },
// colorTheme: { name: 'uniform', value: Color(0xFFCC22) }, // colorTheme: { name: 'uniform', value: Color(0xFFCC22) },
useFog: false // TODO fog not working properly useFog: false // TODO fog not working properly
}, axesShape).run() }, axesShape).run()
} else { } else {
axes.destroy() symmetryAxes.destroy()
} }
} else { } else {
axes.destroy() symmetryAxes.destroy()
} }
} else { } else {
axes.destroy() symmetryAxes.destroy()
} }
viewer.add(axes) viewer.add(symmetryAxes)
viewer.requestDraw() viewer.requestDraw()
} }
...@@ -201,7 +243,8 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model> ...@@ -201,7 +243,8 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
cartoon, cartoon,
ballAndStick, ballAndStick,
axes, carbohydrate,
symmetryAxes,
get modelId() { return modelId }, get modelId() { return modelId },
get assemblyId() { return assemblyId }, get assemblyId() { return assemblyId },
...@@ -217,12 +260,13 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model> ...@@ -217,12 +260,13 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
destroy: () => { destroy: () => {
viewer.remove(cartoon) viewer.remove(cartoon)
viewer.remove(ballAndStick) viewer.remove(ballAndStick)
viewer.remove(axes) viewer.remove(carbohydrate)
viewer.remove(symmetryAxes)
viewer.requestDraw() viewer.requestDraw()
cartoon.destroy() cartoon.destroy()
ballAndStick.destroy() ballAndStick.destroy()
axes.destroy() symmetryAxes.destroy()
} }
} }
} }
......
...@@ -2,13 +2,115 @@ ...@@ -2,13 +2,115 @@
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* *
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
import Structure from '../structure' import Structure from '../structure'
import { Box3D, Sphere3D } from 'mol-math/geometry'; import Unit from '../unit';
import { Box3D, Sphere3D, SymmetryOperator } from 'mol-math/geometry';
import { Vec3 } from 'mol-math/linear-algebra'; import { Vec3 } from 'mol-math/linear-algebra';
import { SortedArray } from 'mol-data/int';
import { ElementIndex } from '../../model/indexing';
function computeStructureBoundary(s: Structure): { box: Box3D, sphere: Sphere3D } { export type Boundary = { box: Box3D, sphere: Sphere3D }
function computeElementsPositionBoundary(elements: SortedArray<ElementIndex>, position: SymmetryOperator.CoordinateMapper): Boundary {
const min = Vec3.create(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE)
const max = Vec3.create(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE)
const center = Vec3.zero()
let radiusSq = 0
let size = 0
const p = Vec3.zero()
size += elements.length
for (let j = 0, _j = elements.length; j < _j; j++) {
position(elements[j], p)
Vec3.min(min, min, p)
Vec3.max(max, max, p)
Vec3.add(center, center, p)
}
if (size > 0) Vec3.scale(center, center, 1/size)
for (let j = 0, _j = elements.length; j < _j; j++) {
position(elements[j], p)
const d = Vec3.squaredDistance(p, center)
if (d > radiusSq) radiusSq = d;
}
return {
box: { min, max },
sphere: { center, radius: Math.sqrt(radiusSq) }
};
}
function computeInvariantUnitBoundary(u: Unit): Boundary {
return computeElementsPositionBoundary(u.elements, u.conformation.invariantPosition)
}
export function computeUnitBoundary(u: Unit): Boundary {
return computeElementsPositionBoundary(u.elements, u.conformation.position)
}
const tmpBox = Box3D.empty()
const tmpSphere = Sphere3D.zero()
export function computeStructureBoundary(s: Structure): Boundary {
const min = Vec3.create(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE)
const max = Vec3.create(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE)
const center = Vec3.zero()
const { units } = s;
const boundaryMap: Map<number, Boundary> = new Map()
function getInvariantBoundary(u: Unit) {
let boundary: Boundary
if (boundaryMap.has(u.invariantId)) {
boundary = boundaryMap.get(u.invariantId)!
} else {
boundary = computeInvariantUnitBoundary(u)
boundaryMap.set(u.invariantId, boundary)
}
return boundary
}
let radiusSq = 0;
let size = 0;
for (let i = 0, _i = units.length; i < _i; i++) {
size += 1
const u = units[i]
const invariantBoundary = getInvariantBoundary(u)
const m = u.conformation.operator.matrix
Box3D.transform(tmpBox, invariantBoundary.box, m)
Vec3.min(min, min, tmpBox.min)
Vec3.max(max, max, tmpBox.max)
Sphere3D.transform(tmpSphere, invariantBoundary.sphere, m)
Vec3.add(center, center, tmpSphere.center)
}
if (size > 0) Vec3.scale(center, center, 1/size)
for (let i = 0, _i = units.length; i < _i; i++) {
const u = units[i]
const invariantBoundary = getInvariantBoundary(u)
const m = u.conformation.operator.matrix
Sphere3D.transform(tmpSphere, invariantBoundary.sphere, m)
const d = Vec3.squaredDistance(tmpSphere.center, center) + (tmpSphere.radius * tmpSphere.radius) * 4
if (d > radiusSq) radiusSq = d
}
const b = {
box: { min, max },
sphere: { center, radius: Math.sqrt(radiusSq) }
};
console.log(b, computeStructureBoundary2(s))
return b
}
export function computeStructureBoundary2(s: Structure): Boundary {
const min = [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE]; const min = [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE];
const max = [-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE]; const max = [-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE];
...@@ -62,6 +164,4 @@ function computeStructureBoundary(s: Structure): { box: Box3D, sphere: Sphere3D ...@@ -62,6 +164,4 @@ function computeStructureBoundary(s: Structure): { box: Box3D, sphere: Sphere3D
box: { min: Vec3.ofArray(min), max: Vec3.ofArray(max) }, box: { min: Vec3.ofArray(min), max: Vec3.ofArray(max) },
sphere: { center: Vec3.create(cx, cy, cz), radius: Math.sqrt(radiusSq) } sphere: { center: Vec3.create(cx, cy, cz), radius: Math.sqrt(radiusSq) }
}; };
} }
\ No newline at end of file
export { computeStructureBoundary }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment