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

wip, cartoon

parent 270d1b91
No related branches found
No related tags found
No related merge requests found
...@@ -52,18 +52,22 @@ export function projectValue({ segments }: Segmentation, set: OrderedSet, value: ...@@ -52,18 +52,22 @@ export function projectValue({ segments }: Segmentation, set: OrderedSet, value:
} }
export class SegmentIterator<T extends number = number> implements Iterator<Segs.Segment<T>> { export class SegmentIterator<T extends number = number> implements Iterator<Segs.Segment<T>> {
private segmentMin = 0; private _segmentMin = 0;
private segmentMax = 0; private _segmentMax = 0;
private segmentCur = 0;
private setRange = Interval.Empty; private setRange = Interval.Empty;
private value: Segs.Segment<T> = { index: 0, start: 0 as T, end: 0 as T }; private value: Segs.Segment<T> = { index: 0, start: 0 as T, end: 0 as T };
hasNext: boolean = false; hasNext: boolean = false;
get segmentMin() { return this._segmentMin }
get segmentMax() { return this._segmentMax }
move() { move() {
while (this.hasNext) { while (this.hasNext) {
if (this.updateValue()) { if (this.updateValue()) {
this.value.index = this.segmentMin++; this.value.index = this.segmentCur++;
this.hasNext = this.segmentMax >= this.segmentMin && Interval.size(this.setRange) > 0; this.hasNext = this._segmentMax >= this.segmentCur && Interval.size(this.setRange) > 0;
break; break;
} else { } else {
this.updateSegmentRange(); this.updateSegmentRange();
...@@ -73,7 +77,7 @@ export class SegmentIterator<T extends number = number> implements Iterator<Segs ...@@ -73,7 +77,7 @@ export class SegmentIterator<T extends number = number> implements Iterator<Segs
} }
private updateValue() { private updateValue() {
const segmentEnd = this.segments[this.segmentMin + 1]; const segmentEnd = this.segments[this.segmentCur + 1];
// TODO: add optimized version for interval and array? // TODO: add optimized version for interval and array?
const setEnd = OrderedSet.findPredecessorIndexInInterval(this.set, segmentEnd, this.setRange); const setEnd = OrderedSet.findPredecessorIndexInInterval(this.set, segmentEnd, this.setRange);
this.value.start = Interval.start(this.setRange) as T; this.value.start = Interval.start(this.setRange) as T;
...@@ -89,10 +93,11 @@ export class SegmentIterator<T extends number = number> implements Iterator<Segs ...@@ -89,10 +93,11 @@ export class SegmentIterator<T extends number = number> implements Iterator<Segs
return; return;
} }
this.segmentMin = this.segmentMap[OrderedSet.getAt(this.set, sMin)]; this.segmentCur = this.segmentMap[OrderedSet.getAt(this.set, sMin)];
this.segmentMax = this.segmentMap[OrderedSet.getAt(this.set, sMax)]; this._segmentMax = this.segmentMap[OrderedSet.getAt(this.set, sMax)];
this.hasNext = this.segmentMax >= this.segmentMin; this._segmentMin = this.segmentCur
this.hasNext = this._segmentMax >= this.segmentCur;
} }
setSegment(segment: Segs.Segment<T>) { setSegment(segment: Segs.Segment<T>) {
......
...@@ -26,17 +26,11 @@ import { MeshBuilder } from '../../../shape/mesh-builder'; ...@@ -26,17 +26,11 @@ import { MeshBuilder } from '../../../shape/mesh-builder';
import { getPolymerElementCount, PolymerTraceIterator } from './util/polymer'; import { getPolymerElementCount, PolymerTraceIterator } from './util/polymer';
import { Vec3 } from 'mol-math/linear-algebra'; import { Vec3 } from 'mol-math/linear-algebra';
// export function spline(target: THREE.Vector3, p1: THREE.Vector3, p2: THREE.Vector3, p3: THREE.Vector3, t: number) { export function reflect(target: Vec3, p1: Vec3, p2: Vec3, amount: number) {
// let a = Math.pow(1 - t, 2) / 2; target[0] = p1[0] - amount * (p2[0] - p1[0])
// let c = Math.pow(t, 2) / 2; target[1] = p1[1] - amount * (p2[1] - p1[1])
// let b = 1 - a - c; target[2] = p1[2] - amount * (p2[2] - p1[2])
}
// let x = a * p1.x + b * p2.x + c * p3.x;
// let y = a * p1.y + b * p2.y + c * p3.y;
// let z = a * p1.z + b * p2.z + c * p3.z;
// target.set(x, y, z);
// }
async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Mesh) { async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Mesh) {
const polymerElementCount = getPolymerElementCount(unit) const polymerElementCount = getPolymerElementCount(unit)
...@@ -45,34 +39,150 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me ...@@ -45,34 +39,150 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me
// TODO better vertex count estimates // TODO better vertex count estimates
const builder = MeshBuilder.create(polymerElementCount * 30, polymerElementCount * 30 / 2, mesh) const builder = MeshBuilder.create(polymerElementCount * 30, polymerElementCount * 30 / 2, mesh)
const linearSegmentCount = 10 const linearSegments = 5
const radialSegments = 8
const tension = 0.9
const tA = Vec3.zero()
const tB = Vec3.zero()
const dA = Vec3.zero()
const dB = Vec3.zero()
const torsionVec = Vec3.zero()
const initialTorsionVec = Vec3.zero()
const tangentVec = Vec3.zero()
const normalVec = Vec3.zero()
const v0 = Vec3.zero() const tmp = Vec3.zero()
const v1 = Vec3.zero() const reflectedControlPoint = Vec3.zero()
const pn = (linearSegments + 1) * 3
const controlPoints = new Float32Array(pn)
const torsionVectors = new Float32Array(pn)
const normalVectors = new Float32Array(pn)
let i = 0 let i = 0
const polymerTraceIt = PolymerTraceIterator(unit) const polymerTraceIt = PolymerTraceIterator(unit)
while (polymerTraceIt.hasNext) { while (polymerTraceIt.hasNext) {
const v = polymerTraceIt.move() const v = polymerTraceIt.move()
builder.setId(v.index)
Vec3.spline(v1, v.c0, v.c1, v.c2, v.c3, 0.5, 0.5) Vec3.spline(tB, v.t1, v.t2, v.t3, v.t4, 0.5, tension)
Vec3.spline(dA, v.d12, v.d23, v.d34, v.d45, 0.5, tension)
builder.setId(v.index) Vec3.normalize(initialTorsionVec, Vec3.sub(initialTorsionVec, tB, dB))
for (let j = 1; j <= linearSegmentCount; ++j) {
let t = j * 1.0 / linearSegmentCount; Vec3.toArray(tB, controlPoints, 0)
Vec3.copy(v0, v1) Vec3.normalize(torsionVec, Vec3.sub(torsionVec, tB, dB))
Vec3.toArray(torsionVec, torsionVectors, 0)
// approximate tangent as direction to previous control point
Vec3.normalize(tangentVec, Vec3.sub(tangentVec, tB, tA))
Vec3.normalize(normalVec, Vec3.cross(normalVec, tangentVec, torsionVec))
Vec3.toArray(normalVec, normalVectors, 0)
//
const t12 = Vec3.zero()
const t23 = Vec3.zero()
const t34 = Vec3.zero()
const t45 = Vec3.zero()
Vec3.spline(t12, v.t0, v.t1, v.t2, v.t3, 0.5, tension)
Vec3.spline(t23, v.t1, v.t2, v.t3, v.t4, 0.5, tension)
Vec3.spline(t34, v.t2, v.t3, v.t4, v.t5, 0.5, tension)
Vec3.spline(t45, v.t3, v.t4, v.t5, v.t6, 0.5, tension)
// const dp12 = Vec3.zero()
// const dp23 = Vec3.zero()
// const dp34 = Vec3.zero()
// const dp45 = Vec3.zero()
// Vec3.projectPointOnVector(dp12, v.d12, t12, v.t1)
// Vec3.projectPointOnVector(dp23, v.d23, t23, v.t2)
// Vec3.projectPointOnVector(dp34, v.d34, t34, v.t3)
// Vec3.projectPointOnVector(dp45, v.d45, t45, v.t4)
const td12 = Vec3.zero()
const td23 = Vec3.zero()
const td34 = Vec3.zero()
const td45 = Vec3.zero()
Vec3.normalize(td12, Vec3.sub(td12, t12, v.d12))
Vec3.scaleAndAdd(v.d12, t12, td12, 1)
Vec3.normalize(td23, Vec3.sub(td23, t23, v.d23))
if (Vec3.dot(td12, td23) < 0) {
Vec3.scaleAndAdd(v.d23, t23, td23, -1)
console.log('foo td0 td1')
} else {
Vec3.scaleAndAdd(v.d23, t23, td23, 1)
}
Vec3.normalize(td34, Vec3.sub(td34, t34, v.d34))
if (Vec3.dot(td12, td34) < 0) {
Vec3.scaleAndAdd(v.d34, t34, td34, -1)
console.log('foo td1 td2')
} else {
Vec3.scaleAndAdd(v.d34, t34, td34, 1)
}
Vec3.normalize(td45, Vec3.sub(td45, t45, v.d45))
if (Vec3.dot(td12, td45) < 0) {
Vec3.scaleAndAdd(v.d45, t45, td45, -1)
console.log('foo td2 td3')
} else {
Vec3.scaleAndAdd(v.d45, t45, td45, 1)
}
// console.log(td0, td1, td2, td3)
builder.addIcosahedron(t12, 0.3, 1)
builder.addIcosahedron(t23, 0.3, 1)
builder.addIcosahedron(t34, 0.3, 1)
builder.addIcosahedron(t45, 0.3, 1)
// builder.addIcosahedron(dp12, 0.3, 1)
// builder.addIcosahedron(dp23, 0.3, 1)
// builder.addIcosahedron(dp34, 0.3, 1)
// builder.addIcosahedron(dp45, 0.3, 1)
builder.addIcosahedron(v.d12, 0.3, 1)
builder.addIcosahedron(v.d23, 0.3, 1)
builder.addIcosahedron(v.d34, 0.3, 1)
builder.addIcosahedron(v.d45, 0.3, 1)
for (let j = 1; j <= linearSegments; ++j) {
const t = j * 1.0 / linearSegments;
Vec3.copy(tA, tB)
// if ((v.last && t > 0.5) || (v.first && t < 0.5)) break // if ((v.last && t > 0.5) || (v.first && t < 0.5)) break
if (t < 0.5) { if (t < 0.5) {
Vec3.spline(v1, v.c0, v.c1, v.c2, v.c3, t + 0.5, 0.5) Vec3.spline(tB, v.t1, v.t2, v.t3, v.t4, t + 0.5, tension)
} else { } else {
Vec3.spline(v1, v.c1, v.c2, v.c3, v.c4, t - 0.5, 0.5) Vec3.spline(tB, v.t2, v.t3, v.t4, v.t5, t - 0.5, tension)
} }
Vec3.spline(dB, v.d12, v.d23, v.d34, v.d45, t, tension)
// reflect(reflectedControlPoint, tB, tA, 1)
Vec3.toArray(tB, controlPoints, j * 3)
Vec3.normalize(torsionVec, Vec3.sub(torsionVec, tB, dB))
// if (Vec3.dot(initialTorsionVec, torsionVec) < 0) Vec3.scale(torsionVec, torsionVec, -1)
Vec3.toArray(torsionVec, torsionVectors, j * 3)
// approximate tangent as direction to previous control point
Vec3.normalize(tangentVec, Vec3.sub(tangentVec, tB, tA))
Vec3.normalize(normalVec, Vec3.cross(normalVec, tangentVec, torsionVec))
Vec3.toArray(normalVec, normalVectors, j * 3)
// TODO size theme // TODO size theme
builder.addCylinder(v0, v1, 1.0, { radiusTop: 0.1, radiusBottom: 0.1 }) // builder.addCylinder(tA, tB, 1.0, { radiusTop: 0.3, radiusBottom: 0.3 })
builder.addIcosahedron(dB, 0.1, 1)
builder.addCylinder(tB, Vec3.add(tmp, tB, torsionVec), 1.0, { radiusTop: 0.1, radiusBottom: 0.1 })
// builder.addCylinder(tB, Vec3.add(tmp, tB, normalVec), 1.0, { radiusTop: 0.1, radiusBottom: 0.1 })
console.log(tA, tB)
} }
builder.addTube(controlPoints, torsionVectors, normalVectors, linearSegments, radialSegments)
if (i % 10000 === 0 && ctx.shouldUpdate) { if (i % 10000 === 0 && ctx.shouldUpdate) {
await ctx.update({ message: 'Backbone mesh', current: i, max: polymerElementCount }); await ctx.update({ message: 'Polymer trace mesh', current: i, max: polymerElementCount });
} }
++i ++i
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
import { Unit, Element, StructureProperties, Model } from 'mol-model/structure'; import { Unit, Element, StructureProperties, Model } from 'mol-model/structure';
import { Segmentation } from 'mol-data/int'; import { Segmentation, Interval } from 'mol-data/int';
import { MoleculeType } from 'mol-model/structure/model/types'; import { MoleculeType } from 'mol-model/structure/model/types';
import Iterator from 'mol-data/iterator'; import Iterator from 'mol-data/iterator';
import { SegmentIterator } from 'mol-data/int/impl/segmentation'; import { SegmentIterator } from 'mol-data/int/impl/segmentation';
...@@ -83,8 +83,12 @@ function getTraceName2(model: Model, residueModelIndex: number) { ...@@ -83,8 +83,12 @@ function getTraceName2(model: Model, residueModelIndex: number) {
let traceName = '' let traceName = ''
if (moleculeType === MoleculeType.protein) { if (moleculeType === MoleculeType.protein) {
traceName = 'CA' traceName = 'CA'
} else if (moleculeType === MoleculeType.DNA || moleculeType === MoleculeType.RNA) { } else if (moleculeType === MoleculeType.DNA) {
traceName = 'P' // traceName = 'P'
traceName = 'C3\''
} else if (moleculeType === MoleculeType.RNA) {
// traceName = 'P'
traceName = 'C4\''
} }
return traceName return traceName
} }
...@@ -99,6 +103,32 @@ function getTraceElement2(model: Model, residueModelSegment: Segmentation.Segmen ...@@ -99,6 +103,32 @@ function getTraceElement2(model: Model, residueModelSegment: Segmentation.Segmen
return residueModelSegment.start return residueModelSegment.start
} }
function getDirectionName2(model: Model, residueModelIndex: number) {
const compId = model.atomicHierarchy.residues.label_comp_id.value(residueModelIndex)
const chemCompMap = model.properties.chemicalComponentMap
const cc = chemCompMap.get(compId)
const moleculeType = cc ? cc.moleculeType : MoleculeType.unknown
let traceName = ''
if (moleculeType === MoleculeType.protein) {
traceName = 'O'
} else if (moleculeType === MoleculeType.DNA) {
traceName = 'O4\''
} else if (moleculeType === MoleculeType.RNA) {
traceName = 'C3\''
}
return traceName
}
function getDirectionElement2(model: Model, residueModelSegment: Segmentation.Segment<Element>) {
const traceName = getDirectionName2(model, residueModelSegment.index)
for (let j = residueModelSegment.start, _j = residueModelSegment.end; j < _j; j++) {
if (model.atomicHierarchy.atoms.label_atom_id.value(j) === traceName) return j
}
console.log('direction name element not found', { ...residueModelSegment })
return residueModelSegment.start
}
/** Iterates over consecutive pairs of residues/coarse elements in polymers */ /** Iterates over consecutive pairs of residues/coarse elements in polymers */
...@@ -268,8 +298,8 @@ export class CoarsePolymerBackboneIterator<T extends number = number> implements ...@@ -268,8 +298,8 @@ export class CoarsePolymerBackboneIterator<T extends number = number> implements
/** /**
* Iterates over individual residues/coarse elements in polymers while providing information * Iterates over individual residues/coarse elements in polymers of a unit while
* about the neighbourhood in the underlying model for drawing splines * providing information about the neighbourhood in the underlying model for drawing splines
*/ */
export function PolymerTraceIterator(unit: Unit): Iterator<PolymerTraceElement> { export function PolymerTraceIterator(unit: Unit): Iterator<PolymerTraceElement> {
switch (unit.kind) { switch (unit.kind) {
...@@ -285,51 +315,63 @@ interface PolymerTraceElement { ...@@ -285,51 +315,63 @@ interface PolymerTraceElement {
index: number index: number
first: boolean first: boolean
last: boolean last: boolean
c0: Vec3
c1: Vec3 t0: Vec3
c2: Vec3 t1: Vec3
c3: Vec3 t2: Vec3
c4: Vec3 t3: Vec3
t4: Vec3
t5: Vec3
t6: Vec3
d12: Vec3
d23: Vec3
d34: Vec3
d45: Vec3
} }
function createPolymerTraceElement (unit: Unit) { function createPolymerTraceElement (unit: Unit): PolymerTraceElement {
return { return {
center: Element.Location(unit), center: Element.Location(unit),
index: 0, index: 0,
first: false, first: false,
last: false, last: false,
c0: Vec3.zero(),
c1: Vec3.zero(), t0: Vec3.zero(),
c2: Vec3.zero(), t1: Vec3.zero(),
c3: Vec3.zero(), t2: Vec3.zero(),
c4: Vec3.zero() t3: Vec3.zero(),
t4: Vec3.zero(),
t5: Vec3.zero(),
t6: Vec3.zero(),
d12: Vec3.zero(),
d23: Vec3.zero(),
d34: Vec3.zero(),
d45: Vec3.zero(),
} }
} }
const enum AtomicPolymerTraceIteratorState { nextPolymer, nextResidue } const enum AtomicPolymerTraceIteratorState { nextPolymer, nextResidue }
function setSegment (outSegment: Segmentation.Segment<Element>, index: number, segments: Segmentation<Element>, boundingSegment: Segmentation.Segment<Element>): Segmentation.Segment<Element> { function setSegment (outSegment: Segmentation.Segment<Element>, index: number, segments: Segmentation<Element>, min: number, max: number): Segmentation.Segment<Element> {
index = Math.min(Math.max(0, index), segments.segments.length - 2) // index = Math.min(Math.max(0, index), segments.segments.length - 2)
outSegment.index = index const _index = Math.min(Math.max(min, index), max)
outSegment.start = segments.segments[index] if (isNaN(_index)) console.log(_index, index, min, max)
outSegment.end = segments.segments[index + 1] outSegment.index = _index
outSegment.start = segments.segments[_index]
outSegment.end = segments.segments[_index + 1]
// console.log(index, {...outSegment}, {...boundingSegment}, segments.segments[boundingSegment.index])
return outSegment return outSegment
} }
// const p0 = Vec3.zero()
// const p1 = Vec3.zero()
// const p2 = Vec3.zero()
// const p3 = Vec3.zero()
// const p4 = Vec3.zero()
// const p5 = Vec3.zero()
// const p6 = Vec3.zero()
export class AtomicPolymerTraceIterator<T extends number = number> implements Iterator<PolymerTraceElement> { export class AtomicPolymerTraceIterator<T extends number = number> implements Iterator<PolymerTraceElement> {
private value: PolymerTraceElement private value: PolymerTraceElement
private polymerIt: SegmentIterator<Element> private polymerIt: SegmentIterator<Element>
private residueIt: SegmentIterator<Element> private residueIt: SegmentIterator<Element>
private polymerSegment: Segmentation.Segment<Element> private residueSegmentMin: number
private residueSegmentMax: number
private state: AtomicPolymerTraceIteratorState = AtomicPolymerTraceIteratorState.nextPolymer private state: AtomicPolymerTraceIteratorState = AtomicPolymerTraceIteratorState.nextPolymer
private residueSegments: Segmentation<Element> private residueSegments: Segmentation<Element>
...@@ -345,42 +387,62 @@ export class AtomicPolymerTraceIterator<T extends number = number> implements It ...@@ -345,42 +387,62 @@ export class AtomicPolymerTraceIterator<T extends number = number> implements It
target[2] = this.unit.model.atomicConformation.z[index] target[2] = this.unit.model.atomicConformation.z[index]
} }
updateResidueSegmentRange(polymerSegment: Segmentation.Segment<Element>) {
const { polymerSegments, residueSegments } = this.unit.model.atomicHierarchy
const sMin = polymerSegments.segments[polymerSegment.index]
const sMax = polymerSegments.segments[polymerSegment.index + 1] - 1
this.residueSegmentMin = residueSegments.segmentMap[sMin]
this.residueSegmentMax = residueSegments.segmentMap[sMax]
}
move() { move() {
const { residueIt, polymerIt, value } = this const { residueIt, polymerIt, value } = this
value.first = false
value.last = false
if (this.state === AtomicPolymerTraceIteratorState.nextPolymer) { if (this.state === AtomicPolymerTraceIteratorState.nextPolymer) {
if (polymerIt.hasNext) { if (polymerIt.hasNext) {
this.polymerSegment = polymerIt.move(); const polymerSegment = polymerIt.move();
residueIt.setSegment(this.polymerSegment); residueIt.setSegment(polymerSegment);
this.updateResidueSegmentRange(polymerSegment)
this.state = AtomicPolymerTraceIteratorState.nextResidue this.state = AtomicPolymerTraceIteratorState.nextResidue
value.first = true
} }
} }
if (this.state === AtomicPolymerTraceIteratorState.nextResidue) { if (this.state === AtomicPolymerTraceIteratorState.nextResidue) {
const { tmpSegment, residueSegments, residueSegmentMin, residueSegmentMax } = this
const residueSegment = residueIt.move(); const residueSegment = residueIt.move();
const resSegIdx = residueSegment.index
value.index = setTraceElement(value.center, residueSegment) value.index = setTraceElement(value.center, residueSegment)
setSegment(this.tmpSegment, residueSegment.index - 2, this.residueSegments, this.polymerSegment) setSegment(tmpSegment, resSegIdx - 3, residueSegments, residueSegmentMin, residueSegmentMax)
this.pos(value.c0, getTraceElement2(this.unit.model, this.tmpSegment)) this.pos(value.t0, getTraceElement2(this.unit.model, tmpSegment))
setSegment(tmpSegment, resSegIdx - 2, residueSegments, residueSegmentMin, residueSegmentMax)
this.pos(value.t1, getTraceElement2(this.unit.model, tmpSegment))
this.pos(value.d12, getDirectionElement2(this.unit.model, tmpSegment))
setSegment(tmpSegment, resSegIdx - 1, residueSegments, residueSegmentMin, residueSegmentMax)
this.pos(value.t2, getTraceElement2(this.unit.model, tmpSegment))
this.pos(value.d23, getDirectionElement2(this.unit.model, tmpSegment))
setSegment(tmpSegment, resSegIdx, residueSegments, residueSegmentMin, residueSegmentMax)
this.pos(value.t3, getTraceElement2(this.unit.model, tmpSegment))
this.pos(value.d34, getDirectionElement2(this.unit.model, tmpSegment))
setSegment(this.tmpSegment, residueSegment.index - 1, this.residueSegments, this.polymerSegment) setSegment(tmpSegment, resSegIdx + 1, residueSegments, residueSegmentMin, residueSegmentMax)
this.pos(value.c1, getTraceElement2(this.unit.model, this.tmpSegment)) this.pos(value.t4, getTraceElement2(this.unit.model, tmpSegment))
this.pos(value.d45, getDirectionElement2(this.unit.model, tmpSegment))
setSegment(this.tmpSegment, residueSegment.index, this.residueSegments, this.polymerSegment) setSegment(tmpSegment, resSegIdx + 2, residueSegments, residueSegmentMin, residueSegmentMax)
this.pos(value.c2, getTraceElement2(this.unit.model, this.tmpSegment)) this.pos(value.t5, getTraceElement2(this.unit.model, tmpSegment))
setSegment(this.tmpSegment, residueSegment.index + 1, this.residueSegments, this.polymerSegment) setSegment(tmpSegment, resSegIdx + 3, residueSegments, residueSegmentMin, residueSegmentMax)
this.pos(value.c3, getTraceElement2(this.unit.model, this.tmpSegment)) this.pos(value.t6, getTraceElement2(this.unit.model, tmpSegment))
setSegment(this.tmpSegment, residueSegment.index + 2, this.residueSegments, this.polymerSegment) value.first = resSegIdx === residueSegmentMin
this.pos(value.c4, getTraceElement2(this.unit.model, this.tmpSegment)) value.last = resSegIdx === residueSegmentMax
if (!residueIt.hasNext) { if (!residueIt.hasNext) {
this.state = AtomicPolymerTraceIteratorState.nextPolymer this.state = AtomicPolymerTraceIteratorState.nextPolymer
value.last = true
} }
} }
......
...@@ -27,6 +27,7 @@ export interface MeshBuilder { ...@@ -27,6 +27,7 @@ export interface MeshBuilder {
addDoubleCylinder(start: Vec3, end: Vec3, lengthScale: number, shift: Vec3, props: CylinderProps): void addDoubleCylinder(start: Vec3, end: Vec3, lengthScale: number, shift: Vec3, props: CylinderProps): void
addFixedCountDashedCylinder(start: Vec3, end: Vec3, lengthScale: number, segmentCount: number, props: CylinderProps): void addFixedCountDashedCylinder(start: Vec3, end: Vec3, lengthScale: number, segmentCount: number, props: CylinderProps): void
addIcosahedron(center: Vec3, radius: number, detail: number): void addIcosahedron(center: Vec3, radius: number, detail: number): void
addTube(controlPoints: Helpers.NumberArray, torsionVectors: Helpers.NumberArray, normalVectors: Helpers.NumberArray, linearSegments: number, radialSegments: number): void
setId(id: number): void setId(id: number): void
getMesh(): Mesh getMesh(): Mesh
} }
...@@ -175,6 +176,84 @@ export namespace MeshBuilder { ...@@ -175,6 +176,84 @@ export namespace MeshBuilder {
setIcosahedronMat(tmpIcosahedronMat, center) setIcosahedronMat(tmpIcosahedronMat, center)
add(tmpIcosahedronMat, vertices, normals, indices) add(tmpIcosahedronMat, vertices, normals, indices)
}, },
addTube: (controlPoints: Helpers.NumberArray, torsionVectors: Helpers.NumberArray, normalVectors: Helpers.NumberArray, linearSegments: number, radialSegments: number) => {
console.log(controlPoints, torsionVectors, normalVectors, linearSegments, radialSegments)
const ico = getIcosahedron({ radius: 0.1, detail: 1 })
const radialVector = Vec3.zero()
const normalVector = Vec3.zero()
const tempPos = Vec3.zero()
const a = Vec3.zero()
const b = Vec3.zero()
const u = Vec3.zero()
const v = Vec3.zero()
const waveFactor = 1
const width = 0.6
const height = 0.2
const vertexCount = vertices.elementCount
const di = 1 / linearSegments
for (let i = 0; i <= linearSegments; ++i) {
const i3 = i * 3
Vec3.fromArray(u, torsionVectors, i3)
Vec3.fromArray(v, normalVectors, i3)
const tt = di * i - 0.5;
const ff = 1 + (waveFactor - 1) * (Math.cos(2 * Math.PI * tt) + 1);
const w = ff * width, h = ff * height;
for (let j = 0; j < radialSegments; ++j) {
let t = 2 * Math.PI * j / radialSegments;
Vec3.copy(a, u)
Vec3.copy(b, v)
Vec3.add(
radialVector,
Vec3.scale(a, a, w * Math.cos(t)),
Vec3.scale(b, b, h * Math.sin(t))
)
Vec3.copy(a, u)
Vec3.copy(b, v)
Vec3.add(
normalVector,
Vec3.scale(a, a, h * Math.cos(t)),
Vec3.scale(b, b, w * Math.sin(t))
)
Vec3.normalize(normalVector, normalVector)
Vec3.fromArray(tempPos, controlPoints, i3)
Vec3.add(tempPos, tempPos, radialVector)
ChunkedArray.add3(vertices, tempPos[0], tempPos[1], tempPos[2]);
ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]);
ChunkedArray.add(ids, currentId);
// setIcosahedronMat(tmpIcosahedronMat, tempPos)
// add(tmpIcosahedronMat, ico.vertices, ico.normals, ico.indices)
}
}
for (let i = 0; i < linearSegments; ++i) {
for (let j = 0; j < radialSegments; ++j) {
ChunkedArray.add3(
indices,
(vertexCount + i * radialSegments + (j + 1) % radialSegments),
(vertexCount + (i + 1) * radialSegments + (j + 1) % radialSegments),
(vertexCount + i * radialSegments + j)
);
ChunkedArray.add3(
indices,
(vertexCount + (i + 1) * radialSegments + (j + 1) % radialSegments),
(vertexCount + (i + 1) * radialSegments + j),
(vertexCount + i * radialSegments + j)
);
}
}
},
setId: (id: number) => { setId: (id: number) => {
if (currentId !== id) { if (currentId !== id) {
currentId = id currentId = id
......
...@@ -380,6 +380,13 @@ namespace Vec3 { ...@@ -380,6 +380,13 @@ namespace Vec3 {
return v[0] === 0 && v[1] === 0 && v[2] === 0 return v[0] === 0 && v[1] === 0 && v[2] === 0
} }
export function projectPointOnVector(out: Vec3, point: Vec3, vector: Vec3, origin: Vec3) {
// point.sub(origin).projectOnVector(vector).add(origin)
Vec3.sub(out, Vec3.copy(out, point), origin)
const scalar = Vec3.dot(vector, out) / Vec3.squaredMagnitude(vector);
return Vec3.add(out, Vec3.scale(out, Vec3.copy(out, vector), scalar), origin);
}
export function toString(a: Vec3) { export function toString(a: Vec3) {
return `[${a[0]} ${a[1]} ${a[2]}]`; return `[${a[0]} ${a[1]} ${a[2]}]`;
} }
......
...@@ -73,14 +73,14 @@ export class Stage { ...@@ -73,14 +73,14 @@ export class Stage {
// this.loadPdbid('1jj2') // this.loadPdbid('1jj2')
// this.loadPdbid('4umt') // ligand has bond with order 3 // this.loadPdbid('4umt') // ligand has bond with order 3
// this.loadPdbid('1crn') // small this.loadPdbid('1crn') // small
// this.loadPdbid('1hrv') // viral assembly // this.loadPdbid('1hrv') // viral assembly
// this.loadPdbid('1rb8') // virus // this.loadPdbid('1rb8') // virus
// this.loadPdbid('1blu') // metal coordination // this.loadPdbid('1blu') // metal coordination
// this.loadPdbid('3pqr') // inter unit bonds // this.loadPdbid('3pqr') // inter unit bonds
// this.loadPdbid('4v5a') // ribosome // this.loadPdbid('4v5a') // ribosome
// this.loadPdbid('3j3q') // ... // this.loadPdbid('3j3q') // ...
this.loadPdbid('3sn6') // discontinuous chains // this.loadPdbid('3sn6') // discontinuous chains
// this.loadMmcifUrl(`../../examples/1cbs_full.bcif`) // this.loadMmcifUrl(`../../examples/1cbs_full.bcif`)
// this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000001.cif`) // ok // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000001.cif`) // ok
...@@ -103,7 +103,7 @@ export class Stage { ...@@ -103,7 +103,7 @@ export class Stage {
const modelEntity = await MmcifUrlToModel.apply(this.ctx, urlEntity) const modelEntity = await MmcifUrlToModel.apply(this.ctx, urlEntity)
const structureEntity = await ModelToStructure.apply(this.ctx, modelEntity) const structureEntity = await ModelToStructure.apply(this.ctx, modelEntity)
// StructureToBallAndStick.apply(this.ctx, structureEntity, { ...ballAndStickProps, visible: true }) StructureToBallAndStick.apply(this.ctx, structureEntity, { ...ballAndStickProps, visible: false })
StructureToSpacefill.apply(this.ctx, structureEntity, { ...spacefillProps, visible: false }) StructureToSpacefill.apply(this.ctx, structureEntity, { ...spacefillProps, visible: false })
StructureToDistanceRestraint.apply(this.ctx, structureEntity, { ...distanceRestraintProps, visible: false }) StructureToDistanceRestraint.apply(this.ctx, structureEntity, { ...distanceRestraintProps, visible: false })
// StructureToBackbone.apply(this.ctx, structureEntity, { ...backboneProps, visible: true }) // StructureToBackbone.apply(this.ctx, structureEntity, { ...backboneProps, visible: true })
...@@ -111,13 +111,14 @@ export class Stage { ...@@ -111,13 +111,14 @@ export class Stage {
this.globalContext.components.sequenceView.setState({ structure: structureEntity.value }); this.globalContext.components.sequenceView.setState({ structure: structureEntity.value });
const structureEntity2 = await ModelToStructure.apply(this.ctx, modelEntity) // const structureEntity2 = await ModelToStructure.apply(this.ctx, modelEntity)
const q1 = Q.generators.atoms({ // const q1 = Q.generators.atoms({
residueTest: l => SP.residue.label_seq_id(l) > 30 // residueTest: l => SP.residue.label_seq_id(l) < 10
}); // });
structureEntity2.value = Selection.unionStructure(await Query(q1)(structureEntity2.value).run()); // structureEntity2.value = Selection.unionStructure(await Query(q1)(structureEntity2.value).run());
StructureToBackbone.apply(this.ctx, structureEntity2, { ...backboneProps, visible: true }) // StructureToBackbone.apply(this.ctx, structureEntity2, { ...backboneProps, visible: true })
StructureToCartoon.apply(this.ctx, structureEntity2, { ...cartoonProps, visible: true }) // StructureToCartoon.apply(this.ctx, structureEntity2, { ...cartoonProps, visible: true })
// StructureToBallAndStick.apply(this.ctx, structureEntity2, { ...ballAndStickProps, visible: true })
} }
loadPdbid (pdbid: string) { loadPdbid (pdbid: string) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment