diff --git a/src/mol-model/structure/query/queries/filters.ts b/src/mol-model/structure/query/queries/filters.ts index 699a774509424b044aa0b3aa18350e8feff172db..a84879bbf472bcc40ecc0f61ea1b52e5afe6f3c6 100644 --- a/src/mol-model/structure/query/queries/filters.ts +++ b/src/mol-model/structure/query/queries/filters.ts @@ -11,6 +11,7 @@ import { StructureQuery } from '../query'; import { StructureSelection } from '../selection'; import { structureAreIntersecting } from '../utils/structure'; import { Vec3 } from 'mol-math/linear-algebra'; +import { checkStructureMaxRadiusDistance, checkStructureMinMaxDistance } from '../utils/structure-distance'; export function pick(query: StructureQuery, pred: QueryPredicate): StructureQuery { return ctx => { @@ -111,8 +112,6 @@ export interface WithinParams { invert?: boolean } -function _zeroRadius(ctx: QueryContext) { return 0; } - export function within(params: WithinParams): StructureQuery { return queryCtx => { const ctx: WithinContext = { @@ -126,11 +125,11 @@ export function within(params: WithinParams): StructureQuery { } if (ctx.minRadius === 0 && typeof params.minRadius === 'undefined') { + return withinMaxRadiusLookup(ctx); + } else if (ctx.minRadius === 0) { return withinMaxRadius(ctx); } else { - // TODO - throw 'not implemented'; - // return withinMinMaxRadius(ctx); + return withinMinMaxRadius(ctx); } } } @@ -144,7 +143,7 @@ interface WithinContext { invert: boolean, elementRadius: QueryFn<number> } -function withinMaxRadius({ queryCtx, selection, target, maxRadius, invert }: WithinContext) { +function withinMaxRadiusLookup({ queryCtx, selection, target, maxRadius, invert }: WithinContext) { const targetLookup = StructureSelection.unionStructure(target).lookup3d; const ret = StructureSelection.LinearBuilder(queryCtx.inputStructure); @@ -174,5 +173,33 @@ function withinMaxRadius({ queryCtx, selection, target, maxRadius, invert }: Wit return ret.getSelection(); } +function withinMaxRadius({ queryCtx, selection, target, maxRadius, invert, elementRadius }: WithinContext) { + const targetStructure = StructureSelection.unionStructure(target); + const ret = StructureSelection.LinearBuilder(queryCtx.inputStructure); + + StructureSelection.forEach(selection, (s, sI) => { + let withinRadius = checkStructureMaxRadiusDistance(queryCtx, targetStructure, s, maxRadius, elementRadius); + if (invert) withinRadius = !withinRadius; + if (withinRadius) ret.add(s); + if (sI % 10 === 0) queryCtx.throwIfTimedOut(); + }); + + return ret.getSelection(); +} + +function withinMinMaxRadius({ queryCtx, selection, target, minRadius, maxRadius, invert, elementRadius }: WithinContext) { + const targetStructure = StructureSelection.unionStructure(target); + const ret = StructureSelection.LinearBuilder(queryCtx.inputStructure); + + StructureSelection.forEach(selection, (s, sI) => { + let withinRadius = checkStructureMinMaxDistance(queryCtx, targetStructure, s, minRadius, maxRadius, elementRadius); + if (invert) withinRadius = !withinRadius; + if (withinRadius) ret.add(s); + if (sI % 10 === 0) queryCtx.throwIfTimedOut(); + }); + + return ret.getSelection(); +} + // TODO: isConnectedTo \ No newline at end of file