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

wip, picking location and label

parent 77f7d249
No related branches found
No related tags found
No related merge requests found
......@@ -6,6 +6,7 @@
import { Task } from 'mol-task'
import { RenderObject } from 'mol-gl/render-object';
import { PickingId, PickingInfo } from '../util/picking';
export interface RepresentationProps {}
......@@ -13,4 +14,5 @@ export interface Representation<D, P extends RepresentationProps = {}> {
renderObjects: ReadonlyArray<RenderObject>
create: (data: D, props?: P) => Task<void>
update: (props: P) => Task<void>
getLabel: (pickingId: PickingId) => PickingInfo | null
}
\ No newline at end of file
......@@ -5,22 +5,26 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { Structure, StructureSymmetry, Unit } from 'mol-model/structure';
import { Structure, StructureSymmetry, Unit, Element, Queries } from 'mol-model/structure';
import { Task } from 'mol-task'
import { RenderObject } from 'mol-gl/render-object';
import { Representation, RepresentationProps } from '..';
import { ColorTheme } from '../../theme';
import { PickingId, PickingInfo } from '../../util/picking';
export interface UnitsRepresentation<P> {
renderObjects: ReadonlyArray<RenderObject>
create: (group: Unit.SymmetryGroup, props: P) => Task<void>
update: (props: P) => Task<boolean>
getLocation: (pickingId: PickingId) => Element.Location | null
}
export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P> {
renderObjects: ReadonlyArray<RenderObject>
create: (structure: Structure, props?: P) => Task<void>
update: (props: P) => Task<void>
getLocation: (pickingId: PickingId) => Element.Location | null
getLabel: (pickingId: PickingId) => PickingInfo | null
}
interface GroupRepresentation<T> {
......@@ -28,6 +32,36 @@ interface GroupRepresentation<T> {
group: Unit.SymmetryGroup
}
function label(loc: Element.Location) {
const model = loc.unit.model.label
const instance = loc.unit.label
let element = ''
if (Unit.isAtomic(loc.unit)) {
const asym_id = Queries.props.chain.auth_asym_id(loc)
const seq_id = Queries.props.residue.auth_seq_id(loc)
const comp_id = Queries.props.residue.auth_comp_id(loc)
const atom_id = Queries.props.atom.auth_atom_id(loc)
element = `[${comp_id}]${seq_id}:${asym_id}.${atom_id}`
} else if (Unit.isCoarse(loc.unit)) {
const asym_id = Queries.props.coarse.asym_id(loc)
const seq_id_begin = Queries.props.coarse.seq_id_begin(loc)
const seq_id_end = Queries.props.coarse.seq_id_end(loc)
if (seq_id_begin === seq_id_end) {
const entityKey = Queries.props.coarse.entityKey(loc)
const seq = loc.unit.model.sequence.byEntityKey[entityKey]
const comp_id = seq.compId.value(seq_id_begin)
element = `[${comp_id}]${seq_id_begin}:${asym_id}`
} else {
element = `${seq_id_begin}-${seq_id_end}:${asym_id}`
}
} else {
element = 'unknown'
}
return { label: `${model} ${instance} ${element}` }
}
export const DefaultStructureProps = {
colorTheme: { name: 'instance-index' } as ColorTheme,
alpha: 1,
......@@ -42,6 +76,14 @@ export function StructureRepresentation<P extends StructureProps>(reprCtor: () =
const groupReprs: GroupRepresentation<P>[] = []
// let currentProps: typeof DefaultStructureProps
function getLocation(pickingId: PickingId) {
for (let i = 0, il = groupReprs.length; i < il; ++i) {
const loc = groupReprs[i].repr.getLocation(pickingId)
if (loc) return loc
}
return null
}
return {
renderObjects,
create(structure: Structure, props: P = {} as P) {
......@@ -77,6 +119,11 @@ export function StructureRepresentation<P extends StructureProps>(reprCtor: () =
renderObjects.push(...repr.renderObjects)
}
})
},
getLocation,
getLabel(pickingId: PickingId) {
const loc = getLocation(pickingId)
return loc ? label(loc) : null
}
}
}
\ No newline at end of file
......@@ -18,6 +18,7 @@ import { createTransforms, createColors, createSizes } from './utils';
import { deepEqual, defaults } from 'mol-util';
import { SortedArray } from 'mol-data/int';
import { RenderableState, PointValues } from 'mol-gl/renderable';
import { PickingId } from '../../util/picking';
export const DefaultPointProps = {
colorTheme: { name: 'instance-index' } as ColorTheme,
......@@ -50,7 +51,8 @@ export function createPointVertices(unit: Unit) {
export default function Point(): UnitsRepresentation<PointProps> {
const renderObjects: RenderObject[] = []
let points: PointRenderObject
let curProps = DefaultPointProps
let currentProps = DefaultPointProps
let currentGroup: Unit.SymmetryGroup
let _units: ReadonlyArray<Unit>
let _elements: SortedArray
......@@ -58,14 +60,16 @@ export default function Point(): UnitsRepresentation<PointProps> {
return {
renderObjects,
create(group: Unit.SymmetryGroup, props: PointProps = {}) {
currentProps = Object.assign({}, DefaultPointProps, props)
return Task.create('Point.create', async ctx => {
renderObjects.length = 0 // clear
curProps = { ...DefaultPointProps, ...props }
currentGroup = group
_units = group.units
_elements = group.elements;
const { colorTheme, sizeTheme } = curProps
const { colorTheme, sizeTheme } = currentProps
const elementCount = _elements.length
const vertexMap = VertexMap.create(
......@@ -119,8 +123,8 @@ export default function Point(): UnitsRepresentation<PointProps> {
return Task.create('Point.update', async ctx => {
if (!points || !_units || !_elements) return false
const newProps = { ...curProps, ...props }
if (deepEqual(curProps, newProps)) {
const newProps = { ...currentProps, ...props }
if (deepEqual(currentProps, newProps)) {
console.log('props identical, nothing to change')
return true
}
......@@ -135,20 +139,30 @@ export default function Point(): UnitsRepresentation<PointProps> {
// fillSerial(new Uint32Array(elementCount + 1))
// )
if (!deepEqual(curProps.colorTheme, newProps.colorTheme)) {
console.log('colorTheme changed', curProps.colorTheme, newProps.colorTheme)
if (!deepEqual(currentProps.colorTheme, newProps.colorTheme)) {
console.log('colorTheme changed', currentProps.colorTheme, newProps.colorTheme)
// await ctx.update('Computing point colors');
// const color = createColors(_units, _elementGroup, vertexMap, newProps.colorTheme)
// ValueCell.update(points.props.color, color)
}
if (!deepEqual(curProps.sizeTheme, newProps.sizeTheme)) {
console.log('sizeTheme changed', curProps.sizeTheme, newProps.sizeTheme)
if (!deepEqual(currentProps.sizeTheme, newProps.sizeTheme)) {
console.log('sizeTheme changed', currentProps.sizeTheme, newProps.sizeTheme)
}
curProps = newProps
currentProps = newProps
return false
})
},
getLocation(pickingId: PickingId) {
const { objectId, instanceId, elementId } = pickingId
if (points.id === objectId) {
const l = Element.Location()
l.unit = currentGroup.units[instanceId]
l.element = currentGroup.elements[elementId]
return l
}
return null
}
}
}
......@@ -22,6 +22,7 @@ import { fillSerial } from 'mol-gl/renderable/util';
import { RenderableState, MeshValues } from 'mol-gl/renderable';
import { getMeshData } from '../../util/mesh-data';
import { Mesh } from '../../shape/mesh';
import { PickingId } from '../../util/picking';
export const DefaultSpacefillProps = {
...DefaultStructureProps,
......@@ -70,9 +71,7 @@ function createSpacefillMesh(unit: Unit, detail: number, mesh?: Mesh) {
}
}
const _mesh = meshBuilder.getMesh()
console.log(_mesh)
return _mesh
return meshBuilder.getMesh()
})
}
......@@ -171,6 +170,16 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
currentProps = newProps
return true
})
},
getLocation(pickingId: PickingId) {
const { objectId, instanceId, elementId } = pickingId
if (spheres.id === objectId) {
const l = Element.Location()
l.unit = currentGroup.units[instanceId]
l.element = currentGroup.elements[elementId]
return l
}
return null
}
}
}
......@@ -8,17 +8,20 @@ import { Task } from 'mol-task'
import { RenderObject } from 'mol-gl/render-object';
import { RepresentationProps, Representation } from '..';
import { VolumeData } from 'mol-model/volume';
import { PickingId, PickingInfo } from '../../util/picking';
export interface VolumeElementRepresentation<P> {
renderObjects: ReadonlyArray<RenderObject>
create: (volumeData: VolumeData, props: P) => Task<void>
update: (props: P) => Task<boolean>
getLabel: (pickingId: PickingId) => PickingInfo | null
}
export interface VolumeRepresentation<P extends RepresentationProps = {}> extends Representation<VolumeData, P> {
renderObjects: ReadonlyArray<RenderObject>
create: (volumeData: VolumeData, props?: P) => Task<void>
update: (props: P) => Task<void>
getLabel: (pickingId: PickingId) => PickingInfo | null
}
export function VolumeRepresentation<P>(reprCtor: () => VolumeElementRepresentation<P>): VolumeRepresentation<P> {
......@@ -35,6 +38,9 @@ export function VolumeRepresentation<P>(reprCtor: () => VolumeElementRepresentat
},
update(props: P) {
return Task.create('VolumeRepresentation.update', async ctx => {})
},
getLabel(pickingId: PickingId) {
return null
}
}
}
\ No newline at end of file
......@@ -17,6 +17,7 @@ import { Mat4 } from 'mol-math/linear-algebra';
import { createUniformColor } from '../../util/color-data';
import { getMeshData } from '../../util/mesh-data';
import { RenderableState, MeshValues } from 'mol-gl/renderable';
import { PickingId } from '../../util/picking';
export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValue) {
return Task.create<Mesh>('Volume Surface', async ctx => {
......@@ -99,6 +100,9 @@ export default function Surface(): VolumeElementRepresentation<SurfaceProps> {
// TODO
return false
})
},
getLabel(pickingId: PickingId) {
return null
}
}
}
......@@ -62,7 +62,6 @@ export function createAttributeColor(props: AttributeColorProps, colorData?: Col
}
}
if (colorData) {
console.log('update colordata attribute')
ValueCell.update(colorData.aColor, colors)
if (colorData.dColorType.ref.value !== 'attribute') {
ValueCell.update(colorData.dColorType, 'attribute')
......@@ -81,7 +80,6 @@ export function createAttributeColor(props: AttributeColorProps, colorData?: Col
export function createTextureColor(colors: TextureImage, type: ColorType, colorData?: ColorData): ColorData {
if (colorData) {
console.log('update colordata texture')
ValueCell.update(colorData.tColor, colors)
ValueCell.update(colorData.uColorTexSize, Vec2.create(colors.width, colors.height))
if (colorData.dColorType.ref.value !== type) {
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
function decodeFloatRGBA(r: number, g: number, b: number) {
r = Math.floor(r)
g = Math.floor(g)
b = Math.floor(b)
return r * 256 * 256 + g * 256 + b
}
export function decodeIdRGBA(r: number, g: number, b: number) {
return decodeFloatRGBA(r, g, b) - 1
}
export interface PickingId {
objectId: number
instanceId: number
elementId: number
}
export interface PickingInfo {
label: string
data?: any
}
\ No newline at end of file
......@@ -21,23 +21,7 @@ import { Representation } from 'mol-geo/representation';
import { createRenderTarget } from 'mol-gl/webgl/render-target';
import Scene from 'mol-gl/scene';
import { RenderVariant } from 'mol-gl/webgl/render-item';
function decodeFloatRGBA(r: number, g: number, b: number) {
r = Math.floor(r)
g = Math.floor(g)
b = Math.floor(b)
return r * 256 * 256 + g * 256 + b
}
function decodeIdRGBA(r: number, g: number, b: number) {
return decodeFloatRGBA(r, g, b) - 1
}
interface PickingId {
objectId: number
instanceId: number
elementId: number
}
import { PickingId, decodeIdRGBA } from 'mol-geo/util/picking';
interface Viewer {
center: (p: Vec3) => void
......@@ -94,7 +78,12 @@ namespace Viewer {
input.resize.subscribe(handleResize)
input.move.subscribe(({x, y}) => {
const p = identify(x, y)
identified.next(`Object: ${p.objectId}, Instance: ${p.instanceId}, Element: ${p.elementId}`)
let label = ''
reprMap.forEach((roSet, repr) => {
const info = repr.getLabel(p)
if (info) label = info.label
})
identified.next(`Object: ${p.objectId}, Instance: ${p.instanceId}, Element: ${p.elementId}, Label: ${label}`)
})
const camera = PerspectiveCamera.create({
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment