Skip to content
Snippets Groups Projects
Commit 51395c1a authored by David Sehnal's avatar David Sehnal
Browse files

mol-model Structure distance checking

parent 51ef3f36
No related branches found
No related tags found
No related merge requests found
......@@ -4,8 +4,9 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { Structure, StructureElement } from '../structure';
import { Structure, StructureElement, Unit } from '../structure';
import { now } from 'mol-task';
import { ElementIndex } from '../model';
export interface QueryContextView {
readonly element: StructureElement;
......@@ -26,6 +27,11 @@ export class QueryContext implements QueryContextView {
readonly element: StructureElement = StructureElement.create();
currentStructure: Structure = void 0 as any;
setElement(unit: Unit, e: ElementIndex) {
this.element.unit = unit;
this.element.element = e;
}
pushCurrentElement(): StructureElement {
this.currentElementStack[this.currentElementStack.length] = this.element;
(this.element as StructureElement) = StructureElement.create();
......
......@@ -107,7 +107,7 @@ export interface WithinParams {
target: StructureQuery,
minRadius?: number,
maxRadius: number,
atomRadius?: QueryFn<number>,
elementRadius?: QueryFn<number>,
invert?: boolean
}
......@@ -120,12 +120,12 @@ export function within(params: WithinParams): StructureQuery {
selection: params.query(queryCtx),
target: params.target(queryCtx),
maxRadius: params.maxRadius,
minRadius: params.minRadius ? params.minRadius : 0,
atomRadius: params.atomRadius || _zeroRadius,
minRadius: params.minRadius ? Math.max(0, params.minRadius) : 0,
elementRadius: params.elementRadius!,
invert: !!params.invert,
}
if (ctx.minRadius === 0 && ctx.atomRadius === _zeroRadius) {
if (ctx.minRadius === 0 && typeof params.minRadius === 'undefined') {
return withinMaxRadius(ctx);
} else {
// TODO
......@@ -142,7 +142,7 @@ interface WithinContext {
minRadius: number,
maxRadius: number,
invert: boolean,
atomRadius: QueryFn<number>
elementRadius: QueryFn<number>
}
function withinMaxRadius({ queryCtx, selection, target, maxRadius, invert }: WithinContext) {
const targetLookup = StructureSelection.unionStructure(target).lookup3d;
......@@ -151,34 +151,18 @@ function withinMaxRadius({ queryCtx, selection, target, maxRadius, invert }: Wit
const pos = Vec3.zero();
StructureSelection.forEach(selection, (s, sI) => {
const { units } = s;
let withinRadius = false;
for (let i = 0, _i = units.length; i < _i; i++) {
const unit = units[i];
const { elements, conformation } = unit;
switch (unit.kind) {
case Unit.Kind.Atomic:
// TODO: assign radius to gaussian elements?
case Unit.Kind.Gaussians:
for (let i = 0, _i = elements.length; i < _i; i++) {
conformation.position(elements[i], pos);
if (targetLookup.check(pos[0], pos[1], pos[2], maxRadius)) {
withinRadius = true;
break;
}
}
break;
case Unit.Kind.Spheres:
const radius = unit.coarseConformation.radius;
for (let i = 0, _i = elements.length; i < _i; i++) {
conformation.position(elements[i], pos);
if (targetLookup.check(pos[0], pos[1], pos[2], maxRadius + radius[elements[i]])) {
withinRadius = true;
break;
}
}
const { elements, conformation: { position, r } } = unit;
for (let i = 0, _i = elements.length; i < _i; i++) {
const e = elements[i];
position(e, pos);
if (targetLookup.check(pos[0], pos[1], pos[2], maxRadius + r(e))) {
withinRadius = true;
break;
}
}
if (withinRadius) break;
}
......
/**
* Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { Structure, Unit } from '../../structure'
import { Vec3 } from 'mol-math/linear-algebra';
import { QueryFn, QueryContext } from '../context';
export function checkStructureMinMaxDistance(ctx: QueryContext, a: Structure, b: Structure, minDist: number, maxDist: number, elementRadius: QueryFn<number>) {
if (a.elementCount === 0 || b.elementCount === 0) return true;
if (a.elementCount <= b.elementCount) return MinMaxDist.check(ctx, a, b, minDist, maxDist, elementRadius);
return MinMaxDist.check(ctx, b, a, minDist, maxDist, elementRadius);
}
export function checkStructureMaxRadiusDistance(ctx: QueryContext, a: Structure, b: Structure, maxDist: number, elementRadius: QueryFn<number>) {
if (a.elementCount === 0 || b.elementCount === 0) return true;
if (a.elementCount <= b.elementCount) return MaxRadiusDist.check(ctx, a, b, maxDist, elementRadius);
return MaxRadiusDist.check(ctx, b, a, maxDist, elementRadius);
}
namespace MinMaxDist {
const enum Result {
BelowMin,
WithinMax,
Miss
}
const distVec = Vec3.zero();
function inUnit(ctx: QueryContext, unit: Unit, p: Vec3, eRadius: number, minDist: number, maxDist: number, elementRadius: QueryFn<number>) {
const { elements, conformation: { position } } = unit, dV = distVec;
ctx.element.unit = unit;
let withinRange = false;
for (let i = 0, _i = elements.length; i < _i; i++) {
const e = elements[i];
ctx.element.element = e;
const d = Math.max(0, Vec3.distance(p, position(e, dV)) - eRadius - elementRadius(ctx));
if (d < minDist) return Result.BelowMin;
if (d < maxDist) withinRange = true;
}
return withinRange ? Result.WithinMax : Result.Miss;
}
export function toPoint(ctx: QueryContext, s: Structure, point: Vec3, radius: number, minDist: number, maxDist: number, elementRadius: QueryFn<number>) {
const { units } = s;
let withinRange = false;
for (let i = 0, _i = units.length; i < _i; i++) {
const iu = inUnit(ctx, units[i], point, radius, minDist, maxDist, elementRadius);
if (iu === Result.BelowMin) return Result.BelowMin;
if (iu === Result.WithinMax) withinRange = true;
}
return withinRange ? Result.WithinMax : Result.Miss;
}
const distPivot = Vec3.zero();
export function check(ctx: QueryContext, a: Structure, b: Structure, minDist: number, maxDist: number, elementRadius: QueryFn<number>) {
if (a.elementCount === 0 || b.elementCount === 0) return 0;
const { units } = a;
let withinRange = false;
for (let i = 0, _i = units.length; i < _i; i++) {
const unit = units[i];
const { elements, conformation: { position } } = unit;
for (let i = 0, _i = elements.length; i < _i; i++) {
const e = elements[i];
ctx.setElement(unit, e);
const tp = toPoint(ctx, b, position(e, distPivot), elementRadius(ctx), minDist, maxDist, elementRadius);
if (tp === Result.BelowMin) return Result.BelowMin;
if (tp === Result.WithinMax) withinRange = true;
}
}
return withinRange;
}
}
namespace MaxRadiusDist {
const distVec = Vec3.zero();
function inUnit(ctx: QueryContext, unit: Unit, p: Vec3, eRadius: number, maxDist: number, elementRadius: QueryFn<number>) {
const { elements, conformation: { position } } = unit, dV = distVec;
ctx.element.unit = unit;
for (let i = 0, _i = elements.length; i < _i; i++) {
const e = elements[i];
ctx.element.element = e;
if (Math.max(0, Vec3.distance(p, position(e, dV)) - eRadius - elementRadius(ctx)) <= maxDist) return true;
}
return false;
}
export function toPoint(ctx: QueryContext, s: Structure, point: Vec3, radius: number, maxDist: number, elementRadius: QueryFn<number>) {
const { units } = s;
for (let i = 0, _i = units.length; i < _i; i++) {
if (inUnit(ctx, units[i], point, radius, maxDist, elementRadius)) return true;
}
return false;
}
const distPivot = Vec3.zero();
export function check(ctx: QueryContext, a: Structure, b: Structure, maxDist: number, elementRadius: QueryFn<number>) {
if (a.elementCount === 0 || b.elementCount === 0) return 0;
const { units } = a;
for (let i = 0, _i = units.length; i < _i; i++) {
const unit = units[i];
const { elements, conformation: { position } } = unit;
for (let i = 0, _i = elements.length; i < _i; i++) {
const e = elements[i];
ctx.setElement(unit, e);
if (toPoint(ctx, b, position(e, distPivot), elementRadius(ctx), maxDist, elementRadius)) return true;
}
}
return false;
}
}
\ 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