From 0ed4d82a5b616f3cb1815945e69f248cd7182202 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Thu, 23 Aug 2018 17:41:30 +0200
Subject: [PATCH] mol-model/query added link support to QueryContext

---
 src/mol-model/structure/model/types.ts        |  4 +++
 src/mol-model/structure/query/context.ts      | 19 +++++++++++
 .../structure/structure/unit/links.ts         | 34 +++++++++++++++++--
 .../structure/structure/unit/links/data.ts    |  9 +++--
 4 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/src/mol-model/structure/model/types.ts b/src/mol-model/structure/model/types.ts
index 159f2fe0b..58a8989b5 100644
--- a/src/mol-model/structure/model/types.ts
+++ b/src/mol-model/structure/model/types.ts
@@ -491,6 +491,10 @@ export namespace LinkType {
         // currently at most 16 flags are supported!!
     }
 
+    export function create(flags: Flag): LinkType {
+        return BitFlags.create(flags);
+    }
+
     export function isCovalent(flags: LinkType.Flag) {
         return (flags & LinkType.Flag.Covalent) !== 0;
     }
diff --git a/src/mol-model/structure/query/context.ts b/src/mol-model/structure/query/context.ts
index 245cd5b37..7404cb05f 100644
--- a/src/mol-model/structure/query/context.ts
+++ b/src/mol-model/structure/query/context.ts
@@ -7,6 +7,7 @@
 import { Structure, StructureElement, Unit } from '../structure';
 import { now } from 'mol-task';
 import { ElementIndex } from '../model';
+import { Link } from '../structure/unit/links';
 
 export interface QueryContextView {
     readonly element: StructureElement;
@@ -15,6 +16,7 @@ export interface QueryContextView {
 
 export class QueryContext implements QueryContextView {
     private currentElementStack: StructureElement[] = [];
+    private currentAtomicLinkStack: Link.Location<Unit.Atomic>[] = [];
     private currentStructureStack: Structure[] = [];
     private inputStructureStack: Structure[] = [];
 
@@ -27,6 +29,9 @@ export class QueryContext implements QueryContextView {
     readonly element: StructureElement = StructureElement.create();
     currentStructure: Structure = void 0 as any;
 
+    /** Current link between atoms */
+    readonly atomicLink: Link.Location<Unit.Atomic> = void 0 as any;
+
     setElement(unit: Unit, e: ElementIndex) {
         this.element.unit = unit;
         this.element.element = e;
@@ -42,6 +47,20 @@ export class QueryContext implements QueryContextView {
         (this.element as StructureElement) = this.currentElementStack.pop()!;
     }
 
+    pushCurrentLink() {
+        if (this.atomicLink) this.currentAtomicLinkStack.push(this.atomicLink);
+        (this.atomicLink as Link.Location<Unit.Atomic>) = Link.Location() as Link.Location<Unit.Atomic>;
+        return this.atomicLink;
+    }
+
+    popCurrentLink() {
+        if (this.currentAtomicLinkStack.length > 0) {
+            (this.atomicLink as Link.Location<Unit.Atomic>) = this.currentAtomicLinkStack.pop()!;
+        } else {
+            (this.atomicLink as any) = void 0;
+        }
+    }
+
     pushCurrentStructure() {
         if (this.currentStructure) this.currentStructureStack.push(this.currentStructure);
     }
diff --git a/src/mol-model/structure/structure/unit/links.ts b/src/mol-model/structure/structure/unit/links.ts
index c7ff8e0a7..5534b62f0 100644
--- a/src/mol-model/structure/structure/unit/links.ts
+++ b/src/mol-model/structure/structure/unit/links.ts
@@ -6,18 +6,20 @@
  */
 
 import { Unit, StructureElement } from '../../structure'
+import Structure from '../structure';
+import { LinkType } from '../../model/types';
 
 export * from './links/data'
 export * from './links/intra-compute'
 export * from './links/inter-compute'
 
 namespace Link {
-    export interface Location {
+    export interface Location<U extends Unit = Unit> {
         readonly kind: 'link-location',
-        aUnit: Unit,
+        aUnit: U,
         /** Index into aUnit.elements */
         aIndex: StructureElement.UnitIndex,
-        bUnit: Unit,
+        bUnit: U,
         /** Index into bUnit.elements */
         bIndex: StructureElement.UnitIndex,
     }
@@ -42,6 +44,32 @@ namespace Link {
     export function isLoci(x: any): x is Loci {
         return !!x && x.kind === 'link-loci';
     }
+
+    export function getType(structure: Structure, link: Location<Unit.Atomic>): LinkType {
+        if (link.aUnit === link.bUnit) {
+            const links = link.aUnit.links;
+            const idx = links.getEdgeIndex(link.aIndex, link.bIndex);
+            if (idx < 0) return LinkType.create(LinkType.Flag.None);
+            return LinkType.create(links.edgeProps.flags[idx]);
+        } else {
+            const bond = structure.links.getBondFromLocation(link);
+            if (bond) return LinkType.create(bond.flag);
+            return LinkType.create(LinkType.Flag.None);
+        }
+    }
+
+    export function getOrder(structure: Structure, link: Location<Unit.Atomic>): number {
+        if (link.aUnit === link.bUnit) {
+            const links = link.aUnit.links;
+            const idx = links.getEdgeIndex(link.aIndex, link.bIndex);
+            if (idx < 0) return 0;
+            return links.edgeProps.order[idx];
+        } else {
+            const bond = structure.links.getBondFromLocation(link);
+            if (bond) return bond.order;
+            return 0;
+        }
+    }
 }
 
 export { Link }
\ No newline at end of file
diff --git a/src/mol-model/structure/structure/unit/links/data.ts b/src/mol-model/structure/structure/unit/links/data.ts
index 74ff5bd2d..e2c56ae49 100644
--- a/src/mol-model/structure/structure/unit/links/data.ts
+++ b/src/mol-model/structure/structure/unit/links/data.ts
@@ -9,6 +9,7 @@ import { LinkType } from '../../../model/types'
 import { IntAdjacencyGraph } from 'mol-math/graph';
 import Unit from '../../unit';
 import StructureElement from '../../element';
+import { Link } from '../links';
 
 type IntraUnitLinks = IntAdjacencyGraph<{ readonly order: ArrayLike<number>, readonly flags: ArrayLike<LinkType.Flag> }>
 
@@ -27,17 +28,21 @@ class InterUnitBonds {
     }
 
     /** Index into this.bonds */
-    getBondIndex(indexA: number, unitA: Unit, indexB: number, unitB: Unit): number {
+    getBondIndex(indexA: StructureElement.UnitIndex, unitA: Unit, indexB: StructureElement.UnitIndex, unitB: Unit): number {
         const key = InterUnitBonds.getBondKey(indexA, unitA, indexB, unitB)
         const index = this.bondKeyIndex.get(key)
         return index !== undefined ? index : -1
     }
 
-    getBond(indexA: number, unitA: Unit, indexB: number, unitB: Unit): InterUnitBonds.Bond | undefined {
+    getBond(indexA: StructureElement.UnitIndex, unitA: Unit, indexB: StructureElement.UnitIndex, unitB: Unit): InterUnitBonds.Bond | undefined {
         const index = this.getBondIndex(indexA, unitA, indexB, unitB)
         return index !== -1 ? this.bonds[index] : undefined
     }
 
+    getBondFromLocation(l: Link.Location) {
+        return this.getBond(l.aIndex, l.aUnit, l.bIndex, l.bUnit);
+    }
+
     constructor(private map: Map<number, InterUnitBonds.UnitPairBonds[]>) {
         let count = 0
         const bonds: (InterUnitBonds.Bond)[] = []
-- 
GitLab