Sfoglia il codice sorgente

add eachLocation to representation/visual interface

Alexander Rose 2 anni fa
parent
commit
e246f4e5ca

+ 1 - 0
CHANGELOG.md

@@ -13,6 +13,7 @@ Note that since we don't clearly distinguish between a public and private interf
 - Fix rendering issues caused by VAO reuse
 - Add "Zoom All", "Orient Axes", "Reset Axes" buttons to the "Reset Camera" button
 - Improve trackball move-state handling when key bindings use modifiers
+- Add `eachLocation` to representation/visual interface
 
 ## [v3.33.0] - 2023-04-02
 

+ 5 - 1
src/mol-model/structure/structure/element/location.ts

@@ -55,13 +55,17 @@ namespace Location {
         return a.unit === b.unit && a.element === b.element;
     }
 
-    const pA = Vec3.zero(), pB = Vec3.zero();
+    const pA = Vec3(), pB = Vec3();
     export function distance(a: Location, b: Location) {
         a.unit.conformation.position(a.element, pA);
         b.unit.conformation.position(b.element, pB);
         return Vec3.distance(pA, pB);
     }
 
+    export function position(out: Vec3, l: Location): Vec3 {
+        return l.unit.conformation.position(l.element, out);
+    }
+
     export function residueIndex(l: Location) {
         return l.unit.model.atomicHierarchy.residueAtomSegments.index[l.element];
     }

+ 1 - 1
src/mol-model/structure/structure/element/loci.ts

@@ -148,7 +148,7 @@ export namespace Loci {
      * The loc argument of the callback is mutable, use Location.clone() if you intend to keep
      * the value around.
      */
-    export function forEachLocation(loci: Loci, f: (loc: Location) => any) {
+    export function forEachLocation(loci: Loci, f: (loc: Location) => void) {
         if (Loci.isEmpty(loci)) return;
 
         const location = Location.create(loci.structure);

+ 14 - 1
src/mol-repr/representation.ts

@@ -18,7 +18,7 @@ import { Loci as ModelLoci, EmptyLoci, isEmptyLoci } from '../mol-model/loci';
 import { Overpaint } from '../mol-theme/overpaint';
 import { Transparency } from '../mol-theme/transparency';
 import { Mat4 } from '../mol-math/linear-algebra';
-import { getQualityProps } from './util';
+import { LocationCallback, getQualityProps } from './util';
 import { BaseGeometry } from '../mol-geo/geometry/base';
 import { Visual } from './visual';
 import { CustomProperty } from '../mol-model-props/common/custom-property';
@@ -162,6 +162,7 @@ interface Representation<D, P extends PD.Params = PD.Params, S extends Represent
     setTheme: (theme: Theme) => void
     getLoci: (pickingId: PickingId) => ModelLoci
     getAllLoci: () => ModelLoci[]
+    eachLocation: (cb: LocationCallback) => void
     mark: (loci: ModelLoci, action: MarkerAction) => boolean
     destroy: () => void
 }
@@ -250,6 +251,7 @@ namespace Representation {
         setTheme: () => {},
         getLoci: () => EmptyLoci,
         getAllLoci: () => [],
+        eachLocation: () => {},
         mark: () => false,
         destroy: () => {}
     };
@@ -370,6 +372,14 @@ namespace Representation {
                 }
                 return loci;
             },
+            eachLocation: (cb: LocationCallback) => {
+                const { visuals } = currentProps;
+                for (let i = 0, il = reprList.length; i < il; ++i) {
+                    if (!visuals || visuals.includes(reprMap[i])) {
+                        reprList[i].eachLocation(cb);
+                    }
+                }
+            },
             mark: (loci: ModelLoci, action: MarkerAction) => {
                 let marked = false;
                 for (let i = 0, il = reprList.length; i < il; ++i) {
@@ -436,6 +446,9 @@ namespace Representation {
                 // TODO
                 return [];
             },
+            eachLocation: () => {
+                // TODO
+            },
             mark: (loci: ModelLoci, action: MarkerAction) => {
                 // TODO
                 return false;

+ 9 - 2
src/mol-repr/shape/representation.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -11,7 +11,7 @@ import { Subject } from 'rxjs';
 import { getNextMaterialId, createRenderObject, GraphicsRenderObject } from '../../mol-gl/render-object';
 import { Theme } from '../../mol-theme/theme';
 import { LocationIterator } from '../../mol-geo/util/location-iterator';
-import { VisualUpdateState } from '../util';
+import { LocationCallback, VisualUpdateState } from '../util';
 import { createMarkers } from '../../mol-geo/geometry/marker-data';
 import { MarkerAction, MarkerActions } from '../../mol-util/marker-action';
 import { ValueCell } from '../../mol-util';
@@ -223,6 +223,13 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa
         getAllLoci() {
             return [Shape.Loci(_shape)];
         },
+        eachLocation: (cb: LocationCallback) => {
+            locationIt.reset();
+            while (locationIt.hasNext) {
+                const { location, isSecondary } = locationIt.move();
+                cb(location, isSecondary);
+            }
+        },
         mark(loci: Loci, action: MarkerAction) {
             if (!MarkerActions.is(_state.markerActions, action)) return false;
             if (ShapeGroup.isLoci(loci) || Shape.isLoci(loci)) {

+ 7 - 1
src/mol-repr/structure/complex-representation.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  * @author David Sehnal <david.sehnal@gmail.com>
@@ -22,6 +22,7 @@ import { Clipping } from '../../mol-theme/clipping';
 import { Transparency } from '../../mol-theme/transparency';
 import { WebGLContext } from '../../mol-gl/webgl/context';
 import { Substance } from '../../mol-theme/substance';
+import { LocationCallback } from '../util';
 
 export function ComplexRepresentation<P extends StructureParams>(label: string, ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, P>, visualCtor: (materialId: number, structure: Structure, props: PD.Values<P>, webgl?: WebGLContext) => ComplexVisual<P>): StructureRepresentation<P> {
     let version = 0;
@@ -80,6 +81,10 @@ export function ComplexRepresentation<P extends StructureParams>(label: string,
         return [Structure.Loci(_structure.target)];
     }
 
+    function eachLocation(cb: LocationCallback) {
+        visual?.eachLocation(cb);
+    }
+
     function mark(loci: Loci, action: MarkerAction) {
         if (!_structure) return false;
         if (!MarkerActions.is(_state.markerActions, action)) return false;
@@ -162,6 +167,7 @@ export function ComplexRepresentation<P extends StructureParams>(label: string,
         setTheme,
         getLoci,
         getAllLoci,
+        eachLocation,
         mark,
         destroy
     };

+ 9 - 2
src/mol-repr/structure/complex-visual.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -15,7 +15,7 @@ import { createRenderObject, GraphicsRenderObject, RenderObjectValues } from '..
 import { PickingId } from '../../mol-geo/geometry/picking';
 import { Loci, isEveryLoci, EmptyLoci } from '../../mol-model/loci';
 import { Interval } from '../../mol-data/int';
-import { VisualUpdateState } from '../util';
+import { LocationCallback, VisualUpdateState } from '../util';
 import { ColorTheme } from '../../mol-theme/color';
 import { ValueCell, deepEqual } from '../../mol-util';
 import { createSizes, SizeData } from '../../mol-geo/geometry/size-data';
@@ -266,6 +266,13 @@ export function ComplexVisual<G extends Geometry, P extends StructureParams & Ge
         getLoci(pickingId: PickingId) {
             return renderObject ? getLoci(pickingId, currentStructure, renderObject.id) : EmptyLoci;
         },
+        eachLocation(cb: LocationCallback) {
+            locationIt.reset();
+            while (locationIt.hasNext) {
+                const { location, isSecondary } = locationIt.move();
+                cb(location, isSecondary);
+            }
+        },
         mark(loci: Loci, action: MarkerAction) {
             return Visual.mark(renderObject, loci, action, lociApply, previousMark);
         },

+ 8 - 0
src/mol-repr/structure/units-representation.ts

@@ -26,6 +26,7 @@ import { Clipping } from '../../mol-theme/clipping';
 import { WebGLContext } from '../../mol-gl/webgl/context';
 import { StructureGroup } from './visual/util/common';
 import { Substance } from '../../mol-theme/substance';
+import { LocationCallback } from '../util';
 
 export interface UnitsVisual<P extends StructureParams> extends Visual<StructureGroup, P> { }
 
@@ -194,6 +195,12 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct
         return loci;
     }
 
+    function eachLocation(cb: LocationCallback) {
+        visuals.forEach(({ visual }) => {
+            visual.eachLocation(cb);
+        });
+    }
+
     function getAllLoci() {
         return [Structure.Loci(_structure.target)];
     }
@@ -312,6 +319,7 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct
         setTheme,
         getLoci,
         getAllLoci,
+        eachLocation,
         mark,
         destroy
     };

+ 9 - 2
src/mol-repr/structure/units-visual.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -16,7 +16,7 @@ import { createRenderObject, GraphicsRenderObject, RenderObjectValues } from '..
 import { PickingId } from '../../mol-geo/geometry/picking';
 import { Loci, isEveryLoci, EmptyLoci } from '../../mol-model/loci';
 import { Interval } from '../../mol-data/int';
-import { VisualUpdateState } from '../util';
+import { LocationCallback, VisualUpdateState } from '../util';
 import { ColorTheme } from '../../mol-theme/color';
 import { createMarkers } from '../../mol-geo/geometry/marker-data';
 import { MarkerAction } from '../../mol-util/marker-action';
@@ -337,6 +337,13 @@ export function UnitsVisual<G extends Geometry, P extends StructureParams & Geom
         getLoci(pickingId: PickingId) {
             return renderObject ? getLoci(pickingId, currentStructureGroup, renderObject.id) : EmptyLoci;
         },
+        eachLocation(cb: LocationCallback) {
+            locationIt.reset();
+            while (locationIt.hasNext) {
+                const { location, isSecondary } = locationIt.move();
+                cb(location, isSecondary);
+            }
+        },
         mark(loci: Loci, action: MarkerAction) {
             let hasInvariantId = true;
             if (StructureElement.Loci.is(loci)) {

+ 4 - 1
src/mol-repr/util.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -10,6 +10,7 @@ import { VisualQuality } from '../mol-geo/geometry/base';
 import { Box3D, SpacegroupCell } from '../mol-math/geometry';
 import { ModelSymmetry } from '../mol-model-formats/structure/property/symmetry';
 import { Volume } from '../mol-model/volume';
+import { Location } from '../mol-model/location';
 
 export interface VisualUpdateState {
     updateTransform: boolean
@@ -45,6 +46,8 @@ export namespace VisualUpdateState {
     }
 }
 
+export type LocationCallback = (loc: Location, isSecondary: boolean) => void
+
 //
 
 export interface QualityProps {

+ 3 - 1
src/mol-repr/visual.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -31,6 +31,7 @@ import { applyMeshOverpaintSmoothing, applyMeshSubstanceSmoothing, applyMeshTran
 import { applyTextureMeshOverpaintSmoothing, applyTextureMeshSubstanceSmoothing, applyTextureMeshTransparencySmoothing } from '../mol-geo/geometry/texture-mesh/color-smoothing';
 import { Substance } from '../mol-theme/substance';
 import { applySubstanceMaterial, clearSubstance, createSubstance } from '../mol-geo/geometry/substance-data';
+import { LocationCallback } from './util';
 
 export interface VisualContext {
     readonly runtime: RuntimeContext
@@ -45,6 +46,7 @@ interface Visual<D, P extends PD.Params> {
     readonly geometryVersion: number
     createOrUpdate: (ctx: VisualContext, theme: Theme, props: PD.Values<P>, data?: D) => Promise<void> | void
     getLoci: (pickingId: PickingId) => Loci
+    eachLocation: (cb: LocationCallback) => void
     mark: (loci: Loci, action: MarkerAction) => boolean
     setVisibility: (visible: boolean) => void
     setAlphaFactor: (alphaFactor: number) => void

+ 14 - 2
src/mol-repr/volume/representation.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -15,7 +15,7 @@ import { createRenderObject, getNextMaterialId, GraphicsRenderObject } from '../
 import { PickingId } from '../../mol-geo/geometry/picking';
 import { Loci, isEveryLoci, EmptyLoci, isEmptyLoci } from '../../mol-model/loci';
 import { Interval, SortedArray } from '../../mol-data/int';
-import { getQualityProps, VisualUpdateState } from '../util';
+import { getQualityProps, LocationCallback, VisualUpdateState } from '../util';
 import { ColorTheme } from '../../mol-theme/color';
 import { ValueCell } from '../../mol-util';
 import { createSizes } from '../../mol-geo/geometry/size-data';
@@ -233,6 +233,13 @@ export function VolumeVisual<G extends Geometry, P extends VolumeParams & Geomet
         getLoci(pickingId: PickingId) {
             return renderObject ? getLoci(pickingId, currentVolume, currentKey, currentProps, renderObject.id) : EmptyLoci;
         },
+        eachLocation(cb: LocationCallback) {
+            locationIt.reset();
+            while (locationIt.hasNext) {
+                const { location, isSecondary } = locationIt.move();
+                cb(location, isSecondary);
+            }
+        },
         mark(loci: Loci, action: MarkerAction) {
             return Visual.mark(renderObject, loci, action, lociApply);
         },
@@ -436,6 +443,11 @@ export function VolumeRepresentation<P extends VolumeParams>(label: string, ctx:
         getAllLoci: (): Loci[] => {
             return [getLoci(_volume, _props)];
         },
+        eachLocation: (cb: LocationCallback) => {
+            visuals.forEach(visual => {
+                visual.eachLocation(cb);
+            });
+        },
         mark,
         destroy
     };