Browse Source

guard against overly high surface resolution

Alexander Rose 5 years ago
parent
commit
ad9160a4a3

+ 11 - 0
src/mol-repr/structure/visual/util/common.ts

@@ -15,6 +15,7 @@ import { fillSerial } from '../../../../mol-util/array';
 import { ParamDefinition as PD } from '../../../../mol-util/param-definition';
 import { AssignableArrayLike } from '../../../../mol-util/type-helpers';
 import { getBoundary } from '../../../../mol-math/geometry/boundary';
+import { Box3D } from '../../../../mol-math/geometry';
 
 /** Return a Loci for the elements of a whole residue the elementIndex belongs to. */
 export function getResidueLoci(structure: Structure, unit: Unit.Atomic, elementIndex: ElementIndex): Loci {
@@ -99,6 +100,16 @@ export function includesUnitKind(unitKinds: UnitKind[], unit: Unit) {
 
 //
 
+const MaxCells = 500_000_000;
+
+/** guard against overly high resolution for the given box size */
+export function ensureReasonableResolution<T>(box: Box3D, props: { resolution: number } & T) {
+    const volume = Box3D.volume(box);
+    const approxCells = volume / props.resolution;
+    const resolution = approxCells > MaxCells ? volume / MaxCells : props.resolution;
+    return { ...props, resolution };
+}
+
 export function getConformation(unit: Unit) {
     switch (unit.kind) {
         case Unit.Kind.Atomic: return unit.model.atomicConformation;

+ 19 - 9
src/mol-repr/structure/visual/util/gaussian.ts

@@ -11,7 +11,7 @@ import { ParamDefinition as PD } from '../../../../mol-util/param-definition';
 import { GaussianDensityTexture, GaussianDensityTexture2d } from '../../../../mol-math/geometry/gaussian-density/gpu';
 import { Texture } from '../../../../mol-gl/webgl/texture';
 import { WebGLContext } from '../../../../mol-gl/webgl/context';
-import { getUnitConformationAndRadius, getStructureConformationAndRadius, CommonSurfaceParams } from './common';
+import { getUnitConformationAndRadius, getStructureConformationAndRadius, CommonSurfaceParams, ensureReasonableResolution } from './common';
 import { BaseGeometry } from '../../../../mol-geo/geometry/base';
 
 const SharedGaussianDensityParams = {
@@ -37,38 +37,48 @@ export type GaussianDensityTextureProps = typeof DefaultGaussianDensityTexturePr
 //
 
 export function computeUnitGaussianDensity(structure: Structure, unit: Unit, props: GaussianDensityProps, webgl?: WebGLContext) {
-    const { position, radius } = getUnitConformationAndRadius(structure, unit, props);
+    const { box } = unit.lookup3d.boundary;
+    const p = ensureReasonableResolution(box, props);
+    const { position, radius } = getUnitConformationAndRadius(structure, unit, p);
     return Task.create('Gaussian Density', async ctx => {
-        return await GaussianDensity(ctx, position, unit.lookup3d.boundary.box, radius, props, webgl);
+        return await GaussianDensity(ctx, position, box, radius, p, webgl);
     });
 }
 
 export function computeUnitGaussianDensityTexture(structure: Structure, unit: Unit, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) {
-    const { position, radius } = getUnitConformationAndRadius(structure, unit, props);
+    const { box } = unit.lookup3d.boundary;
+    const p = ensureReasonableResolution(box, props);
+    const { position, radius } = getUnitConformationAndRadius(structure, unit, p);
     return Task.create('Gaussian Density', async ctx => {
-        return GaussianDensityTexture(webgl, position, unit.lookup3d.boundary.box, radius, props, texture);
+        return GaussianDensityTexture(webgl, position, box, radius, p, texture);
     });
 }
 
 export function computeUnitGaussianDensityTexture2d(structure: Structure, unit: Unit, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) {
-    const { position, radius } = getUnitConformationAndRadius(structure, unit, props);
+    const { box } = unit.lookup3d.boundary;
+    const p = ensureReasonableResolution(box, props);
+    const { position, radius } = getUnitConformationAndRadius(structure, unit, p);
     return Task.create('Gaussian Density', async ctx => {
-        return GaussianDensityTexture2d(webgl, position, unit.lookup3d.boundary.box, radius, props, texture);
+        return GaussianDensityTexture2d(webgl, position, box, radius, p, texture);
     });
 }
 
 //
 
 export function computeStructureGaussianDensity(structure: Structure, props: GaussianDensityProps, webgl?: WebGLContext) {
+    const { box } = structure.lookup3d.boundary;
+    const p = ensureReasonableResolution(box, props);
     const { position, radius } = getStructureConformationAndRadius(structure, props.ignoreHydrogens, props.traceOnly);
     return Task.create('Gaussian Density', async ctx => {
-        return await GaussianDensity(ctx, position, structure.lookup3d.boundary.box, radius, props, webgl);
+        return await GaussianDensity(ctx, position, box, radius, p, webgl);
     });
 }
 
 export function computeStructureGaussianDensityTexture(structure: Structure, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) {
+    const { box } = structure.lookup3d.boundary;
+    const p = ensureReasonableResolution(box, props);
     const { position, radius } = getStructureConformationAndRadius(structure, props.ignoreHydrogens, props.traceOnly);
     return Task.create('Gaussian Density', async ctx => {
-        return GaussianDensityTexture(webgl, position, structure.lookup3d.boundary.box, radius, props, texture);
+        return GaussianDensityTexture(webgl, position, box, radius, p, texture);
     });
 }

+ 4 - 3
src/mol-repr/structure/visual/util/molecular-surface.ts

@@ -6,7 +6,7 @@
 
 import { Unit, Structure } from '../../../../mol-model/structure';
 import { Task, RuntimeContext } from '../../../../mol-task';
-import { getUnitConformationAndRadius, CommonSurfaceProps } from './common';
+import { getUnitConformationAndRadius, CommonSurfaceProps, ensureReasonableResolution } from './common';
 import { PositionData, DensityData, Box3D } from '../../../../mol-math/geometry';
 import { MolecularSurfaceCalculationProps, calcMolecularSurface } from '../../../../mol-math/geometry/molecular-surface';
 import { OrderedSet } from '../../../../mol-data/int';
@@ -34,9 +34,10 @@ function getPositionDataAndMaxRadius(structure: Structure, unit: Unit, props: Mo
 
 export function computeUnitMolecularSurface(structure: Structure, unit: Unit, props: MolecularSurfaceProps) {
     const { box } = unit.lookup3d.boundary;
-    const { position, boundary, maxRadius } = getPositionDataAndMaxRadius(structure, unit, props);
+    const p = ensureReasonableResolution(box, props);
+    const { position, boundary, maxRadius } = getPositionDataAndMaxRadius(structure, unit, p);
     return Task.create('Molecular Surface', async ctx => {
-        return await MolecularSurface(ctx, position, boundary, maxRadius, box, props);
+        return await MolecularSurface(ctx, position, boundary, maxRadius, box, p);
     });
 }