Переглянути джерело

assembly-symmetry: dihedral cage fixes

Alexander Rose 5 роки тому
батько
коміт
86aae08257
1 змінених файлів з 27 додано та 6 видалено
  1. 27 6
      src/extensions/rcsb/assembly-symmetry/representation.ts

+ 27 - 6
src/extensions/rcsb/assembly-symmetry/representation.ts

@@ -186,12 +186,22 @@ const getSymbolCage = memoize1((symbol: string): Cage | undefined => {
     if (symbol.startsWith('D') || symbol.startsWith('C')) {
         // z axis is prism axis, x/y axes cut through edge midpoints
         const fold = parseInt(symbol.substr(1));
+        let cage: Cage;
         if (fold === 2) {
-            return PrismCage(polygon(4, false));
+            cage = PrismCage(polygon(4, false));
         } else if (fold === 3) {
-            return WedgeCage();
+            cage = WedgeCage();
         } else if (fold > 3) {
-            return PrismCage(polygon(fold, false));
+            cage = PrismCage(polygon(fold, false));
+        } else {
+            return;
+        }
+        if (fold % 2 === 0) {
+            return cage;
+        } else {
+            const m = Mat4.identity();
+            Mat4.rotate(m, m, 1 / fold * Math.PI / 2, Vec3.unitZ);
+            return transformCage(cloneCage(cage), m);
         }
     } else if (symbol === 'O') {
         // x/y/z axes cut through order 4 vertices
@@ -237,7 +247,7 @@ function setSymbolTransform(t: Mat4, symbol: string, axes: AssemblySymmetry.Rota
             pair = axes.filter(a => a.order === 2);
         } else if (fold >= 3) {
             const aN = axes.filter(a => a.order === fold)[0];
-            const a2 = axes.filter(a => a.order === 2)[0];
+            const a2 = axes.filter(a => a.order === 2)[1];
             pair = [aN, a2];
         }
     } else if (symbol === 'O') {
@@ -267,7 +277,19 @@ function setSymbolTransform(t: Mat4, symbol: string, axes: AssemblySymmetry.Rota
             Vec3.sub(dir, eye, target);
             if (Vec3.dot(dir, up) < 0) Vec3.negate(up, up);
             Mat4.targetTo(t, eye, target, up);
-            Mat4.scaleUniformly(t, t, size * getSymbolScale(symbol));
+
+            if (symbol.startsWith('D')) {
+                const { sphere } = structure.lookup3d.boundary;
+                let sizeXY = (sphere.radius * 2) * 0.8; // fallback for missing extrema
+                if (Sphere3D.hasExtrema(sphere)) {
+                    const n = Mat3.directionTransform(Mat3(), t);
+                    const dirs = unitCircleDirections.map(d => Vec3.transformMat3(Vec3(), d, n));
+                    sizeXY = getMaxProjectedDistance(sphere.extrema, dirs, sphere.center) * 1.6;
+                }
+                Mat4.scale(t, t, Vec3.create(sizeXY, sizeXY, Vec3.distance(aA.start, aA.end) * 0.9));
+            } else {
+                Mat4.scaleUniformly(t, t, size * getSymbolScale(symbol));
+            }
         } else {
             if (Vec3.dot(Vec3.unitY, Vec3.sub(tmpV, aA.end, aA.start)) === 0) {
                 Vec3.copy(up, Vec3.unitY);
@@ -283,7 +305,6 @@ function setSymbolTransform(t: Mat4, symbol: string, axes: AssemblySymmetry.Rota
                 const dirs = unitCircleDirections.map(d => Vec3.transformMat3(Vec3(), d, n));
                 sizeXY = getMaxProjectedDistance(sphere.extrema, dirs, sphere.center);
             }
-
             Mat4.scale(t, t, Vec3.create(sizeXY, sizeXY, size * 0.9));
         }
     }