From 2e013fafc835da774134d11879f82c04261fc85d Mon Sep 17 00:00:00 2001
From: dsehnal <david.sehnal@gmail.com>
Date: Thu, 5 Jan 2023 13:07:21 +0100
Subject: [PATCH] Add StructureElement.Loci.forEachLocation

---
 CHANGELOG.md                                  |  1 +
 .../structure/structure/element/loci.ts       | 20 +++++++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 992f4a754..810d7bfd8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ Note that since we don't clearly distinguish between a public and private interf
     - Update clip `defines` only when changed
     - Check for identity in structure/unit areEqual methods
     - Avoid cloning of structure representation parameters
+- Add StructureElement.Loci.forEachLocation
 
 ## [v3.28.0] - 2022-12-20
 
diff --git a/src/mol-model/structure/structure/element/loci.ts b/src/mol-model/structure/structure/element/loci.ts
index e920a0929..60c7a9436 100644
--- a/src/mol-model/structure/structure/element/loci.ts
+++ b/src/mol-model/structure/structure/element/loci.ts
@@ -143,6 +143,26 @@ export namespace Loci {
         return Structure.create(units, { parent: loci.structure.parent });
     }
 
+    /**
+     * Iterates over all locations.
+     * 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) {
+        if (Loci.isEmpty(loci)) return;
+
+        const location = Location.create(loci.structure);
+        for (const e of loci.elements) {
+            const { unit, indices } = e;
+            location.unit = unit;
+            const { elements } = e.unit;
+            for (let i = 0, _i = OrderedSet.size(indices); i < _i; i++) {
+                location.element = elements[OrderedSet.getAt(indices, i)];
+                f(location);
+            }
+        }
+    }
+
     // TODO: there should be a version that properly supports partitioned units
     export function remap(loci: Loci, structure: Structure): Loci {
         if (structure === loci.structure) return loci;
-- 
GitLab