Sfoglia il codice sorgente

tryAdjustBoundary tweaks

Alexander Rose 4 anni fa
parent
commit
845269e9a5
1 ha cambiato i file con 30 aggiunte e 9 eliminazioni
  1. 30 9
      src/mol-math/geometry/boundary.ts

+ 30 - 9
src/mol-math/geometry/boundary.ts

@@ -10,12 +10,14 @@ import { Vec3 } from '../linear-algebra';
 import { OrderedSet } from '../../mol-data/int';
 import { BoundaryHelper } from './boundary-helper';
 import { Box3D, Sphere3D } from '../geometry';
-import { EPSILON } from '../linear-algebra/3d/common';
+import { EPSILON, equalEps } from '../linear-algebra/3d/common';
 
 export type Boundary = { readonly box: Box3D, readonly sphere: Sphere3D }
 
 // avoiding namespace lookup improved performance in Chrome (Aug 2020)
 const v3set = Vec3.set;
+const v3copy = Vec3.copy;
+const v3distance = Vec3.distance;
 const v3squaredDistance = Vec3.squaredDistance;
 
 const boundaryHelperCoarse = new BoundaryHelper('14');
@@ -58,31 +60,50 @@ export function getBoundary(data: PositionData): Boundary {
     return { box: boundaryHelper.getBox(), sphere };
 }
 
+const extremPoint = Vec3();
 export function tryAdjustBoundary(data: PositionData, boundary: Boundary): Boundary | undefined {
     const { x, y, z, indices } = data;
     const n = OrderedSet.size(indices);
     const { center, radius } = boundary.sphere;
 
+    const threshold = (radius / 100) * 5;
+    const upper = radius + threshold;
+    const upperSq = upper * upper;
+
     let maxDistSq = 0;
     for (let t = 0; t < n; t++) {
         const i = OrderedSet.getAt(indices, t);
         v3set(p, x[i], y[i], z[i]);
         const distSq = v3squaredDistance(p, center);
-        if (distSq > maxDistSq) maxDistSq = distSq;
+        if (distSq > upperSq) return;
+
+        if (distSq > maxDistSq) {
+            maxDistSq = distSq;
+            v3copy(extremPoint, p);
+        }
     }
 
     const adjustedRadius = Math.sqrt(maxDistSq);
-    const deltaRadius = adjustedRadius - radius;
-    const absDeltaRadius = Math.abs(deltaRadius);
 
-    if (absDeltaRadius < EPSILON) {
+    if (equalEps(adjustedRadius, radius, EPSILON)) {
         return boundary;
-    } else if (absDeltaRadius < (radius / 100) * 5) {
-        // TODO: The expanded sphere extrema are not correct if the principal axes differ
+    } else if (equalEps(adjustedRadius, radius, threshold)) {
+        if (Sphere3D.hasExtrema(boundary.sphere)) {
+            let flag = false;
+            for (const e of boundary.sphere.extrema) {
+                if (v3distance(e, extremPoint) < threshold * 2) {
+                    flag = true;
+                    break;
+                }
+            }
+            if (!flag) return;
+        }
+
+        const deltaRadius = adjustedRadius - radius;
         const sphere = Sphere3D.expand(Sphere3D(), boundary.sphere, deltaRadius);
         const box = Box3D.fromSphere3D(Box3D(), sphere);
         return { box, sphere };
-    } else {
-        return undefined;
     }
+
+    return;
 }